অ্যান্ড্রয়েডে দুটি ড্রয়যোগ্য তুলনা করা


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পরিবর্তে ব্যবহার করুন।


4
ড্রয়াবলকে বিটম্যাপে রূপান্তর করা এবং তুলনা করা এড়ানোর কারণে এই সমাধানটি আরও ভাল কাজ করে।
ব্রজ

4
সর্বদা নয়: ওয়ালপেপার ম্যানেজ.জেটআইনস্ট্যান্স (এটি) .getFastDrawable ()। GetConstantState () নাল।
পলগাগ্রিকভ

এটিকে উত্তর হিসাবে দেরি করে গ্রহণ করার জন্য এবং আমার নিজের উত্তর পরিবর্তন করার জন্য দুঃখিত কারণ এটি আরও ভাল বিকল্প বলে মনে হচ্ছে (এবং আরও উন্নতিও :))। সুতরাং উত্তর হিসাবে এটি চেক।
রওশন ঝা

ধন্যবাদ, এটি সেরা উত্তর
ধীরগতি

8
এই কোডটি 5.0 এর চেয়ে কম ডিভাইসগুলিতে দুর্দান্ত কাজ করে তবে 5.0 ডিভাইসে এটি ব্যবহার করে ত্রুটি পাচ্ছে, যে কেউ এই পদ্ধতিটি অ্যান্ড্রয়েড 5.0 বা তার বেশি বা তার উপর কাজ করে না তা নিশ্চিত করতে পারে
ফিল3992

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% সত্য এবং আরও উন্নত প্রয়োজন! মানুষ, অবিলম্বে জানানোর আগে পরিচিত drawables সঙ্গে আপনার কোড পরীক্ষা দয়া getConstantState()তুলনা
avalancha

ভাল অনুসন্ধান! কিন্তু বিটম্যাপড্রেবল.সেটবিটম্যাপ () এর ডকুমেন্টেশন অনুসারে getBitmap () নাল হতে পারে তাই আপনি
এটিও

এই উত্তরটি সত্য এবং আমি কেবল getConstantState () এর কোডিংয়ের সাথে কয়েক ঘন্টা ডিবাগ করার পরে পরীক্ষা করে দেখেছি।
রাঘব সত্যদেব 11'17

নিরাপদ হতে, setBoundsএবং drawমূল পরিবর্তে একটি কপি উপর stackoverflow.com/a/25462223/1916449
arekolek

এটি টিন্টেড বিটম্যাপড্রেইবলগুলি (সেটটিন্টমোড / সেটটিন্ট / সেটটিন্টলিস্ট দেখুন) দিয়ে কাজ করে না। বিটম্যাপগুলি বাইটের জন্য অভিন্ন বাইট হতে পারে তবে বিভিন্ন রঙিন বৈশিষ্ট্য সহ। যেহেতু অ্যান্ড্রয়েড এসডিকে টিন্টের বৈশিষ্ট্যগুলির জন্য কোনও জেটর সরবরাহ করে না, এটির জন্য রঙিন ড্রয়যোগ্যদের সাথে কাজ করার কোনও উপায় নেই।
থিও

13

আমার প্রশ্নটি কেবলমাত্র দুটি ড্রএবলের সাথে তুলনা করার জন্য ছিল, আমি চেষ্টা করেছি কিন্তু এমন কোনও পদ্ধতি পেলাম না যা সরাসরি দুটি ড্রয়েবলের সাথে সরাসরি তুলনা করতে পারে, তবে আমার সমাধানের জন্য আমি বিটম্যাপে ড্রয়যোগ্য পরিবর্তন করেছি এবং তারপরে দুটি বিটম্যাপের তুলনা করছি এবং এটি কাজ করছে।

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

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

আমি আপনাকে যা পরামর্শ দিচ্ছিলাম তা ড্রয়কের ধরণ অনুযায়ী আঁকতে তুলনা করতে।
জীট

4
: আপনি মত এই বিটম্যাপ তুলনা করতে চাইতে পারেন stackoverflow.com/a/7696320/317889
HGPB

4
এটি খুব ভারী, সুতরাং বিটম্যাপগুলি পুনর্ব্যবহার করার বিষয়টি বিবেচনা করুন বা আপনি একটি আউটআফমিউরিওর এ শেষ করবেন!
পলগাগ্রিকভ

4
আপনি কেন বিটম্যাপের সাথে পয়েন্টার সমতার (==) তুলনা করতে পারেন? আমি Bitmap.equals () প্রয়োজন হবে আশা করি।
এলেন স্পারটাস

@espertus আপনি ঠিক বলেছেন অঙ্কনযোগ্য অবজেক্টের জন্য আমি প্রশ্নে একই রকম ব্যবহার করেছি কারণ জানে বিটম্যাপ অবজেক্টের জন্য কেন == পরিণত হয়েছে know এই বেসিকটি নির্দেশ করার জন্য যে কোনও উপায়ে ধন্যবাদ।
রওশন ঝা

9

এসডিকে 21+ এর জন্য

এটি এসডিকে -21 এ কাজ করে

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

এসডিকে +21 অ্যান্ড্রয়েডের জন্য 5. ট্যাগ সহ চিত্রকল্পে অঙ্কনযোগ্য আইডি সেট করুন

img.setTag(R.drawable.xxx);

এবং এই মত তুলনা করুন

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

এই সমাধানটি আইডিটির সাথে যারা drawableআইডি তুলনা করতে চান তাদের imageviewজন্য drawable.xxx


আসলে এটি কাজ করে তবে আমি ধাক্কা খেয়েছি কেন অন্য কোনও সম্ভাবনা নেই টি টি টি!
ত্রুটি 1337


4

getDrawable (int) এখন হ্রাস করা হয়েছেGetDrawable ব্যবহার করুন (প্রসঙ্গ, আর। ডিআরওয়েবল.ইউরিজিমেড)

দুটি পটভূমি তুলনা করতে

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

4
এটি অ্যান্ড্রয়েড 5. এ একটি বিজোড় বাগ ঠিক করার জন্য একটি কবজির মতো কাজ করেছে In আমার কোডে, আসল অঙ্কনযোগ্যটি context.getResources().getDrawable(R.drawable.***)অ্যান্ড্রয়েড ++ এ ফিরে এসেছিল তবে অ্যান্ড্রয়েডে ছিল না this এই সামান্য পরিবর্তনের মাধ্যমে আমি সমস্ত অ্যান্ড্রয়েড সংস্করণে নির্বিঘ্নে ব্যাকগ্রাউন্ড ড্রয়েবলের তুলনা করতে পারি
জোসে_জিডি

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উভয় পরামিতি হিসাবে একই আঁকিয়ে যাওয়ার চেষ্টা করেছেন ?
ওয়াকসলাম

হ্যালো ওয়াকাস, আপনার পদ্ধতিটি আবার একবার যাচাই করুন এবং তারপরে আবার বলুন এটি কাজ করছে কিনা তা সম্ভবত সম্ভব হতে পারে যে আমি কিছু ভুল করছি কিন্তু এটি কার্যকর হয়নি, তবে এটি আমার প্রশ্নের সংজ্ঞা পরিবর্তন করে যে কীভাবে দুটি অঙ্কনযোগ্যকে তুলনা করতে পারি। পরিবর্তন বিটম্যাপে আঁকতে সক্ষম এবং তারপরে বাইটগুলি বিটম্যাপ এবং বাইটগুলি আমার প্রয়োজনের তুলনায় তুলনামূলকভাবে তুলনা করবে if যদি আমরা অঙ্কনযোগ্য পদ্ধতিগুলি পরীক্ষা করি তবে সেখানে পদ্ধতি রয়েছে eসমান (অবজেক্ট) তাই আমি ভেবেছিলাম এটি সরাসরি কাজ করা উচিত, তবে এটি হয়নি did আপনি আমার উত্তরটি পরীক্ষা করতে পারেন নীচে আমি অঙ্কনযোগ্যকে বিটম্যাপে রূপান্তর করছি এবং তারপরে দুটি বিটম্যাপের তুলনা করছি এবং এটি কাজ করছে।
রওশন ঝা 3'12

2

ঠিক আছে, আমি মনে করি আমি এর চূড়ান্ত সমাধান খুঁজে পেয়েছি। অ্যাপকম্প্যাট এবং বন্ধুদের কারণে, সরবরাহযোগ্য আঁকাগুলি মাঝে মধ্যে বিভিন্ন রূপে স্ফীত হয় তাই এটি করা যথেষ্ট নয়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

আমি ইতিমধ্যে এখানে অনুরূপ বিষয়ে জবাব দিয়েছি: ইমেজভিউতে একটি অঙ্কনযোগ্য আইডি পান । পদ্ধতিটি কাস্টমটিতে একটি নির্দিষ্ট সংস্থান আইডি দিয়ে একটি ভিউ ট্যাগ করার উপর ভিত্তি করে LayoutInflater। সম্পূর্ণ প্রক্রিয়াটি একটি সাধারণ লাইব্রেরি ট্যাগভিউ দিয়ে স্বয়ংক্রিয় হয়

ফলস্বরূপ, আপনি কেবল দুটি আইডিয়েবলকে তাদের আইডি দ্বারা তুলনা করতে পারেন:

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

0

@ ওয়াঘানড্রয়েডের উত্তরটি প্রসারিত করার জন্য নিম্নলিখিত ম্যাচার রঙিত একটি ভেক্টর ড্রয়যোগ্যের জন্য কাজ করে। আপনাকে অঙ্কনযোগ্যটির জন্য যে রঙ ব্যবহার করা হয়েছিল তা সরবরাহ করতে হবে।

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 = getRes श्रोत ()। GetDrawable (R.drawable.twt_hover);

অঙ্কনযোগ্য sDraw = getResources ()। 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
  }
}

তবে এটি সম্ভবত তারা == নয়, তারা! =
লুসিফার

তবে তারা উত্স থেকে একই চিত্রটি উল্লেখ করে
রওশন ঝা

আমি কেবল তাদের সমান কিনা তা খতিয়ে দেখা দরকার? এর জন্য কোনও পদ্ধতি উপলব্ধ নেই?
রওশন ঝা

হ্যাঁ, আমি আপনার প্রয়োজনীয়তা পেয়েছি, দয়া করে চ্যাট রুমে আসুন
লুসিফার

4
== তুলনা করুন এটি যদি একই জিনিস হয় তবে এটি সময়ের 99999999999% নয়।
পলগাগ্রিকভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.