如何比较两个可绘制对象,我这样做却没有成功
public void MyClick(View view)
{
Drawable fDraw = view.getBackground();
Drawable sDraw = getResources().getDrawable(R.drawable.twt_hover);
if(fDraw.equals(sDraw))
{
//Not coming
}
}
如何比较两个可绘制对象,我这样做却没有成功
public void MyClick(View view)
{
Drawable fDraw = view.getBackground();
Drawable sDraw = getResources().getDrawable(R.drawable.twt_hover);
if(fDraw.equals(sDraw))
{
//Not coming
}
}
Answers:
更新 https://stackoverflow.com/a/36373569/1835650
getConstantState()效果不佳
还有另一种比较方法:
mRememberPwd.getDrawable().getConstantState().equals
(getResources().getDrawable(R.drawable.login_checked).getConstantState());
mRemeberPwd是ImageView在本实施例中。如果您使用TextView,请getBackground().getConstantState改用。
依靠getConstantState()单独可导致假阴性。
我采用的方法是尝试在第一个实例中比较ConstantState,但是如果该检查失败,则退回到Bitmap比较中。
这在所有情况下都应适用(包括不是资源的图像),但请注意,这会占用大量内存。
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;
}
getConstantState()比较之前,请使用已知的Drawables测试您的代码
我的问题是只比较两个可绘制对象,我试过但无法获得直接比较两个可绘制对象的任何方法,但是对于我的解决方案,我将可绘制对象更改为位图,然后比较两个位图,这是可行的。
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.将带有标签的可绘制ID设置为imageview
img.setTag(R.drawable.xxx);
并像这样比较
if ((Integer) img.getTag() == R.drawable.xxx)
{
....your code
}
此解决方案适用于谁希望将drawableID imageview与的ID 进行比较drawable.xxx。
Android 5解决方案:
if(image.getDrawable().getConstantState().equals(image.getContext().getDrawable(R.drawable.something).getConstantState()))
getDrawable(int)现在已弃用。使用 getDrawable(context,R.drawable.yourimageid)
比较两个背景
Boolean Condition1=v.getBackground().getConstantState().equals(
ContextCompat.getDrawable(getApplicationContext(),R.drawable.***).getConstantState());
context.getResources().getDrawable(R.drawable.***)在Android 6+上返回,但在Android 5上却没有。通过这一小的更改,我可以完美地比较所有Android版本的背景drawable
也许可以这样尝试:
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转换为字节并进行比较,
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;
}
e.g R.drawable.abc为两个参数传递相同的drawable ?
好的,我想我已经找到了最终的解决方案。由于AppCompat和朋友的关系,所提供的drawable有时会以不同的形式膨胀,因此这样做还不够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);
}
}
}
}
使用getTag()和setTag()进行比较
我已经在这里回答了类似的主题:在ImageView中获取可绘制的ID。该方法基于在custom中用指定的资源ID标记视图LayoutInflater。整个过程由一个简单的TagView库自动化。
结果,您可以仅通过两个ID对其进行比较:
TagViewUtils.getTag(view, ViewTag.VIEW_BACKGROUND.id) == R.drawable.twt_hover
通过扩展@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) {
}
};
}
比较2个可绘制对象:
drawable1.constantState == drawable2.constantState
|| drawable1.toBitmap().sameAs(drawable2.toBitmap())
如果您Drawable.toBitmap(...)在这里找不到,它是Drawable.kt
如果要直接比较两个可绘制对象,则使用以下代码
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
}
}