How to use setBackground with an Android Widget
Asked Answered
R

4

5

I asked a similar question before but I was too vague in my request. The code below draws a nice stylized button. When you click on the button, you can input a number and based on the number, changes the background color using

remoteViews.setInt(R.id.nmcButton, "setBackgroundColor", color);

Unfortunately, when I try to preserve the styling by using

remoteViews.setInt(R.id.nmcButton, "setBackground", color);

the widget won't load. Is there a way around this? Is there a way to preserve the styling while changing the background color?

Here are some of the relevant files

    package test.widget;

    import android.os.Bundle;
    import android.app.PendingIntent;
    import android.appwidget.AppWidgetManager;
    import android.appwidget.AppWidgetProvider;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.util.Log;
    import android.widget.RemoteViews;
    import android.graphics.Color;

    public class MyWidget extends AppWidgetProvider {

        private final static String TEST_ACTIVITY = "test.widget.action.TEST_ACTIVITY";
        private final static int INTENT_NO_REQUEST = 0; /* no requestCode */
        private final static int INTENT_NO_FLAGS = 0; /* code for no Flags */
        private int count = 9;

        @Override
        public void onReceive(Context context, Intent intent) {
            super.onReceive(context, intent);
            Bundle b = intent.getExtras();
            if (b != null) {
                count = b.getInt("nmcCount");
                callOnUpdate(context);
            }
        }

        private void callOnUpdate(Context context) {
            AppWidgetManager appWidgetManager = AppWidgetManager
                    .getInstance(context);
            ComponentName thisAppWidget = new ComponentName(
                    context.getPackageName(), MyWidget.class.getName());
            int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
            onUpdate(context, appWidgetManager, appWidgetIds);
        }

        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                int[] appWidgetIds) {
            super.onUpdate(context, appWidgetManager, appWidgetIds);
            buildUpdate(context, appWidgetManager, appWidgetIds);
        }

        private void buildUpdate(Context context,
                AppWidgetManager appWidgetManager, int[] appWidgetIds) {
            final int N = appWidgetIds.length;
            for (int i = 0; i < N; i++) {
                int appWidgetId = appWidgetIds[i];

                RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
                        R.layout.widget);

                Intent intent = new Intent(TEST_ACTIVITY);
                PendingIntent pendingIntent = PendingIntent.getActivity(context,
                        INTENT_NO_REQUEST, intent, INTENT_NO_FLAGS);
                remoteViews.setOnClickPendingIntent(R.id.nmcButton, pendingIntent);
                remoteViews.setTextViewText(R.id.nmcButton, String.valueOf(count));

                // the code below works, but the button does not have nice styling
                // int color = (count >= 5) ? Color.GREEN : Color.RED;
                // remoteViews.setInt(R.id.nmcButton, "setBackgroundColor", color);

                // this code doesn't work, you get "problem loading widget"
                int color = (count >= 5) ? R.drawable.btn_green
                        : R.drawable.btn_red;
                remoteViews.setInt(R.id.nmcButton, "setBackground", color);

                appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
            }
        }
    }

btn_red.xml

    <?xml version="2.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">

        <item android:state_pressed="true"><shape>
       <solid android:color="#ef4444" />

       <stroke android:width="1dp" android:color="#992f2f" />

       <corners android:radius="3dp" />

       <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
    </shape></item>
        <item><shape>
       <gradient android:angle="270" android:endColor="#992f2f" android:startColor="#ef4444" />

       <stroke android:width="1dp" android:color="#992f2f" />

       <corners android:radius="3dp" />

       <padding android:bottom="11dp" android:left="10dp" android:right="10dp" android:top="10dp" />
    </shape></item>

    </selector>

styles.xml

    <resources>
        <style name="ButtonText">
            <item name="android:layout_width">wrap_content</item>
            <item name="android:layout_height">wrap_content</item>
            <item name="android:gravity">center</item>
            <item name="android:layout_margin">1dp</item>
            <item name="android:textSize">10dp</item>
            <item name="android:textStyle">normal</item>
            <item name="android:shadowColor">#000000</item>
            <item name="android:shadowDx">1</item>
            <item name="android:shadowDy">1</item>
            <item name="android:shadowRadius">2</item>
            <item name="android:textColor">#ffffff</item>  
        </style>
        <style name="AppTheme" parent="android:Theme.Light" />
    </resources>
Rolf answered 21/11, 2012 at 20:23 Comment(0)
R
18

A co-worker had the answer, I should have used:

remoteViews.setInt(R.id.nmcButton, "setBackgroundResource", color);

Instead of:

remoteViews.setInt(R.id.nmcButton, "setBackground", color);
Rolf answered 21/11, 2012 at 22:9 Comment(1)
Doesn't work. The styling is removed. It doesn't answer your own questionFlowers
V
2

I tried this but that didn't work for me.

If you want to set a color in your widget you should do this:

remoteViews.setInt(R.id.nmcButton, "setBackgroundColor", color);
Vlada answered 4/9, 2014 at 15:47 Comment(3)
I downvoted because it doesn't address the issue of losing style after a setBackgroundColorScarabaeus
@BrenoSalgado Then why downvote? This may not be the answer for you, but it sure works perfectly for me. The answer above also doesn't address that issue right? You could also just leave a comment that you lose your style after using this method.Vlada
Nothing personal but I think it doesn't address the question properly. I think the quality on Java/Android answers are somewhat low because there's too much of this. At Ruby answers(as an example) I was used to answers trying to explain what's is the problem to the reader, suggesting solution, addressing each question made in OP, providing links, etc. This is the better way IMO(if I write a letter to you asking you 3 things you answer only 1 and ignore the rest, that's not the most polite, is it?), SO isn't a forum(again, I'm not meaning to offend you, but I think this holds true)Scarabaeus
S
0

This doesn't work for me on my ListView in my widget, so I came up with a workaround:

First I defined my layout to be FrameLayout where an ImageView is there to draw my background:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/iv_widget_background"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitXY" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/transparent"
        android:orientation="vertical"
        android:padding="@dimen/widget_listview_padding">

        <ListView
            android:id="@+id/lv_widget"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:divider="@null"
            android:dividerHeight="0dp" />
    </LinearLayout>

</FrameLayout>

Then I defined drawables in R.drawable like this:

red.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="#F44336" />
</shape>

When the user changes the background via SharedPrefs I have to do the following:

        Intent intent = new Intent(context, WidgetProvider.class);
        intent.setAction("android.appwidget.action.APPWIDGET_UPDATE");
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
        context.sendBroadcast(intent);

Then in my onUpdate() function in the AppWidgetProvider I do the following:

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWdgetIds) {
    try {
        RemoteViews remoteViews;
        for (int appWdgetId : appWdgetIds) {
            remoteViews = updateWidgetListView(context, appWdgetId);
            appWidgetManager.updateAppWidget(appWdgetId, remoteViews);
        }
        super.onUpdate(context, appWidgetManager, appWdgetIds);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private RemoteViews updateWidgetListView(Context context, int appWidgetId) {
    //which layout to show on widget
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
    Intent svcIntent = new Intent(context, WidgetService.class);
    svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);        svcIntent.setData(Uri.parse(svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
    remoteViews.setRemoteAdapter(appWidgetId, R.id.lv_widget, svcIntent);

    setBackground(context, remoteViews);

    return remoteViews;
}

private void setBackground(Context context, RemoteViews remoteViews) {
    String background = Utils.getStringValue(context, R.string.pref_widget_backgroundcolor_key,
            R.string.pref_widget_backgroundcolor_default);

    if (!TextUtils.isEmpty(background)) {
        int identifier = context.getResources().getIdentifier(
                background, "drawable", context.getPackageName());
        remoteViews.setImageViewResource(R.id.iv_widget_background, identifier);
    }
}

Result:

enter image description here

Symphysis answered 1/1, 2016 at 8:46 Comment(0)
B
0

One Easy and reliable way is to have an imageview and filled with a bitmap with our desired color :

  Bitmap image = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
  Canvas canvas=new Canvas (image);
  canvas.drawColor (Color.parseColor(color));
  contentView_big.setImageViewBitmap(R.id.ntp_colorhint, image);
Bussy answered 25/3, 2020 at 22:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.