Сравнение двух рисовалок в Android - PullRequest
85 голосов
/ 03 февраля 2012

Как сравнить два рисунка, я делаю так, но безуспешно

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

  if(fDraw.equals(sDraw))
  {
   //Not coming
  }
}

Ответы [ 12 ]

149 голосов
/ 20 декабря 2012

Обновление https://stackoverflow.com/a/36373569/1835650

getConstantState () работает не очень хорошо

Существует другой способ сравнения:

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

mRemeberPwd - это ImageView в этом примере.Если вы используете TextView, используйте getBackground().getConstantState.

35 голосов
/ 22 июля 2015

Использование только getConstantState() может привести к ложным отрицаниям .

. Подход, который я выбрал, заключается в том, чтобы сначала сравнить ConstantState, но использовать битовую картусравните, если эта проверка не удалась.

Это должно работать во всех случаях (включая изображения, которые не являются ресурсами), но обратите внимание, что это требует памяти.

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 - e.g. 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;
}
12 голосов
/ 03 февраля 2012

Мой вопрос был о том, чтобы просто сравнить две прорисовки, я пытался, но не смог получить какой-либо метод, который напрямую сравнивал бы две прорисовки, однако для своего решения я изменил прорисовку на растровую, а затем сравнил две растровые картинки, и это работает.

Bitmap bitmap = ((BitmapDrawable)fDraw).getBitmap();
Bitmap bitmap2 = ((BitmapDrawable)sDraw).getBitmap();

if(bitmap == bitmap2)
    {
        //Code blcok
    }
6 голосов
/ 13 мая 2015

для SDK 21+

это работает в SDK -21

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

для SDK +21 для Android 5. Установите идентификатор для рисования для просмотра изображений с тегом

img.setTag(R.drawable.xxx);

и сравните вот так

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

Это решение для тех, кто хочет сравнить drawable идентификатор imageview с идентификатором drawable.xxx.

4 голосов
/ 08 апреля 2015

Решение для Android 5:

 if(image.getDrawable().getConstantState().equals(image.getContext().getDrawable(R.drawable.something).getConstantState()))
3 голосов
/ 03 февраля 2012

возможно попробуйте это так:

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

  if(fDraw.hashCode() == sDraw.hashCode())
  {
   //Not coming
  }
}

или подготовьте метод, который принимает два аргумента drawable и возвращает логическое значениеВ этом методе вы можете преобразовать drawable в байты и сравнить,

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;
}
2 голосов
/ 19 июня 2017

Хорошо, я думаю, что нашел оптимальное решение для этого. Из-за AppCompat и друзей, предоставленный чертеж иногда раздувается в разных формах, поэтому недостаточно сделать getResources().getBitmap(R.drawable.my_awesome_drawable).

Итак, чтобы получить прорисовываемый экземпляр того же типа и формы, что и в представлении, можно сделать следующее:

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

Это полезно при выполнении тестов. Однако я не рекомендовал бы делать это в производстве. Если вам нужно, было бы желательно дополнительное кэширование, чтобы избежать чрезмерного отражения.

Для тестов Expresso вы можете использовать это довольно красиво:

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

или

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

Прежде чем вам нужно будет объявить этот вспомогательный класс:

public class CustomMatchers {

  public static Matcher<View> withDrawable(@DrawableRes final int drawableId) {
     return new DrawableViewMatcher(drawableId);
  }
  private static class DrawableViewMatcher extends TypeSafeMatcher<View> {

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

}
1 голос
/ 31 марта 2017

getDrawable (int) устарела. Используйте getDrawable (context, R.drawable.yourimageid)

Для сравнения двух фонов

Boolean Condition1=v.getBackground().getConstantState().equals(
ContextCompat.getDrawable(getApplicationContext(),R.drawable.***).getConstantState());
1 голос
/ 24 апреля 2012

Используйте getTag () и setTag () для сравнения

0 голосов
/ 21 марта 2018

Я уже ответил на аналогичную тему здесь: Получите ID отрисовки в ImageView .Подход основан на тегировании представления с указанным идентификатором ресурса в пользовательском LayoutInflater.Весь процесс автоматизирован простой библиотекой TagView .

. В результате вы можете сравнить два рисованных объекта по их идентификаторам:

TagViewUtils.getTag(view, ViewTag.VIEW_BACKGROUND.id) == R.drawable.twt_hover
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...