[英]Android : How to update the selector(StateListDrawable) programmatically
[英]Android: How to create a StateListDrawable programmatically
我有一個 GridView 來顯示一些對象,並且在視覺上每個對象都會有一個圖像圖標和一個文本 label。 我還希望圖像圖標在單擊時具有一些“推送和彈出”效果,即按下時,圖像將向右下方向移動一小段距離,釋放時返回其原始 position。
對象(及其圖像圖標)來自一些動態來源。 我的直覺是為每個項目創建一個 StateListDrawable,它將有兩種狀態:按下或不按下。 對於 GridView 項目視圖,我會使用一個按鈕,它可以容納一個 Drawable 和一個 label,完全滿足我的要求。
我定義了一個項目 class 來包裝原始 object:
public class GridItem<T> {
public static final int ICON_OFFSET = 4;
private StateListDrawable mIcon;
private String mLabel;
private T mObject;
public Drawable getIcon() {
return mIcon;
}
public void setIcon(Drawable d) {
if (null == d) {
mIcon = null;
}else if(d instanceof StateListDrawable) {
mIcon = (StateListDrawable) d;
} else {
InsetDrawable d1 = new InsetDrawable(d, 0, 0, ICON_OFFSET, ICON_OFFSET);
InsetDrawable d2 = new InsetDrawable(d, ICON_OFFSET, ICON_OFFSET, 0, 0);
mIcon = new StateListDrawable();
mIcon.addState(new int[] { android.R.attr.state_pressed }, d2);
mIcon.addState(StateSet.WILD_CARD, d1);
//This won't help either: mIcon.addState(new int[]{}, d1);
}
}
public String getLabel() {
return mLabel;
}
public void setLabel(String l) {
mLabel = l;
}
public T getObject() {
return mObject;
}
public void setObject(T o) {
mObject = o;
}
}
現在的問題是,當我觸摸一個網格項目時,圖標會像我預期的那樣“移動”,但是當我的手指抬起離開該項目時,它不會恢復其原始 position。
我的問題是:如何以編程方式創建一個 StateListDrawable 等效於從 XML 資源膨脹的一個
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true"
android:drawable="@drawable/image_pressed" />
<item android:drawable="@drawable/image_normal" />
</selector>
?
如果您的drawables只是位圖,您可以以編程方式繪制它們,現在它應該有所幫助,但是我想知道這里使用InsetDrawable
有什么問題,基本上使用以編程方式繪制的准備好的BitmapDrawables
,您需要修改您的方法以接受位圖b
Bitmap bc1 = Bitmap.createBitmap(b.getWidth() + ICON_OFFSET, b.getHeight() + ICON_OFFSET, Bitmap.Config.ARGB_8888);
Canvas c1 = new Canvas(bc1);
c1.drawBitmap(b, 0, 0, null);
Bitmap bc2 = Bitmap.createBitmap(b.getWidth() + ICON_OFFSET, b.getHeight() + ICON_OFFSET, Bitmap.Config.ARGB_8888);
Canvas c2 = new Canvas(bc2);
c2.drawBitmap(b, ICON_OFFSET, ICON_OFFSET, null);
mIcon = new StateListDrawable();
mIcon.addState(new int[] { android.R.attr.state_pressed }, new BitmapDrawable(bc2));
mIcon.addState(StateSet.WILD_CARD, new BitmapDrawable(bc1));
我可以看到答案已被接受。 如果您想從用戶那里動態分配 colors 按鈕,我將分享正常以及按下 state。 那么你可以直接調用這個 function:
public static StateListDrawable convertColorIntoBitmap(String pressedColor, String normalColor){
/*Creating bitmap for color which will be used at pressed state*/
Rect rectPressed = new Rect(0, 0, 1, 1);
Bitmap imagePressed = Bitmap.createBitmap(rectPressed.width(), rectPressed.height(), Config.ARGB_8888);
Canvas canvas = new Canvas(imagePressed);
int colorPressed = Color.parseColor(pressedColor);
Paint paintPressed = new Paint();
paintPressed.setColor(colorPressed);
canvas.drawRect(rectPressed, paintPressed);
RectF bounds = new RectF();
bounds.round(rectPressed);
/*Creating bitmap for color which will be used at normal state*/
Rect rectNormal = new Rect(0, 0, 1, 1);
Bitmap imageNormal = Bitmap.createBitmap(rectNormal.width(), rectNormal.height(), Config.ARGB_8888);
Canvas canvasNormal = new Canvas(imageNormal);
int colorNormal = Color.parseColor(normalColor);
Paint paintNormal = new Paint();
paintNormal.setColor(colorNormal);
canvasNormal.drawRect(rectNormal, paintNormal);
/*Now assigning states to StateListDrawable*/
StateListDrawable stateListDrawable= new StateListDrawable();
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new BitmapDrawable(imagePressed));
stateListDrawable.addState(StateSet.WILD_CARD, new BitmapDrawable(imageNormal));
return stateListDrawable;
}
現在您只需將其設置為 textview 或按鈕背景,如下所示:
if(android.os.Build.VERSION.SDK_INT>=16){
yourbutton.setBackground(convertColorIntoBitmap("#CEF6CE00","#4C9D32"));
}else{
yourbutton.setBackgroundDrawable(convertColorIntoBitmap("#CEF6CE00","#4C9D32"));
}
在這里,您可以看到動態傳遞 colors 所需的一切,我們就完成了。 希望這會對某人有所幫助:)你也可以在這里找到它的要點:)
我已經看到了以前的答案,但使用ColorDrawable
提出了一個更短更好的解決方案。
/**
* Get {@link StateListDrawable} given the {@code normalColor} and {@code pressedColor}
* for dynamic button coloring
*
* @param normalColor The color in normal state.
* @param pressedColor The color in pressed state.
* @return
*/
public static StateListDrawable getStateListDrawable(int normalColor, int pressedColor) {
StateListDrawable stateListDrawable = new StateListDrawable();
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, new ColorDrawable(pressedColor));
stateListDrawable.addState(StateSet.WILD_CARD, new ColorDrawable(normalColor));
return stateListDrawable;
}
這接受解析的 colors 作為 integer 並使用ColorDrawable
將它們添加到StateListDrawable
中。
一旦你有了drawable,你可以像這樣簡單地使用它,
if (android.os.Build.VERSION.SDK_INT >= 16) {
mButton.setBackground(Utils.getStateListDrawable(ResourceUtils.getColor(R.color.white),
ResourceUtils.getColor(R.color.pomegranate)));
} else {
mButton.setBackgroundDrawable(Utils.getStateListDrawable(ResourceUtils.getColor(R.color.white),
ResourceUtils.getColor(R.color.pomegranate)));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.