एंड्रॉइड में दो ड्रॉबल्स की तुलना करना


90

दो ड्रॉबल्स की तुलना कैसे करें, मैं इस तरह से कर रहा हूं लेकिन कोई सफलता नहीं है

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

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

जवाबों:


150

अपडेट https://stackoverflow.com/a/36373569/1835650

getConstantState () अच्छी तरह से काम नहीं करता है

तुलना करने का एक और तरीका है:

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

mRemeberPwdएक है ImageViewइस उदाहरण में। यदि आप उपयोग कर रहे हैं TextView, तो getBackground().getConstantStateइसके बजाय उपयोग करें ।


3
यह समाधान काम करता है और इसकी बेहतर है क्योंकि यह ड्राएबल को बिटमैप में परिवर्तित करने से बचता है और तुलना करता है।
— ब्रज

2
हमेशा नहीं: WallpaperManager.getInstance (यह) .getFastDrawable ()। GetConstantState () शून्य है।
— पौलगाव्रिकोव

इसे उत्तर के रूप में स्वीकार करने और अपने स्वयं के उत्तर को बदलने के लिए खेद है क्योंकि यह बेहतर विकल्प लगता है (और अधिक upvotes भी :))। तो यह उत्तर के रूप में जाँच कर रहा है।
— रोशन झा

धन्यवाद, यह सबसे अच्छा जवाब है
— व्यंग्य

8
यह कोड 5.0 से कम उपकरणों पर बहुत अच्छा काम करता है, लेकिन 5.0 डिवाइस पर इसका उपयोग करने में त्रुटियाँ हो रही हैं, क्या कोई इस विधि की पुष्टि करता है कि यह एंड्रॉइड 5.0 या उच्चतर पर काम करता है या नहीं
— Phil3992

41

getConstantState()अकेले पर भरोसा करने से झूठे नकारात्मक परिणाम हो सकते हैं ।

जिस दृष्टिकोण को मैंने लिया है, वह पहली बार में कॉन्स्टैंटस्टैट की तुलना करने की कोशिश करना है, लेकिन यदि वह चेक विफल हो जाता है तो बिटमैप तुलना पर वापस गिर जाता है।

यह सभी मामलों में काम करना चाहिए (छवियों में जो संसाधन नहीं हैं) लेकिन ध्यान दें कि यह मेमोरी भूख है।

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

यह 100% सच है और अधिक upvotes की जरूरत है! लोग, getConstantState()तुलना करने पर तुरंत भरोसा करने से पहले ज्ञात कोडेबलों के साथ अपने कोड का परीक्षण करें
— avalancha

अच्छा निष्कर्ष! लेकिन BitmapDrawable.getBitmap (), getBitmap () के प्रलेखन के अनुसार अशक्त हो सकता है तो आप भी इस जांच करना चाह सकते
— PhilLab

यह उत्तर सही है और मैंने जाँच की है कि केवल getConstantState () के कोडिंग के साथ कई घंटे डिबग करने के बाद।
— राघव सत्यदेव

सुरक्षा के लिए, setBoundsऔर drawमूल के बजाय एक प्रति पर stackoverflow.com/a/25462223/1916449
— arekolek

यह टिंटेड BitmapDrawables के साथ काम नहीं करता है (setTintMode / setTint / setTintList देखें)। बिटमैप्स बाइट के लिए समान बाइट हो सकते हैं लेकिन विभिन्न टिंट गुणों के साथ। क्योंकि एंड्रॉइड एसडीके टिंट संपत्तियों के लिए कोई गेटर्स प्रदान नहीं करता है, इसलिए टिंट ड्रॉबल्स के साथ काम करने का कोई तरीका नहीं हो सकता है।
— थियो

13

मेरा प्रश्न सिर्फ दो ड्रॉबल्स की तुलना करने के लिए था, मैंने कोशिश की लेकिन कोई भी ऐसा तरीका नहीं मिला जो सीधे दो ड्रॉबल्स की तुलना कर सके, हालाँकि मेरे समाधान के लिए मैंने बिटमैप के लिए ड्रॉबल को बदल दिया और फिर दो बिटमैप्स की तुलना की और वह काम कर रहा है।

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

if(bitmap == bitmap2)
    {
        //Code blcok
    }

Thats मैं तुम्हें क्या सुझाव दे रहा था, drawable के प्रकार के अनुसार drawable की तुलना करने के लिए।
— जेईटी

1
आप इस तरह से बिटमैप्स की तुलना करना चाहते हैं: stackoverflow.com/a/7696320/317889
— HGPB

2
यह बहुत भारी है, इसलिए बिटमैप को पुनर्चक्रण करने पर विचार करें या आप एक आउटऑफमेरीरोर में समाप्त हो जाएंगे!
— पौलगाव्रिकोव

2
आप Bitmaps की तुलना सूचक समानता (==) से क्यों कर सकते हैं? मुझे उम्मीद है कि Bitmap.equals () की आवश्यकता होगी।
— एलेन स्पर्टस

@ एस्परटस आप सही कह रहे हैं। मैं आरेखण योग्य वस्तुओं के लिए प्रश्न में एक ही इस्तेमाल किया है पता नहीं क्यों जवाब में बिटमैप ऑब्जेक्ट के लिए == में बदल गया। इस मूल को इंगित करने के लिए कोई भी तरीका धन्यवाद।
— रोशन झा

9

एसडीके 21+ के लिए

यह एसडीके -21 में काम करता है

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

एसडीके + १.० एंड्रॉइड के लिए 5. टैग के साथ इमेजव्यू के लिए ड्रा करने योग्य आईडी सेट करें

img.setTag(R.drawable.xxx);

और इस तरह की तुलना करें

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

यह समाधान उन लोगों के लिए है जो drawableआईडी के imageviewसाथ आईडी की तुलना करना चाहते हैं drawable.xxx।


वास्तव में यह काम करता है लेकिन मैं इस तरह से हैरान हूं कि कोई और संभावना नहीं है T_T!
— एरर 1337


4

getDrawable (int) अब डिप्रेस्ड हो गया है । GetDrawable का उपयोग करें (संदर्भ, R.drawable.yourimageid)

दो पृष्ठभूमि की तुलना करने के लिए

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

2
यह एंड्रॉइड 5 पर एक अजीब बग को ठीक करने के लिए एक आकर्षण की तरह काम करता है। मेरे कोड में, वास्तविक ड्रा करने योग्य context.getResources().getDrawable(R.drawable.***)एंड्रॉइड 6+ के साथ वापस आ गया था, लेकिन एंड्रॉइड 5 पर नहीं था। इस छोटे से बदलाव के साथ मैं सभी एंड्रॉइड वर्जन के बैकग्राउंड ड्रॉबल्स की त्रुटिपूर्ण तुलना कर सकता हूं
— जोस_जीडी

3

शायद इस तरह से कोशिश करें:

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

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

या एक विधि तैयार करें जो दो ड्रॉबल तर्कों और रिटर्न बूलियन ले। उस पद्धति में आप ड्रा करने योग्य को बाइट्स में बदल सकते हैं और तुलना कर सकते हैं,

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 परिवर्तित कर रहा हूं और फिर दो बिटमैप की तुलना कर रहा हूं और यह काम कर रहा है।
— रोशन झा

2

ठीक है, मुझे लगता है कि मैंने इसके लिए अंतिम समाधान ढूंढ लिया है। 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);
    }
}

परीक्षण करते समय यह उपयोगी है। हालांकि, मैं उत्पादन में ऐसा करने की सिफारिश नहीं करूंगा। यदि आप की जरूरत है, तो बहुत अधिक प्रतिबिंब करने से बचने के लिए अतिरिक्त कैशिंग करना वांछनीय होगा।

एक्सप्रेसो परीक्षणों के लिए आप इसका काफी अच्छी तरह से उपयोग कर सकते हैं:

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

}


0

मैंने पहले से ही इसी तरह के विषय पर यहां उत्तर दिया था: ImageView में एक ड्रॉबल की आईडी प्राप्त करें । दृष्टिकोण कस्टम में एक निर्दिष्ट संसाधन आईडी के साथ एक दृश्य को टैग करने पर आधारित है LayoutInflater। संपूर्ण प्रक्रिया एक साधारण लाइब्रेरी टैगव्यू द्वारा स्वचालित है ।

नतीजतन, आप केवल दो आईडी की तुलना उनके आईडी से कर सकते हैं:

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

0

@Vaughandroid से उत्तर पर विस्तार करने वाला निम्नलिखित मिलान वेक्टर ड्रिबल के लिए काम करता है जो कि रंगा हुआ है। आपको टिंट प्रदान करना होगा जो कि ड्रॉएबल के लिए उपयोग किया गया था।

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) {

        }
    };
}

0

2 दराज की तुलना करें:

drawable1.constantState == drawable2.constantState
            || drawable1.toBitmap().sameAs(drawable2.toBitmap())

आप बंद हो जाए तो Drawable.toBitmap(...)ये रहा Drawable.kt


-1

अगर आप सीधे दो ड्रॉबल की तुलना करना चाहते हैं तो निम्न कोड का उपयोग करें

आकर्षित करने योग्य fDraw = getResource ()। GetDrawable (R.drawable.twt_hover);

आकर्षित करने योग्य sDraw = getResource ()। GetDrawable (R.drawable.twt_hover);

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

-2

जब आप equals()विधि का उपयोग कर रहे हैं तो इसका उपयोग सामग्री की तुलना करने के लिए किया जाता है। आपको ==दो वस्तुओं की तुलना करने का प्रयास करना चाहिए ।

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

  if( fDraw == sDraw )
  {
   // Coming
  }
}

तब यह संभव हो सकता है कि वे == नहीं हैं, वे हैं! =
— लूसिफ़ेर

लेकिन वे संसाधनों से एक ही छवि का उल्लेख करते हैं
— रोशन झा

मुझे सिर्फ यह जाँचने की आवश्यकता है कि वे समान हैं या नहीं? उसके लिए कोई विधि उपलब्ध नहीं है?
— रोशन झा

फिर, मुझे आपकी आवश्यकता हुई, कृपया चैट रूम में आएँ
— लूसिफ़ेर

1
== तुलना अगर यह एक ही वस्तु है, जो यह n 99.99999999% समय नहीं है।
— पौलगाव्रिकोव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.