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从我原本想使用的位图的改变的副本。