0

I created a widget configuration file which is started when my app widget is placed on the screen. However, I don't know how I can access the button from my widget layout to make changes on it (In this example I want to change the color/tint)

public class ExampleAppWidgetConfig extends AppCompatActivity {
private int appWidgetId;
private RadioGroup radioGroupColor;
private RadioButton radioButtonDefault;
private RadioButton radioButtonGreen;
private RadioButton radioButtonRed;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_example_app_widget_config);

    Intent configIntent = getIntent();
    Bundle extras = configIntent.getExtras();
    if (extras != null) {
        appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
    }

    radioGroupColor = findViewById(R.id.radio_group_color);
    radioButtonDefault = findViewById(R.id.radio_button_default);
    radioButtonGreen = findViewById(R.id.radio_button_green);
    radioButtonRed = findViewById(R.id.radio_button_red);
}

public void confirmConfiguration(View v) {


    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);

    Intent intent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);

    RemoteViews views = new RemoteViews(this.getPackageName(), R.layout.example_widget);
    views.setOnClickPendingIntent(R.id.example_widget_button, pendingIntent);

    appWidgetManager.updateAppWidget(appWidgetId, views);

    Intent resultValue = new Intent();
    resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    setResult(RESULT_OK, resultValue);
    finish();
}

}

Florian Walther
  • 6,237
  • 5
  • 46
  • 104
  • `RemoteViews` is pretty limited, as far as what you can pass to it. AFAIK, there's no way to pass one a `ColorStateList`, which you'd need to only tint the background. You could use `setInt(R.id.example_widget_button, "setBackgroundColor", ???)`, but that would completely replace `Button`'s default background with a simple `ColorDrawable`. If you have only a limited number of options, you could possibly add a separate `Button` for each, and juggle their visibility with `setViewVisibility()`. – Mike M. Mar 13 '18 at 10:06
  • Ah so I have to do all the setup via remote views? – Florian Walther Mar 13 '18 at 10:07
  • 2
    Yeah, 'cause your Widget is actually running in another app. That's why `RemoteViews` is so restricted; to prevent running of arbitrary, possibly malicious, code in another process. – Mike M. Mar 13 '18 at 10:11
  • OK thanks, now I get it – Florian Walther Mar 13 '18 at 10:32
  • Thanks that was very helpful. Can you also tell me if I should put some of the work outside of the confirm button? Is what I do in there too heavy, considering that I also add something like changing a view? – Florian Walther Mar 13 '18 at 12:26
  • Nah, that looks perfectly reasonable. Basically all you're doing there is setting some simple values on a relatively simple object that you just hand off. The actual `View` construction and setup is handled elsewhere. – Mike M. Mar 13 '18 at 12:31
  • 1
    Thank you so much! – Florian Walther Mar 13 '18 at 12:34
  • What about writing the method names yourself with those "setInt", "setCharSequence" etc. methods? Looks like this way there are more possible methods available. – Florian Walther Mar 13 '18 at 13:07
  • They would have to be methods that are already defined in [the `View`s supported by `RemoteViews`](https://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout). You can't use your own custom `View`, if that's what you're suggesting, even if it is a subclass of one of those. _"Descendants of these classes are not supported."_ – Mike M. Mar 13 '18 at 13:13
  • No I just mean having more methods available. For example setEnabled or setBackgroundColor are not directly callable on RemoteViews, but I can use them with setInt or setBoolean. – Florian Walther Mar 13 '18 at 13:16
  • I just wonder if there are limits to the method I can call. – Florian Walther Mar 13 '18 at 13:17
  • Yeah, absolutely. That's exactly what those methods are for. I couldn't think of a way to tint a background `Drawable` like that, though. Did you think of something? – Mike M. Mar 13 '18 at 13:18
  • 1
    The limiting factor there is that there are only such methods for single primitive or `CharSequence` arguments. – Mike M. Mar 13 '18 at 13:19
  • No, the background tint was just an example so I don't mind. So if I understand it correctly, we can't do it because this method takes a ColorStateList but there is no RemoteViews.setColorStateList method available? But we can do all the stuff we pass Strings, ints, booleans etc. for? – Florian Walther Mar 13 '18 at 13:20
  • 1
    Yep, you got it. – Mike M. Mar 13 '18 at 13:21
  • 1
    Thank you, that was very helpful. – Florian Walther Mar 13 '18 at 13:22
  • If you know a lot about widgets and are in the mood of answering questions, I have another question here: https://stackoverflow.com/questions/49256734/changes-in-appwidgetproviderinfo-file-makes-previous-app-widgets-unusable – Florian Walther Mar 13 '18 at 13:27
  • Yeah, I saw that one. It doesn't really surprise me that that happens, but I've not had experience with that behavior before, and I don't really have time to investigate and test a solution right now. Off the top of my head, I would think that you'll have to persist the settings for each Widget based on its ID; e.g., in `SharedPreferences`, an SQLite database, a file, etc. I wouldn't think that the IDs change, but I'm not sure. – Mike M. Mar 13 '18 at 13:35
  • 1
    Ok thank you for your help – Florian Walther Mar 13 '18 at 13:38

0 Answers0