Vector Resources is not supported for < API level 21, thus the Vector Drawables Backward Compatibility is required.
Module:app build.gradle
Edit Module:app build.gradle
- include
vectorDrawables.useSupportLibrary = true
- include
com.android.support:appcompat-v7
orcom.android.support:design
- include
com.android.support:support-vector-drawable
...
android {
defaultConfig {
applicationId ...
...
vectorDrawables.useSupportLibrary = true
}
}
dependencies {
// https://developer.android.com/topic/libraries/support-library/revisions.html
// implementation "com.android.support:support-v4:26.1.0"
// implementation "com.android.support:appcompat-v7:26.1.0"
implementation "com.android.support:support-vector-drawable:26.1.0"
implementation "com.android.support:design:26.1.0"
}
...
AppCompatDelegate.setCompatVectorFromResourcesEnabled
It's recommended to call AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) at Application.onCreate
.
Sets whether vector drawables on older platforms (< API 21) can be used within DrawableContainer resources.
When enabled, AppCompat can intercept some drawable inflation from the framework, which enables implicit inflation of vector drawables within DrawableContainer resources. You can then use those drawables in places such as android:src on ImageView, or android:drawableLeft on TextView.
This feature defaults to disabled, since enabling it can cause issues with memory usage, 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 with this disabled, you can still use vector resources through setImageResource(int) and its app:srcCompat attribute. They can also be used in anything which AppCompat inflates for you, such as menu resources.
Please note: this only takes effect in Activities created after this call.
If you don't do this, you might bump into android.content.res.Resources$NotFoundException: File res/drawable/ic_error_black_24dp.xml from drawable resource ID #0x7f08006a. If the resource you are trying to use is a vector resource, you may be referencing it in an unsupported way. See AppCompatDelegate.setCompatVectorFromResourcesEnabled() for more info
on older platforms (< API 21).
class MyApp : Application() { override fun onCreate() { super.onCreate() AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); }}
NOTE: remember to load your application class in AndroidManifest.xml -> application.android:name
.
Load vector drawable
Get vector Drawable
programatically
val icon = AppCompatResources.getDrawable(context, R.drawable.ic_error_black_24dp)
val icon = ContextCompat.getDrawable(context, R.drawable.ic_error_black_24dp)
NOTE: AppCompatResources.getDrawable - This method supports inflation of
NOTE: Seems like AppCompatResources.getDrawable
is more realiable for vector, but ContextCompat.getDrawable
works when AppCompatDelegate.setCompatVectorFromResourcesEnabled
is used.
imageView.setImageResource(context, R.drawable.ic_error_black_24dp)
NOTE: ImageView.setImageResource
is equivelant to app:srcCompat
in layout xml.
Load vector Drawable
using app:srcCompat
in layout.
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_add_black_24dp" />
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:tint="@color/fab_tint"
app:srcCompat="@drawable/ic_add_black_24dp" />
</android.support.design.widget.CoordinatorLayout>
Get vector Drawable
from TypedArray
for custom view
class BadgePreference : Preference { private var badge: Drawable? = null constructor(context: Context) : super(context) {} constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { val a = context.theme.obtainStyledAttributes( attrs, R.styleable.PreferencesBadge, 0, 0) try { // Resources$NotFoundException // badge = a.getDrawable(R.styleable.PreferencesBadge_badge) val drawableResId = a.getResourceId(R.styleable.PreferencesBadge_badge, -1); badge = AppCompatResources.getDrawable(context, drawableResId) } finally { a.recycle() } } constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) { }}
Content of res/values/attrs.xml
<resources>
<declare-styleable name="PreferencesBadge">
<attr name="badge" format="reference" />
</declare-styleable>
</resources>
Specify custom drawable attribute in layout.
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.mypackage.myapp">
<com.mypackage.myapp.BadgePreference
android:key="@string/pref_key_export_text"
android:title="Export as Text"
android:summary="Export as data as plain text file. Keep the file safe as it is not encrypted"
custom:badge="@drawable/ic_upcoming"
/>
</PreferenceScreen>
References:
- https://developer.android.com/guide/topics/graphics/vector-drawable-resources.html
- https://medium.com/@chrisbanes/appcompat-v23-2-age-of-the-vectors-91cbafa87c88
- https://medium.com/@ferrand.d/can-you-and-should-you-use-vector-drawables-a-cheatsheet-32a2e1cc2ecf
- https://medium.com/androiddevelopers/using-vector-assets-in-android-apps-4318fd662eb9