J'ai un AppWidget et j'aimerais également utiliser VectorDrawables sur des appareils pré-Lollipop. VectorDrawableCompat ne fonctionnera pas avec les RemoteViews que je crée.
Pour réduire la taille de l'APK de mon application, je ne veux pas ajouter d'autres versions PNG de mes drawables pour les anciennes plates-formes d'API.
Comment puis je faire ça?
MISE À JOUR 22/10/2017
Comme indiqué par @ user924 maintenant l'accès AppCompatDrawableManager est limité à sa propre bibliothèque. ContextCompat.getDrawable (...) devrait faire l'affaire.
MISE À JOUR 05/09/2016
Comme indiqué par @ kirill-kulakov dans sa réponse, les dernières mises à jour de la bibliothèque de support limitaient la visibilité de TintContextWrapper à son propre package. Je mets à jour ma réponse pour supprimer le code incorrect, mais merci à Kirill pour la correction!
Vous pouvez éviter d'ajouter des versions tramées alternatives de vos ressources vectorielles dessinables avec un hack simple : utilisez AppCompat TintResources à TintContextWrapper en utilisant AppCompatDrawableManager en utilisant ContextCompat .
TintResources AppCompatDrawableManager ContextCompat est la classe qui, entre autres, sur les appareils pré-Lollipop, analyse les fichiers XML VectorDrawable et les convertit en Instances VectorDrawableCompat pouvant être utilisées jusqu'à l'API 7.
Ensuite, une fois que vous avez une instance VectorDrawableCompat , pixellisez-la sur un bitmap. Vous utiliserez plus tard ce bitmap dans une ImageView distante .
Assurez-vous que vous utilisez Android Studio 2.0+ et que vous avez configuré votre application build.gradle
comme suit:
Android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
dependencies {
compile 'com.Android.support:appcompat-v7:23.3.0'
}
Tout d'abord: ne définissez pas vos ressources vectorielles dessinables dans votre fichier de mise en page RemoteViews (ni Android:src
ni app:srcCompat
marchera). Vous devrez les définir par programme.
Dans votre classe AppWidgetProvider , définissez la ressource vectorielle ou une version tramée en fonction du niveau de l'API:
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.appwidget_layout);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Lollipop) {
remoteViews.setImageViewResource(R.id.imageView, R.drawable.vector);
} else {
Drawable d = ContextCompat.getDrawable(context, R.drawable.vector);
Bitmap b = Bitmap.createBitmap(d.getIntrinsicWidth(),
d.getIntrinsicHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
d.setBounds(0, 0, c.getWidth(), c.getHeight());
d.draw(c);
remoteViews.setImageViewBitmap(R.id.imageView, b);
}
La méthode suivante convertira le vector drawable
à un bitmap avant, cela devrait faire l'affaire.
public static BitmapDrawable vectorToBitmapDrawable(Context ctx, @DrawableRes int resVector) {
return new BitmapDrawable(ctx.getResources(), vectorToBitmap(ctx, resVector));
}
public static Bitmap vectorToBitmap(Context ctx, @DrawableRes int resVector) {
Drawable drawable = AppCompatDrawableManager.get().getDrawable(ctx, resVector);
Bitmap b = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
drawable.setBounds(0, 0, c.getWidth(), c.getHeight());
drawable.draw(c);
return b;
}