AppCompat 23.2 использует VectorDrawableCompat с RemoteViews (AppWidget) в API<21

У меня есть AppWidget, и я хотел бы использовать в нем VectorDrawables также на устройствах, предшествующих Lollipop. VectorDrawableCompat не будет работать с RemoteViews, которые я создаю.

Чтобы уменьшить размер APK моего приложения, я не хочу добавлять альтернативные версии моих чертежей в формате PNG для более старых платформ API.

Как я могу это сделать?

2 ответа

Решение

ОБНОВЛЕНИЕ 22/10/2017

Как отметил @user924, теперь доступ к AppCompatDrawableManager ограничен его собственной библиотекой. ContextCompat.getDrawable (...) должен сделать свое дело.

ОБНОВЛЕНИЕ 05/09/2016

Как отметил @kirill-kulakov в своем ответе, последние обновления библиотеки поддержки ограничивали видимость TintContextWrapper собственным пакетом. Я обновляю свой ответ, чтобы удалить неправильный код, но, пожалуйста, поблагодарите Кирилла за исправление!

VectorDrawable и RemoteViews перед леденцом на палочке

Вы можете избежать добавления альтернативных растеризованных версий ваших векторных графических ресурсов простым взломом: используйте AppCompat TintResources через TintContextWrapper, используя AppCompatDrawableManager, используя ContextCompat.

TintResources AppCompatDrawableManager ContextCompat - это класс, который, помимо прочего, на устройствах, предшествующих Lollipop, анализирует XML-файлы VectorDrawable и преобразует их в экземпляры VectorDrawableCompat, которые можно использовать вплоть до API 7.

Затем, когда у вас будет экземпляр VectorDrawableCompat, растеризуйте его в растровое изображение. Позже вы будете использовать это растровое изображение в удаленном ImageView.


Прежде чем мы начнем: Библиотека AppCompat

Убедитесь, что вы используете Android Studio 2.0+ и настроили свое приложение build.gradle файл следующим образом:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

dependencies {
  compile 'com.android.support:appcompat-v7:23.3.0'
}


Обновите свой AppWidgetProvider

Прежде всего: не устанавливайте векторные ресурсы рисования внутри файла макета RemoteViews (ни android:src ни app:srcCompat буду работать). Вы должны будете установить их программно.

Внутри вашего класса AppWidgetProvider установите векторный ресурс или растрированную версию в зависимости от уровня 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);
}


Рекомендации

Следующий метод преобразует vector drawable до растрового изображения раньше, это должно сработать.

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;
}
Другие вопросы по тегам