Modal dialog (popup) from Android widget example
Introduction
Android widgets only contain a subset of the available UI components and functionality when compared to Android activities. This means that if we have a requirement that needs something a bit more sophisticated than the functionality provided by widgets, we may need to implement some workarounds in order to achieve our goal. In this tutorial we will see how we can launch a modal popup dialog from an Android widget.
Used software:
- Android SDK 21.0.0
A simple widget
In this tutorial we will use a widget that consists in a simple button. When the user presses the button the application will show a modal popup containing some random text and a dismiss button. The button widget will look similar to the following image:
We declare out widget in AndroidManifest.xml:
<receiver android:name=".BytesLoungeWidget" android:icon="@drawable/ic_launcher" android:label="Bytes Lounge Widget" > <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="com.byteslounge.android.widgetshowdialog" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget" /> </receiver>
Note that we are registering our widget to listen for com.byteslounge.android.widgetshowdialog intent. This intent will be fired when we press the Show modal popup dialog button.
Following next is our simple widget implementation:
package com.byteslounge.android; 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.widget.RemoteViews; public class BytesLoungeWidget extends AppWidgetProvider { private static final String SHOW_DIALOG_ACTION = "com.byteslounge.android.widgetshowdialog"; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { prepareWidget(context); super.onUpdate(context, appWidgetManager, appWidgetIds); } @Override public void onReceive(final Context context, Intent intent) { // If the intent is the one that signals // to launch the modal popup activity // we launch the activity if(intent.getAction().equals(SHOW_DIALOG_ACTION)) { Intent i = new Intent(context, WidgetDialogActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(i); } super.onReceive(context, intent); } private void prepareWidget(Context context) { AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); ComponentName thisWidget = new ComponentName(context, BytesLoungeWidget.class); // Fetch all instances of our widget // from the AppWidgetManager manager. // The user may have added multiple // instances of the same widget to the // home screen int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget); for (int widgetId : allWidgetIds) { RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout); // Create intent that launches the // modal popup activity Intent intent = new Intent(context, BytesLoungeWidget.class); intent.setAction(SHOW_DIALOG_ACTION); PendingIntent pendingIntent = PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); // Attach the onclick listener to // the widget button remoteViews.setOnClickPendingIntent(R.id.w_show_btn, pendingIntent); appWidgetManager.updateAppWidget(widgetId, remoteViews); } } }
We should note a couple of things in the widget implementation:
The first one is that we are registering the widget button onclick event to launch a specific intent - com.byteslounge.android.widgetshowdialog.
The second one is that we are handling this intent in the widget itself - inside onReceive method. This method will handle the intent and will launch a completely separate activity that will contain the modal popup. The widget is configured to handle this specific intent as we defined in AndroidManifest.xml.
The modal popup activity
We have seen in the previous section that we can launch a separate activity when the user clicks the widget Show button. Now we need to define an activity which look and feel looks like a modal popup. We go back to AndroidManifest.xml and define a new activity:
<activity android:name="com.byteslounge.android.WidgetDialogActivity" android:noHistory="true" android:theme="@android:style/Theme.Dialog" />
We defined our activity to use the Theme.Dialog theme. This will configure our modal popup dialog activity to look like a native Android dialog.
Now we define the activity content in a separate file, lets say /res/layout/widgetdialog_activity.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="220dp" android:layout_height="wrap_content" android:background="@drawable/modalbckg" android:gravity="center_horizontal" android:orientation="vertical" > <TextView android:id="@+id/w_dialog_txt" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="0dp" android:layout_marginRight="0dp" android:layout_marginTop="5dp" android:layout_marginBottom="10dp" android:gravity="center_horizontal" android:textColor="#000000" android:textSize="13sp" /> <Button android:id="@+id/w_dismiss_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Dismiss" /> </LinearLayout>
The activity consists in a layout that holds the modal dialog text and dismiss button. We are also defining the background of the modal popup as @drawable/modalbckg. In this drawable you configure the look and feel of the modal popup itself. In this tutorial we defined the popup with rounded corners and white background:
<?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <gradient android:startColor="#FFFFFF" android:endColor="#FFFFFF" android:angle="90"/> <corners android:bottomRightRadius="2dp" android:bottomLeftRadius="2dp" android:topLeftRadius="2dp" android:topRightRadius="2dp"/> <stroke android:width="1dp" android:color="#888888"/> </shape>
This file should be placed in /res/drawable/modalbckg.xml
Following next is the activity implementation:
package com.byteslounge.android; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class WidgetDialogActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.widgetdialog_activity); String dialogText = "This is the dialog text"; TextView txt = (TextView) findViewById(R.id.w_dialog_txt); txt.setText(dialogText); Button dismissbutton = (Button) findViewById(R.id.w_dismiss_btn); dismissbutton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { WidgetDialogActivity.this.finish(); } }); } }
We basically set the modal dialog text and configure the activity dismiss button to finish the activity itself when pressed.
Now when we press the Show button our modal popup activity will be launched and will look like the following: