Comparando dos dibujables en Android

Cómo comparar dos objetos arrastrables, estoy haciendo esto pero sin éxito

public void MyClick(View view) { Drawable fDraw = view.getBackground(); Drawable sDraw = getResources().getDrawable(R.drawable.twt_hover); if(fDraw.equals(sDraw)) { //Not coming } } 

Actualice https://stackoverflow.com/a/36373569/1835650

getConstantState () no funciona bien

Hay otra forma de comparar:

 mRememberPwd.getDrawable().getConstantState().equals (getResources().getDrawable(R.drawable.login_checked).getConstantState()); 

mRemeberPwd es un ImageView en este ejemplo. Si está utilizando un TextView , use getBackground().getConstantState en getBackground().getConstantState lugar.

getConstantState() solo de getConstantState() puede getConstantState() falsos negativos .

El enfoque que he tomado es intentar comparar ConstantState en primera instancia, pero recurrir a una comparación de bitmap si falla la verificación.

Esto debería funcionar en todos los casos (incluidas las imágenes que no son recursos), pero tenga en cuenta que tiene mucha memoria.

 public static boolean areDrawablesIdentical(Drawable drawableA, Drawable drawableB) { Drawable.ConstantState stateA = drawableA.getConstantState(); Drawable.ConstantState stateB = drawableB.getConstantState(); // If the constant state is identical, they are using the same drawable resource. // However, the opposite is not necessarily true. return (stateA != null && stateB != null && stateA.equals(stateB)) || getBitmap(drawableA).sameAs(getBitmap(drawableB)); } public static Bitmap getBitmap(Drawable drawable) { Bitmap result; if (drawable instanceof BitmapDrawable) { result = ((BitmapDrawable) drawable).getBitmap(); } else { int width = drawable.getIntrinsicWidth(); int height = drawable.getIntrinsicHeight(); // Some drawables have no intrinsic width - eg solid colours. if (width <= 0) { width = 1; } if (height <= 0) { height = 1; } result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(result); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); } return result; } 

Mi pregunta era solo por comparar dos diseños, intenté pero no pude obtener ningún método que compare directamente dos diseños, sin embargo, para mi solución, cambié dibujable a bitmap y luego comparé dos mapas de bits y eso está funcionando.

 Bitmap bitmap = ((BitmapDrawable)fDraw).getBitmap(); Bitmap bitmap2 = ((BitmapDrawable)sDraw).getBitmap(); if(bitmap == bitmap2) { //Code blcok } 

La solución para Android 5:

  if(image.getDrawable().getConstantState().equals(image.getContext().getDrawable(R.drawable.something).getConstantState())) 

para SDK 21+

esto funciona en SDK -21

 mRememberPwd.getDrawable().getConstantState().equals (getResources().getDrawable(R.drawable.login_checked).getConstantState()) 

para SDK +21 android 5. establecer id dibujable a la vista de imagen con la etiqueta

 img.setTag(R.drawable.xxx); 

y comparar así

 if ((Integer) img.getTag() == R.drawable.xxx) { ....your code } 

esta solución es para quienes desean comparar el ID imageview de la imageview de la imageview con el ID de drawable.xxx .

quizás intente de esta manera:

 public void MyClick(View view) { Drawable fDraw = view.getBackground(); Drawable sDraw = getResources().getDrawable(R.drawable.twt_hover); if(fDraw.hashCode() == sDraw.hashCode()) { //Not coming } } 

o prepare un método que tome dos argumentos dibujables y devuelva booleano. En ese método, puede convertir dibujables en bytes y comparar,

 public boolean compareDrawable(Drawable d1, Drawable d2){ try{ Bitmap bitmap1 = ((BitmapDrawable)d1).getBitmap(); ByteArrayOutputStream stream1 = new ByteArrayOutputStream(); bitmap1.compress(Bitmap.CompressFormat.JPEG, 100, stream1); stream1.flush(); byte[] bitmapdata1 = stream1.toByteArray(); stream1.close(); Bitmap bitmap2 = ((BitmapDrawable)d2).getBitmap(); ByteArrayOutputStream stream2 = new ByteArrayOutputStream(); bitmap2.compress(Bitmap.CompressFormat.JPEG, 100, stream2); stream2.flush(); byte[] bitmapdata2 = stream2.toByteArray(); stream2.close(); return bitmapdata1.equals(bitmapdata2); } catch (Exception e) { // TODO: handle exception } return false; } 

Ok, creo que he encontrado la mejor solución para esto. Debido a AppCompat y sus amigos, el dibujo disponible a veces se infla en diferentes formas, por lo que no es suficiente hacer getResources().getBitmap(R.drawable.my_awesome_drawable) .

Entonces, para obtener una instancia dibujable del mismo tipo y forma que la vista, se puede hacer esto:

 public static Drawable drawableFrom(View view, @DrawableRes int drawableId) { Context context = view.getContext(); try { View dummyView = view.getClass().getConstructor(Context.class).newInstance(context); dummyView.setBackgroundResource(drawableId); return dummyView.getBackground(); } catch (Exception e) { return ResourcesCompat.getDrawable(context.getResources(), drawableId, null); } } 

Esto es útil al hacer pruebas. Sin embargo, no recomendaría hacer esto en producción. Si es necesario, sería deseable el almacenamiento en caché adicional para evitar hacer demasiada reflexión.

Para las pruebas de Expresso puedes usar esto bastante bien:

 onView(withDrawable(R.drawable.awesome_drawable)) .check(matches(isDisplayed())); 

o

 onView(withId(R.id.view_id)) .check(matches(withDrawable(R.drawable.awesome_drawable))); 

Antes tendrás que declarar esta clase de ayuda:

 public class CustomMatchers { public static Matcher withDrawable(@DrawableRes final int drawableId) { return new DrawableViewMatcher(drawableId); } private static class DrawableViewMatcher extends TypeSafeMatcher { private final int expectedId; private String resourceName; private enum DrawableExtractionPolicy { IMAGE_VIEW { @Override Drawable findDrawable(View view) { return view instanceof ImageView ? ((ImageView) view).getDrawable() : null; } }, TEXT_VIEW_COMPOUND { @Override Drawable findDrawable(View view) { return view instanceof TextView ? findFirstCompoundDrawable((TextView) view) : null; } }, BACKGROUND { @Override Drawable findDrawable(View view) { return view.getBackground(); } }; @Nullable private static Drawable findFirstCompoundDrawable(TextView view) { for (Drawable drawable : view.getCompoundDrawables()) { if (drawable != null) { return drawable; } } return null; } abstract Drawable findDrawable(View view); } private DrawableViewMatcher(@DrawableRes int expectedId) { this.expectedId = expectedId; } @Override protected boolean matchesSafely(View view) { resourceName = resources(view).getResourceName(expectedId); return haveSameState(actualDrawable(view), expectedDrawable(view)); } private boolean haveSameState(Drawable actual, Drawable expected) { return actual != null && expected != null && areEqual(expected.getConstantState(), actual.getConstantState()); } private Drawable actualDrawable(View view) { for (DrawableExtractionPolicy policy : DrawableExtractionPolicy.values()) { Drawable drawable = policy.findDrawable(view); if (drawable != null) { return drawable; } } return null; } private boolean areEqual(Object first, Object second) { return first == null ? second == null : first.equals(second); } private Drawable expectedDrawable(View view) { return drawableFrom(view, expectedId); } private static Drawable drawableFrom(View view, @DrawableRes int drawableId) { Context context = view.getContext(); try { View dummyView = view.getClass().getConstructor(Context.class).newInstance(context); dummyView.setBackgroundResource(drawableId); return dummyView.getBackground(); } catch (Exception e) { return ResourcesCompat.getDrawable(context.getResources(), drawableId, null); } } @NonNull private Resources resources(View view) { return view.getContext().getResources(); } @Override public void describeTo(Description description) { description.appendText("with drawable from resource id: "); description.appendValue(expectedId); if (resourceName != null) { description.appendValueList("[", "", "]", resourceName); } } } } 

Use getTag () y setTag () para comparar

getDrawable (int) ahora está en desuso. Use getDrawable (context, R.drawable.yourimageid)

Para comparar dos fondos

 Boolean Condition1=v.getBackground().getConstantState().equals( ContextCompat.getDrawable(getApplicationContext(),R.drawable.***).getConstantState()); 

Ya respondí sobre el tema similar aquí: Obtener la ID de un dibujable en ImageView . El enfoque se basa en etiquetar una vista con una identificación de recurso especificada en el LayoutInflater personalizado. Todo el proceso está automatizado por una biblioteca simple TagView .

Como resultado, puede comparar dos objetos arrastrables solo por sus ids:

 TagViewUtils.getTag(view, ViewTag.VIEW_BACKGROUND.id) == R.drawable.twt_hover 

si desea comparar directamente dos dibujables, utilice el siguiente código

Drawable fDraw = getResources (). GetDrawable (R.drawable.twt_hover);

Drawable sDraw = getResources (). GetDrawable (R.drawable.twt_hover);

 if (fDraw.getConstantState().equals(sDraw.getConstantState())) { //write your code. } else { //write your code. } 

Cuando usa el método equals() , se usa para comparar los contenidos. deberías probar == para comparar dos objetos.

 public void MyClick(View view) { Drawable fDraw = view.getBackground(); Drawable sDraw = getResources().getDrawable(R.drawable.twt_hover); if( fDraw == sDraw ) { // Coming } }