How to have a vector drawing selector?

Background

I made the following ImageView to support selectors like "src":

public class CheckableImageView extends ImageView implements Checkable { private boolean mChecked; private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked }; public CheckableImageView(final Context context, final AttributeSet attrs) { super(context, attrs); final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.com_app_CheckableImageView, 0, 0); setChecked(a.getBoolean(R.styleable.com_app_CheckableImageView_com_app_checked, false)); a.recycle(); } @Override public int[] onCreateDrawableState(final int extraSpace) { final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); if (isChecked()) mergeDrawableStates(drawableState, CHECKED_STATE_SET); return drawableState; } @Override public void toggle() { setChecked(!mChecked); } @Override public boolean isChecked() { return mChecked; } public interface OnCheckStateListener { void onCheckStateChanged(boolean checked); } private OnCheckStateListener mOnCheckStateListener; public void setOnCheckStateListener(OnCheckStateListener onCheckStateListener) { mOnCheckStateListener = onCheckStateListener; } @Override public void setChecked(final boolean checked) { if (mChecked == checked) return; mChecked = checked; refreshDrawableState(); if (mOnCheckStateListener != null) mOnCheckStateListener.onCheckStateChanged(checked); } } 

Problem

The code above works great with regular selectors that have image files as elements available for each state.

The fact is that it does not work at all with vector drawings (using "srcCompat"). Instead, it shows empty content.

Here is what I tried:

  <...CheckableImageView ... app:srcCompat="@drawable/selector"/> 

And a selector (for example):

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_checked="true" android:drawable="@drawable/test"/> <item android:state_pressed="true" android:drawable="@drawable/test" /> <item android:drawable="@drawable/test2" /> </selector> 

vector drawing example:

 <?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="48dp" android:height="48dp" android:viewportWidth="48" android:viewportHeight="48"> <path android:fillColor="#0000ff" android:strokeColor="#000000" android:pathData="M 0 0 H 48 V 48 H 0 V 0 Z" /> <path android:fillColor="#ff0000" android:strokeColor="#000000" android:pathData="M14.769224,32.692291l5.707315,-17.692275l3.073244,17.479182l6.585245,-16.413424l2.634209,16.200186l-4.170761,-8.526356l-5.048693,7.247362l-5.268419,-8.100027l-3.51214,9.805351z" /> </vector> 

Question

Why is this not working? What happened to what I did? How can i fix this?

+5
source share
2 answers

This seems to be a mistake in how the support library works, and it is not documented in any way.

I tried to post an error report, but Google marked it as "UserError", although I do not see it documented or has any warning:

Designated work. Vectors are not supported in containers if you include AppComaptDelegate.setCompatVectorFromResourcesEnabled (true).

https://code.google.com/p/android/issues/detail?id=210745

So, if you see a selector that does not appear, or it causes a crash in this log:

Called: android.content.res.Resources $ NotFoundException: file res / drawable / selector.xml from resource resource ID # 0x7f02004f

you should either avoid using vectorDrawable inside the selector or not use the string vectorDrawables.useSupportLibrary = true.

You can use AppComaptDelegate.setCompatVectorFromResourcesEnabled (true), but according to the docs , this may be malfunctioning (memory / performance issues) and is not recommended at all:

Sets whether vector drawings on older platforms (<API 21) can be used in DrawableContainer resources.

When enabled, AppCompat can capture some profitable inflation from a frame that provides implicit inflation of vector drawings within DrawableContainer Resources. Then you can use these drawings in such as android: src on ImageView, or android: drawableLeft on TextView.

This feature is disabled by default because enabling it can cause memory problems and problems updating configuration instances. If you update the configuration manually, then you probably do not want to enable this. You have been warned.

Even if it is disabled, you can still use vector resources through setImageResource (int) and its app: srcCompat attribute. They can also be used in everything that AppComapt inflates for you, such as the resources menu.

Please note: this only takes effect in the Acts created after this call.

+12
source

Just create xml with color change. And set the selected color frame at runtime for the button.

-1
source

Source: https://habr.com/ru/post/1246809/


All Articles