Comparing Two Drawables in Android

Comparing two drawables in android

Update
https://stackoverflow.com/a/36373569/1835650

getConstantState() works not well

There is another way to compare:

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

mRemeberPwd is an ImageView in this example. If you're using a TextView, use getBackground().getConstantState instead.

How to Comparing two drawables in android

The most straightforward solution to this would be to set a tag to the ImageView whenever you are setting the drawable and then later checking the tag set to the ImageView.

Something like this :

When you are setting drawable1 to the imageView1, do imageView1.setTag("drawable1")

When you want to check the drawable in imageView1, you can simply go imageView1.getTag()

 //populerer buttons med images
for(int i = 0; i < buttons.size(); i++) {
int random = r.nextInt(buttons.size());
while(printedImagesIDs.contains(random))
random = r.nextInt(buttons.size());

buttons.get(i).setImageResource(imageIDs[random]);
buttons.get(i).setTag("" +imageIDs[random]); //set the tag while setting the drawable
printedImagesIDs.add(random);
}

if(((String)klikk1.getTag()).equals((String)klikk2.getTag())){//get and match the tags
turnstate = true;
}

Comparing resources within two drawables

getConstantState doesn't work well

If you do this:
if(drawable1 == drawable2){

you are comparing the reference of the objects and it not correct...

use instead equals with the getConstantState() method...

Update Try to compare with bytes or pixel is the only way that generally works.

 // Usage: 
drawable1.bytesEqualTo(drawable2)
drawable1.pixelsEqualTo(drawable2)
bitmap1.bytesEqualTo(bitmap1)
bitmap1.pixelsEqualTo(bitmap2)

https://gist.github.com/XinyueZ/3cca89416a1e443f914ed37f80ed59f2

Comparing two VectorDrawables fails in Kaspresso - Android

The issue was because actually the image is scaled. So the scaled image is different from the original one.

To avoid this issue I've used this "altered" KImageView:

package your_package

import android.content.res.ColorStateList
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.PorterDuff
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.StateListDrawable
import android.os.Build
import android.view.View
import android.widget.ImageView
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.core.graphics.drawable.DrawableCompat
import androidx.test.espresso.DataInteraction
import androidx.test.espresso.assertion.ViewAssertions
import com.agoda.kakao.common.assertions.BaseAssertions
import com.agoda.kakao.common.builders.ViewBuilder
import com.agoda.kakao.common.utilities.getResourceColor
import com.agoda.kakao.common.utilities.getResourceDrawable
import com.agoda.kakao.common.views.KBaseView
import com.agoda.kakao.image.KImageView
import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.TypeSafeMatcher

class KImageView2 : KBaseView<KImageView>, ImageViewAssertions2 {
constructor(function: ViewBuilder.() -> Unit) : super(function)
constructor(parent: Matcher<View>, function: ViewBuilder.() -> Unit) : super(parent, function)
constructor(parent: DataInteraction, function: ViewBuilder.() -> Unit) : super(parent, function)
}

interface ImageViewAssertions2 : BaseAssertions {
/**
* Checks if the view displays given drawable
*
* @param resId Drawable resource to be matched
* @param toBitmap Lambda with custom Drawable -> Bitmap converter (default is null)
*/
fun hasDrawable(@DrawableRes resId: Int, toBitmap: ((drawable: Drawable) -> Bitmap)? = null) {
view.check(ViewAssertions.matches(DrawableMatcher2(resId = resId, toBitmap = toBitmap)))
}
}

class DrawableMatcher2(
@DrawableRes private val resId: Int = -1,
@ColorRes private val tintColorId: Int? = null,
private val toBitmap: ((drawable: Drawable) -> Bitmap)? = null
) : TypeSafeMatcher<View>(View::class.java) {

override fun describeTo(desc: Description) {
desc.appendText("with drawable id $resId or provided instance")
}

override fun matchesSafely(view: View?): Boolean {
if (view !is ImageView) {
return false
}

if (resId < 0) {
return view.drawable == null
}
val bitmap = extractFromImageView(view)
view.setImageResource(resId)
val otherBitmap = extractFromImageView(view)

return bitmap?.sameAs(otherBitmap) ?: false
}

private fun extractFromImageView(view: View?): Bitmap? {
return view?.let { imageView ->
var expectedDrawable: Drawable? = getResourceDrawable(resId)?.mutate()

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && expectedDrawable != null) {
expectedDrawable = DrawableCompat.wrap(expectedDrawable).mutate()
}

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
tintColorId?.let { tintColorId ->
val tintColor = getResourceColor(tintColorId)
expectedDrawable?.apply {
setTintList(ColorStateList.valueOf(tintColor))
setTintMode(PorterDuff.Mode.SRC_IN)
}
}
}

if (expectedDrawable == null) {
return null
}

val convertDrawable = (imageView as ImageView).drawable.mutate()
toBitmap?.invoke(convertDrawable) ?: convertDrawable.toBitmap()
}
}
}

internal fun Drawable.toBitmap(): Bitmap {
if (this is BitmapDrawable && this.bitmap != null) {
return this.bitmap
}

if (this is StateListDrawable && this.getCurrent() is BitmapDrawable) {
val bitmapDrawable = this.getCurrent() as BitmapDrawable
if (bitmapDrawable.bitmap != null) {
return bitmapDrawable.bitmap
}
}

val bitmap = if (this.intrinsicWidth <= 0 || this.intrinsicHeight <= 0) {
Bitmap.createBitmap(
1,
1,
Bitmap.Config.ARGB_8888
) // Single color bitmap will be created of 1x1 pixel
} else {
Bitmap.createBitmap(this.intrinsicWidth, this.intrinsicHeight, Bitmap.Config.ARGB_8888)
}

val canvas = Canvas(bitmap)
this.setBounds(0, 0, canvas.width, canvas.height)
this.draw(canvas)
return bitmap
}

Not the cleanest solution possible, but it works. If anyone can provide a better solution would be great :-)



Related Topics



Leave a reply



Submit