/Widget

Primary LanguageJava

Widget

Create a new layout resource file named list_widget.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:layout_margin="@dimen/widget_margin">

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:background="#bbDEDFDE"
       android:orientation="vertical">

       <ListView
           android:id="@+id/widget_list"
           android:layout_width="match_parent"
           android:layout_height="match_parent">
       </ListView>
   </LinearLayout>

</FrameLayout>

Populating the collection widget

Next, we need to create a data provider for our ListView.
Create a new Java class named DataProvider.java and add the following:

public class DataProvider implements RemoteViewsService.RemoteViewsFactory {

   List<String> myListView = new ArrayList<>();
   Context mContext = null;

   public DataProvider(Context context, Intent intent) {
       mContext = context;
   }

   @Override
   public void onCreate() {
       initData();
   }

   @Override
   public void onDataSetChanged() {
       initData();
   }

   @Override
   public void onDestroy() {

   }

   @Override
   public int getCount() {
       return myListView.size();
   }

   @Override
   public RemoteViews getViewAt(int position) {
       RemoteViews view = new RemoteViews(mContext.getPackageName(),
       simple_list_item_1);
               view.setTextViewText(text1, myListView.get(position));
               return view;
   }

   @Override
   public RemoteViews getLoadingView() {
       return null;
   }

   @Override
   public int getViewTypeCount() {
       return 1;
   }

   @Override
   public long getItemId(int position) {
      return position;
   }

   @Override
   public boolean hasStableIds() {
       return true;
   }

   private void initData() {
       myListView.clear();
       for (int i = 1; i <= 15; i++) {
           myListView.add("ListView item " + i);
       }

   }
  }

To create an Android widget, you need to create several files.

Our first widget-specific file is an AppWidgetProvider, which is a BroadcastReceiver where you’ll define the various widget lifecycle methods, such as the method that’s called when your widget is first created and the method that’s called when that widget is eventually deleted.

Create a new Java class (File > New > Java Class) named CollectionWidget.

To start, all widget provider files must extend from the AppWidgetProvider class. We then need to load the list_widget.xml layout resource file into a RemoteViews object, and inform the AppWidgetManager about the updated RemoteViews object:

public class CollectionWidget extends AppWidgetProvider {

   static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                     int appWidgetId) {

//Instantiate the RemoteViews object//

       RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.list_widget);
           setRemoteAdapter(context, views);

//Request that the AppWidgetManager updates the application widget//

       appWidgetManager.updateAppWidget(appWidgetId, views);

   }

Create the adapter

Since we’re displaying our data in a ListView, we need to define a setRemoteAdapter() method in our AppWidgetProvider.
The setRemoteAdapter() is equivalent to calling AbsListView.setRemoteViewsAdapter() but is designed to be used in application widgets.
In this method, we need to define the id of the AdapterView (R.id.widget_list) and the intent of the service that’ll eventually provide the data to our RemoteViewsAdapter.

private static void setRemoteAdapter(Context context, @NonNull final RemoteViews views) {
   views.setRemoteAdapter(R.id.widget_list,new Intent(context, WidgetService.class));
}

The onUpdate() widget lifecycle method is responsible for updating your widget’s Views with new information.
This method is called each time:

The user performs an action that manually triggers the onUpdate() method. The application’s specified update interval has elapsed.
The user places a new instance of this widget on their homescreen. An ACTION_APPWIDGET_RESTORED broadcast intent is sent to the AppWidgetProvider.
This broadcast intent is triggered if the widget is ever restored from backup.

When you call onUpdate(), you need to specify whether you’re updating every instance of this widget, or a specific instance only.
If you want to update every instance, then you can use appWidgetIds, which is an array of IDs that identifies every instance across the device.

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
   for (int appWidgetId : appWidgetIds) {

//Update all instances of this widget//

       updateAppWidget(context, appWidgetManager, appWidgetId);
   }
   super.onUpdate(context, appWidgetManager, appWidgetIds);
}

onEnabled: Performing the initial setup

The onEnabled() lifecycle method is called in response to ACTION_APPWIDGET_ENABLED, which is sent when an instance of your widget is added to the homescreen for the first time.
If the user creates two instances of your widget, then onEnabled() will be called for the first instance, but not for the second.

The onEnabled() lifecycle method is where you should perform any setup that’s required for all instances of your widget, such as creating the database that’ll feed your widget information.

@Override
public void onEnabled(Context context) {
   Toast.makeText(context,"onEnabled called", Toast.LENGTH_LONG).show();
}