【问题标题】:AppCompat 23.2 use VectorDrawableCompat with RemoteViews (AppWidget) on API<21AppCompat 23.2 在 API<21 上使用 VectorDrawableCompat 和 RemoteViews (AppWidget)
【发布时间】:2016-06-08 14:06:39
【问题描述】:

我有一个 AppWidget,我想在棒棒糖之前的设备上使用 VectorDrawables。 VectorDrawableCompat 不适用于我创建的 RemoteView。

为了减小我的应用 APK 大小,我不想为旧 API 平台添加替代的 PNG 版本的 drawable。

我该怎么做?

【问题讨论】:

    标签: android android-support-library android-appcompat remoteview android-vectordrawable


    【解决方案1】:

    2017 年 10 月 22 日更新

    正如@user924 所指出的,现在AppCompatDrawableManager 访问仅限于其自己的库。 ContextCompat.getDrawable(...) 应该可以解决问题。

    2016 年 5 月 9 日更新

    正如@kirill-kulakov 在其回答中所指出的,支持库的最新更新将 TintContextWrapper 的可见性限制在它自己的包中。 我正在更新我的答案以删除不正确的代码,但请感谢 Kirill 的更正!

    VectorDrawable 和 RemoteViews pre-Lollipop

    您可以通过简单的hack避免添加矢量可绘制资源的替代光栅化版本:使用 AppCompat TintResourcesTintContextWrapper 使用 AppCompatDrawableManager 使用 ContextCompat

    TintResources AppCompatDrawableManager ContextCompat 是除其他外,在Lollipop 之前的设备,解析 VectorDrawable 的 XML 文件并将它们转换为可一直使用到 API 7 的 VectorDrawableCompat 实例。

    然后,一旦你有一个 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:srcapp: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);
    }
    


    参考文献

    【讨论】:

    • TintContextWrapper 在 android.support.v7.widget 中不公开;无法从外部包访问
    • Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); stackoverflow.com/questions/43710994/… 上的错误
    • AppCompatDrawableManager can only be called from within the same library group
    • 嗨@user924,我更新了答案以添加对最新Android支持库版本的兼容性!谢谢!
    • @user924,RemoteViews 肯定不适用于 AppCompatImageView。您可以在 RemoteViews 中使用的小部件和布局列表定义在 documentation
    【解决方案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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-08-27
      • 1970-01-01
      • 1970-01-01
      • 2013-08-09
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      相关资源
      最近更新 更多