1

在任何活动的普通 Android 代码中,我可以控制背景可绘制的颜色

Drawable d = findViewById(R.id.button_highlight).getBackground();  
PorterDuffColorFilter filter = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_ATOP);  
d.setColorFilter(filter); 

我想知道如何在 WidgetProvider 中利用它来动态更改元素的背景可绘制对象的背景颜色

从我的 AppWidgetProvider 实例中,我想调用如下内容:

int color2 = settings.getInt("secondary_color", R.color.main_alt);
// following won't work because a <Button> has no method "setColorFilter"
remoteViews.setInt(R.id.button_highlight,"setColorFilter",color2);

id 为 R.id.highlight 的按钮的 button_bg.xml 可绘制对象如下所示:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape>

            <corners android:topRightRadius="5dp" android:bottomRightRadius="5dp"/>
            <solid android:color="@color/main_alt"/>
            <padding android:bottom="5dp" android:left="5dp" android:right="5dp" android:top="5dp"/>

        </shape>
    </item>

    <item>
        <shape>

            <corners android:topRightRadius="5dp" android:bottomRightRadius="5dp"/>
            <solid android:color="@color/main"/>
            <padding android:bottom="5dp" android:left="5dp" android:right="5dp" android:top="5dp"/>

        </shape>
    </item>
</selector>

有什么解决方法吗?我错过了什么吗?如何更改背景可绘制对象的颜色?我正在考虑子类化 Button 并实现自定义方法来设置颜色,但我首先想知道是否有更常见或更简单的方法..

4

4 回答 4

2

setColorFilter(int color, PorterDuff.Mode mode) 没有@RemotableViewMethod 注解,因此不能在RemoteViews 中使用。

我最好的选择是将drawable转换为位图,然后使用RemoteViews.setImageBitmap(): http: //developer.android.com/reference/android/widget/RemoteViews.html#setImageViewBitmap(int, android.graphics.Bitmap ) 我还没有实际测试过,但值得一试。我发现有些方法在远程视图中不起作用,即使它们有 @RemotableViewMethod 注释,所以它可能起作用,也可能不起作用。

您将在 SO 上找到有关如何将 Drawable 转换为位图的答案,例如: https ://stackoverflow.com/a/9390776/534471

于 2013-08-07T16:34:22.760 回答
2

您应该使用 match_parent 参数从 ImageView puted 或 Relative 布局创建背景。所以你可以在代码中改变颜色和透明度。 我的小部件布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:padding="@dimen/widget_margin"
    android:orientation="vertical"
    android:gravity="center"
    android:baselineAligned="false"
    android:id="@+id/widget_layout">

    <ImageView
        android:id="@+id/widget_background_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/layout_bg"
        android:contentDescription="@string/background"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"/>

  <TextView
            android:id="@+id/widget_text"
            android:layout_width="fill_parent"
            android:layout_height="0dp"
            android:contentDescription="@string/appwidget_text"
            android:text="@string/widget_default_name"
            android:textColor="#fbff00"
            android:textSize="12sp"
            android:textStyle="bold"
            android:allowUndo="false"
            android:clickable="true"
            android:gravity="bottom|center"
            android:layout_weight="1"/>
 </RelativeLayout>

在 drawables 中创建自定义形状文件layout_bg.xml

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle" >
    <corners android:radius="10dip"/>
    <padding android:left="8dip" android:top="8dip" android:right="8dip" android:bottom="8dip" />
</shape>

现在在小部件更新侦听器中,您可以通过代码设置任何颜色:

remoteViews.setInt(R.id.widget_background_image, "setColorFilter", backColor);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    remoteViews.setInt(R.id.widget_background_image,"setImageAlpha",Color.alpha(backColor));
} else {
remoteViews.setInt(R.id.widget_background_image, setAlpha",Color.alpha(backColor));
        }
于 2016-04-07T16:23:26.393 回答
1

我想根据@bitfor 的回答添加一些内容。

由于该方法使用@hide 注解,因此无法直接调用该方法,因此必须通过反射调用该方法:

int id =  R.id.button1  //(the button in widget)
RemoteViews views = ....
  int textcolor = .......
int backgroundcolor = .....
      views.setTextViewText(id, "myButtontext");
          views.setTextColor(id, textcolor);
          Class c = Class.forName("android.widget.RemoteViews");
          Method m = c.getMethod("setDrawableParameters", new Class[] {int.class, boolean.class, int.class, int.class, PorterDuff.Mode.class, int.class});
          m.invoke(views, new Object[]{id, true, -1, backgroundcolor, android.graphics.PorterDuff.Mode.OVERLAY, -1});

希望它有所帮助:) 测试并确认在 4.4 和 5.0 上工作

于 2014-12-20T18:47:27.807 回答
1

昨晚我需要这样做!但是在我阅读 RemoteViews.java 之后,我发现我应该用 PorterDuff 添加 setColorFilter

从原始 android RemotView.java 看这里

       /**
   * @hide
   * Equivalent to calling a combination of {@link Drawable#setAlpha(int)},
   * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)},
   * and/or {@link Drawable#setLevel(int)} on the {@link Drawable} of a given
   * view.
   * <p>
   * You can omit specific calls by marking their values with null or -1.
   * 
   * @param viewId The id of the view that contains the target
   *            {@link Drawable}
   * @param targetBackground If true, apply these parameters to the
   *            {@link Drawable} returned by
   *            {@link android.view.View#getBackground()}. Otherwise, assume
   *            the target view is an {@link ImageView} and apply them to
   *            {@link ImageView#getDrawable()}.
   * @param alpha Specify an alpha value for the drawable, or -1 to leave
   *            unchanged.
   * @param colorFilter Specify a color for a
   *            {@link android.graphics.ColorFilter} for this drawable, or -1
   *            to leave unchanged.
   * @param mode Specify a PorterDuff mode for this drawable, or null to leave
   *            unchanged.
   * @param level Specify the level for the drawable, or -1 to leave
   *            unchanged.
   */
   public void setDrawableParameters(int viewId, boolean targetBackground, int alpha,
         int colorFilter, PorterDuff.Mode mode, int level) {
     addAction(new SetDrawableParameters(viewId, targetBackground, alpha,
             colorFilter, mode, level));
  }

那么您可以像我一样使用它,例如:

           contentView.setDrawableParameters(R.id.right_icon, false, -1, mBiftorIconColor, android.graphics.PorterDuff.Mode.MULTIPLY, -1);

我知道现在回答您的问题为时已晚,但也许许多其他人需要它。

祝阿明好运。

于 2014-02-12T13:21:49.467 回答