从widgetprovider更改按钮背景可绘制的颜色

时间:2013-08-07 15:51:56

标签: android android-widget android-styles

在任何活动的普通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 个答案:

答案 0 :(得分:2)

setColorFilter(int color,PorterDuff.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

答案 1 :(得分: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);

我知道回答你的问题为时已晚,但也许很多人都会需要它。

祝你好运 阿明。

答案 2 :(得分:1)

id喜欢根据@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上工作

答案 3 :(得分:1)

您应该使用带有match_parent参数的ImageView puted或Relative布局创建背景。因此,您可以在代码中更改颜色和透明度dinamicaly。 我的小部件布局

<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));
        }