Сравнение двух рисовалок в Android
Как сравнить два рисунка, я делаю так, но безуспешно
public void MyClick(View view)
{
Drawable fDraw = view.getBackground();
Drawable sDraw = getResources().getDrawable(R.drawable.twt_hover);
if(fDraw.equals(sDraw))
{
//Not coming
}
}
15 ответов
Обновление /questions/34065181/sravnenie-resursov-v-dvuh-chertezhah/34065185#34065185
getConstantState () работает не хорошо
Есть еще один способ сравнения:
mRememberPwd.getDrawable().getConstantState().equals
(getResources().getDrawable(R.drawable.login_checked).getConstantState());
mRemeberPwd
является ImageView
в этом примере. Если вы используете TextView
использоватьgetBackground().getConstantState
вместо.
Надеется 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;
}
Мой вопрос состоял в том, чтобы просто сравнить две прорисовки, я попытался, но не смог получить метод, который напрямую сравнивал бы две прорисовки, однако для своего решения я изменил отрисовку на растровую, а затем сравнил две растровые картинки, и это работает.
Bitmap bitmap = ((BitmapDrawable)fDraw).getBitmap();
Bitmap bitmap2 = ((BitmapDrawable)sDraw).getBitmap();
if(bitmap == bitmap2)
{
//Code blcok
}
Для SDK 21+
это работает в SDK -21
mRememberPwd.getDrawable().getConstantState().equals
(getResources().getDrawable(R.drawable.login_checked).getConstantState())
для SDK +21 android 5. установить drawable id для просмотра изображений с тегом
img.setTag(R.drawable.xxx);
и сравнить, как это
if ((Integer) img.getTag() == R.drawable.xxx)
{
....your code
}
это решение для тех, кто хочет сравнить drawable
идентификатор imageview
с идентификатором drawable.xxx
,
getDrawable(int) теперь устарела. Используйте getDrawable(context,R.drawable.yourimageid)
Сравнить два фона
Boolean Condition1=v.getBackground().getConstantState().equals(
ContextCompat.getDrawable(getApplicationContext(),R.drawable.***).getConstantState());
Решение для Android 5:
if(image.getDrawable().getConstantState().equals(image.getContext().getDrawable(R.drawable.something).getConstantState()))
Возможно, попробуйте это так:
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 чертежа:
drawable1.constantState == drawable2.constantState
|| drawable1.toBitmap().sameAs(drawable2.toBitmap())
Если ты не можешь найти Drawable.toBitmap(...)
вот он Drawable.kt
Хорошо, я думаю, что нашел оптимальное решение для этого. Из-за 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);
}
}
}
}
Я уже ответил на аналогичную тему здесь: Получить ID Drawable в ImageView. Подход основан на тегировании представления с указанным идентификатором ресурса в пользовательском LayoutInflater
, Весь процесс автоматизирован простой библиотекой TagView.
В результате вы можете сравнивать два объекта рисования только по их идентификаторам:
TagViewUtils.getTag(view, ViewTag.VIEW_BACKGROUND.id) == R.drawable.twt_hover
полезный метод, собранный из второго пилота GitHub:
fun compareTwoDrawable(drawable1: Drawable, drawable2: Drawable): Boolean {
val bitmap1 = (drawable1 as BitmapDrawable).bitmap
val bitmap2 = (drawable2 as BitmapDrawable).bitmap
return bitmap1.sameAs(bitmap2)
}
Расширяя ответ от @vaughandroid, следующий Matcher работает для окрашенного Vector Drawable. Вы должны предоставить оттенок, который использовался для Drawable.
public static Matcher<View> compareVectorDrawables(final int imageId, final int tintId) {
return new TypeSafeMatcher<View>() {
@Override
protected boolean matchesSafely(View target) {
if (!(target instanceof ImageView)) {
return false;
}
ImageView imageView = (ImageView) target;
if (imageId < 0) {
return imageView.getDrawable() == null;
}
Resources resources = target.getContext().getResources();
Drawable expectedDrawable = resources.getDrawable(imageId, null);
if (expectedDrawable == null) {
return false;
}
Drawable imageDrawable = imageView.getDrawable();
ColorFilter imageColorFilter = imageDrawable.getColorFilter();
expectedDrawable.setColorFilter(imageColorFilter);
expectedDrawable.setTintList(target.getResources()
.getColorStateList(tintId, null));
boolean areSame = areDrawablesIdentical(imageDrawable, expectedDrawable);
return areSame;
}
public 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 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;
}
@Override
public void describeTo(Description description) {
}
};
}
Если вы хотите напрямую сравнить два рисуемых объекта, используйте следующий код
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.
}
Когда вы используете equals()
Метод используется для сравнения содержимого. тебе стоит попробовать ==
для сравнения двух объектов.
public void MyClick(View view)
{
Drawable fDraw = view.getBackground();
Drawable sDraw = getResources().getDrawable(R.drawable.twt_hover);
if( fDraw == sDraw )
{
// Coming
}
}