Is it possible to use VectorDrawable in Buttons and TextViews using android:DrawableRight?
it possible to use drawableRight etc for SVG assets ?
Yes
AppCompatTextView now supports app:drawableLeftCompat
, app:drawableTopCompat
, app:drawableRightCompat
, app:drawableBottomCompat
, app:drawableStartCompat
and app:drawableEndCompat
compound drawables, supporting backported drawable types such as VectorDrawableCompat
.
Include this in your gradle file
implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
In your text view you can use
app:drawableLeftCompat
app:drawableStartCompat
If you have problems while using app:drawableLeftCompat, app:drawableStartCompat in buttons you will need to update your library to
androidx.appcompat:appcompat:1.2.0-alpha01
they had a bug on
androidx.appcompat:appcompat:1.1.0-alpha01
you can see the docs
Or if you don't want to update yet, then:
Because it seems Google not going to do anything about this issue any time soon, I had to came up with a more solid reusable solution for all of my apps:
-
First add custom TextView attributes in attrs.xml file of your app "res/values/attrs.xml" :
<resources> <declare-styleable name="CustomTextView"> <attr name="drawableStartCompat" format="reference"/> <attr name="drawableEndCompat" format="reference"/> <attr name="drawableTopCompat" format="reference"/> <attr name="drawableBottomCompat" format="reference"/> </declare-styleable> </resources>
-
Then create custom TextView class like this:
import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.v7.content.res.AppCompatResources; import android.support.v7.widget.AppCompatTextView; import android.util.AttributeSet; public class CustomTextView extends AppCompatTextView { public CustomTextView(Context context) { super(context); } public CustomTextView(Context context, AttributeSet attrs) { super(context, attrs); initAttrs(context, attrs); } public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(context, attrs); } void initAttrs(Context context, AttributeSet attrs) { if (attrs != null) { TypedArray attributeArray = context.obtainStyledAttributes( attrs, R.styleable.CustomTextView); Drawable drawableStart = null; Drawable drawableEnd = null; Drawable drawableBottom = null; Drawable drawableTop = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { drawableStart = attributeArray.getDrawable(R.styleable.CustomTextView_drawableStartCompat); drawableEnd = attributeArray.getDrawable(R.styleable.CustomTextView_drawableEndCompat); drawableBottom = attributeArray.getDrawable(R.styleable.CustomTextView_drawableBottomCompat); drawableTop = attributeArray.getDrawable(R.styleable.CustomTextView_drawableTopCompat); } else { final int drawableStartId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableStartCompat, -1); final int drawableEndId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableEndCompat, -1); final int drawableBottomId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableBottomCompat, -1); final int drawableTopId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableTopCompat, -1); if (drawableStartId != -1) drawableStart = AppCompatResources.getDrawable(context, drawableStartId); if (drawableEndId != -1) drawableEnd = AppCompatResources.getDrawable(context, drawableEndId); if (drawableBottomId != -1) drawableBottom = AppCompatResources.getDrawable(context, drawableBottomId); if (drawableTopId != -1) drawableTop = AppCompatResources.getDrawable(context, drawableTopId); } // to support rtl setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStart, drawableTop, drawableEnd, drawableBottom); attributeArray.recycle(); } } }
-
Now you can use it easily in any layouts by your custom attributes:
<YOUR_VIEW_PACKAGE.CustomTextView android:id="@+id/edt_my_edit_text" android:layout_width="wrap_content" android:layout_height="wrap_content" app:drawableStartCompat="@drawable/your_vector_drawable" <!-- vector drawable --> app:drawableEndCompat="@drawable/your_vector_drawable" <!-- vector drawable --> app:drawableTopCompat="@drawable/your_vector_drawable" <!-- vector drawable --> app:drawableBottomCompat="@drawable/your_vector_drawable" <!-- vector drawable --> />
- You can do similar thing with Button, EditText and RadioButton because they derived from TextView
Hope this helps :)
The best way I found:
Drawable leftDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_search);
search.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);
This solution is no longer correct. From 23.3.0 version vector drawables can only be loaded via app:srcCompat or setImageResource()
Try to wrap your vector drawable into layer-list or selector:
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableRight="@drawable/ic_accessible_white_wrapped"
android:background="@color/colorPrimary"
android:textColor="#FFFFFF"
android:textSize="22sp"
android:text="Hello World!"/>
ic_accessible_white_wrapped.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_accessible_white_36px"/>
</layer-list>
To complement some of the answers here: you can get VectorDrawable to work as drawableLeft
(etc.) but it depends on the Support Library version and it comes with a price.
In which cases does it work? I've made this diagram to help (valid for Support Library 23.4.0 to - at least - 25.1.0).