Android:为了使用filter创build一个StateListDrawable,克隆一个drawable

我试图做一个通用的框架function,使任何可绘制成为突出显示时按/聚焦/select/等

我的函数需要一个Drawable并返回一个StateListDrawable,其中默认状态是Drawable本身, android.R.attr.state_pressed的状态是可绘制的,只是使用setColorFilter应用了一个filter。

我的问题是,我不能克隆drawable,并应用filter的一个单独的实例。 这是我想要实现的:

 StateListDrawable makeHighlightable(Drawable drawable) { StateListDrawable res = new StateListDrawable(); Drawable clone = drawable.clone(); // how do I do this?? clone.setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY); res.addState(new int[] {android.R.attr.state_pressed}, clone); res.addState(new int[] { }, drawable); return res; } 

如果我不克隆,那么filter显然应用于两种状态。 我尝试玩mutate()但它没有帮助..

有任何想法吗?

更新:

被接受的答案确实克隆了一个drawable。 它并没有帮助我,虽然因为我的一般function失败了一个不同的问题。 看起来,当你将一个drawable添加到一个StateList时,它将失去所有的filter。

尝试以下操作:

 Drawable clone = drawable.getConstantState().newDrawable(); 

如果将filter/ etc应用于使用getConstantState().newDrawable()创build的drawable, getConstantState().newDrawable()则该drawable的所有实例都将被更改,因为drawable使用constantState作为caching!

所以如果你用彩色滤镜和newDrawable给一个圆圈着色,你将改变所有圆圈的颜色。

如果你想得到这个可绘制的可更新而不影响其他实例,那么你必须改变现有的常量状态。

 // To make a drawable use a separate constant state drawable.mutate() 

有一个很好的解释,请看:

http://www.curious-creature.org/2009/05/02/drawable-mutations/

http://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate();

这是我的解决scheme,基于此代码: https : //stackoverflow.com/a/6071813/2075875 。 这个想法是,当用户触摸它时,ImageView会获取颜色filter,当用户停止触摸时,将会移除颜色filter。 内存中只有1个drawable / bitmap,所以不需要浪费它。 它的工作原理应该如此。

 class PressedEffectStateListDrawable extends StateListDrawable { private int selectionColor; public PressedEffectStateListDrawable(Drawable drawable, int selectionColor) { super(); this.selectionColor = selectionColor; addState(new int[] { android.R.attr.state_pressed }, drawable); addState(new int[] {}, drawable); } @Override protected boolean onStateChange(int[] states) { boolean isStatePressedInArray = false; for (int state : states) { if (state == android.R.attr.state_pressed) { isStatePressedInArray = true; } } if (isStatePressedInArray) { super.setColorFilter(selectionColor, PorterDuff.Mode.MULTIPLY); } else { super.clearColorFilter(); } return super.onStateChange(states); } @Override public boolean isStateful() { return true; } } 

用法:

 Drawable drawable = new FastBitmapDrawable(bm); imageView.setImageDrawable(new PressedEffectStateListDrawable(drawable, 0xFF33b5e5)); 

这对我有用。

 Drawable clone = drawable.getConstantState().newDrawable().mutate(); 

我在这里回答了一个相关问题

基本上看起来像StateListDrawables确实失去了他们的filter。 我创build了一个新的BitmapDrawale从我原本想使用的位图的改变的副本。