studio programación programacion herramientas gratis fundamentos curso crear con avanzado aplicaciones android statelist

programación - manual android studio avanzado



Android: Cómo crear un StateListDrawable mediante programación (3)

He visto las respuestas anteriores, pero se me ocurrió una solución mucho más corta y mejor usando 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; }

Acepta colores resueltos como un número entero y usa ColorDrawable para agregarlos en un StateListDrawable .

Una vez que tenga el dibujable, puede usarlo simplemente así,

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))); }

Tengo un GridView para mostrar algunos objetos, y visualmente cada uno de los objetos tendrá un icono de imagen y una etiqueta de texto. También quiero que el ícono de la imagen tenga algún efecto "push and pop" cuando se hace clic, es decir, cuando se presiona, la imagen se moverá una pequeña distancia en la dirección inferior derecha, y cuando se libere volverá a su posición original.

Los objetos (y sus iconos de imagen) provienen de algunas fuentes dinámicas. Mi intuición es crear un StateListDrawable para cada elemento, que tendrá dos estados: presionado o no. Para la vista de elementos de GridView, usaría un botón, que puede acomodar un Drawable y una etiqueta, que satisfaga perfectamente mi requerimiento.

Definí una clase de elemento para concluir el objeto original:

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; } }

Ahora el problema es que, cuando toco un elemento de la cuadrícula, el ícono "se mueve" bastante como esperaba, pero no restaurará su posición original cuando mi dedo se levante dejando el ítem.

Mi pregunta es: cómo crear programáticamente un StateListDrawable equivalente a uno inflado de un recurso XML como

<?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>

?


Puedo ver que la respuesta ya está aceptada. Lo estoy compartiendo si desea asignar dinámicamente colores de botones de los usuarios para el estado normal y el estado presionado. entonces puedes simplemente llamar a esta función:

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; }

Ahora todo lo que necesita es configurarlo como su vista de texto o fondo de botón como se muestra a continuación:

if(android.os.Build.VERSION.SDK_INT>=16){ yourbutton.setBackground(convertColorIntoBitmap("#CEF6CE00","#4C9D32")); }else{ yourbutton.setBackgroundDrawable(convertColorIntoBitmap("#CEF6CE00","#4C9D32")); }

Aquí puede ver todo lo que necesita para pasar los colores de forma dinámica y hemos terminado. Espero que esto ayude a alguien :) Puedes encontrarlo here también :)


Si tus dibujables son solo mapas de bits, podrías dibujarlos programáticamente, por ahora debería ser útil. Sin embargo, me pregunto cuál es el problema con el uso de InsetDrawable aquí, básicamente utilizo BitmapDrawables preparados que se dibujan programáticamente. BitmapDrawables que modificar tu método para aceptar bitmaps. 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));