Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

VectorDrawable и RemoteViews pre-Lollipop

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

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

Затем, как только у вас есть экземпляр VectorDrawableCompat, растеризуйте его на Bitmap. Позднее вы будете использовать это растровое изображение в удаленном 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);
}


Ссылки

Ответ 2

Следующий метод преобразует 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;
}