コレクション ウィジェットは、次のような、同じタイプの多くの要素の表示に特化しています。 ギャラリー アプリの画像のコレクション、ニュースアプリの記事、 やり取りできます。コレクション ウィジェットでは通常、以下の 2 つの用途に重点を置きます。 ケース: コレクションの閲覧、コレクションの要素をそのコレクションで開く できます。コレクション ウィジェットは上下にスクロールできます。
これらのウィジェットでは
表示する RemoteViewsService
リモート データに基づくコレクション(
できます。ウィジェットには、
コレクションと呼ばれるビュータイプのいずれかを使用して、
ビュー:
ListView
- 特定のフォルダ内でアイテムを表示するビュー 縦方向にスクロールするリストです。
GridView
- 特定のフォルダ内でアイテムを表示するビュー 2 次元のスクロール グリッドです。
StackView
- 縦に積まれたカード 前面をフリックすると、Rolodex のようなビューです。 前または次のカードを表示するために、カードを上または下にスクロールします。
AdapterViewFlipper
-
アダプターを使用する(シンプル)
アニメーション化する
ViewAnimator
ビュー間の調整も可能ですお子様は一度に 1 人だけ表示されます。
これらのコレクション ビューは、リモートデータに基づくコレクションを表示するため、
Adapter
を使用してユーザーをバインドする
データへのインターフェースを提供します。Adapter
は、データセットから個々のアイテムをバインドします。
個々の View
オブジェクトに割り当てることもできます。
これらのコレクション ビューはアダプターを基盤としているため、Android フレームワークは
ウィジェットでの使用をサポートするための追加のアーキテクチャが必要です。コンテキスト
ウィジェットの場合、Adapter
は
RemoteViewsFactory
,
Adapter
インターフェースのシンラッパーです。リクエストが
場合、RemoteViewsFactory
が作成して返します。
コレクションのアイテムとして
RemoteViews
オブジェクト。コメントに
コレクション ビューを作成し、RemoteViewsService
を実装して、
RemoteViewsFactory
。
RemoteViewsService
は、リモート アダプターによるリクエストを可能にするサービスです。
RemoteViews
オブジェクト。RemoteViewsFactory
はアダプターのインターフェースです。
コレクション ビュー(ListView
、GridView
、
StackView
、およびそのビューの基になるデータです。StackWidget
より
サンプル、
このサービスを実装するボイラープレート コードの例を以下に示します。
インターフェース:
Kotlin
class StackWidgetService : RemoteViewsService() { override fun onGetViewFactory(intent: Intent): RemoteViewsFactory { return StackRemoteViewsFactory(this.applicationContext, intent) } } class StackRemoteViewsFactory( private val context: Context, intent: Intent ) : RemoteViewsService.RemoteViewsFactory { // See the RemoteViewsFactory API reference for the full list of methods to // implement. }
Java
public class StackWidgetService extends RemoteViewsService { @Override public RemoteViewsFactory onGetViewFactory(Intent intent) { return new StackRemoteViewsFactory(this.getApplicationContext(), intent); } } class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { // See the RemoteViewsFactory API reference for the full list of methods to // implement. }
サンプルアプリ
このセクションのコード抜粋も、StackWidget
サンプル:
このサンプルは、値 0 を表示する 10 個のビューのスタックで構成されています。 表示されます。サンプル ウィジェットの主な動作は次のとおりです。
ユーザーはウィジェットの上面を垂直方向にフリングして次のビューを表示できます。 確認できます。これは組み込みの
StackView
の動作です。ユーザーが操作しなくても、ウィジェットは自動的に スライドショーのように順番に表示できます。これは
android:autoAdvanceViewId="@id/stack_view"
(res/xml/stackwidgetinfo.xml
ファイル。この設定はビュー ID に適用されます。 これはスタックビューのビュー ID ですユーザーがトップビューをタップすると、ウィジェットには
Toast
「タッチビュー n」というメッセージが表示されるここで n は、タップされたビューのインデックス(位置)です。Google Cloud のオペレーションスイートを 動作を実装するには、動作を個々に items セクションにあります。
コレクションを使用してウィジェットを実装する
コレクションを使用するウィジェットを実装するには、次の手順に沿って、
ウィジェットを実行してから、さらにいくつかの手順を実施します。
マニフェストの変更、ウィジェット レイアウトへのコレクション ビューの追加、
AppWidgetProvider
サブクラス。
コレクションを含むウィジェットのマニフェスト
マニフェストを使用して、ウィジェットが
RemoteViewsService
にバインドするコレクションを作成します。そのためには、Terraform で
権限を使用してマニフェスト ファイルに
BIND_REMOTEVIEWS
。
これにより、他のアプリはウィジェットのデータに自由にアクセスできなくなります。
たとえば、RemoteViewsService
を使用して
マニフェスト エントリは次のようになります。
<service android:name="MyWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
この例では、android:name="MyWidgetService"
は
RemoteViewsService
。
コレクションを使用したウィジェットのレイアウト
ウィジェット レイアウト XML ファイルの主な要件は、
コレクション ビュー: ListView
、GridView
、StackView
、または
AdapterViewFlipper
。これは、次の widget_layout.xml
ファイルです。
StackWidget
サンプル:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<StackView
android:id="@+id/stack_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:loopViews="true" />
<TextView
android:id="@+id/empty_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="@drawable/widget_item_background"
android:textColor="#ffffff"
android:textStyle="bold"
android:text="@string/empty_view_text"
android:textSize="20sp" />
</FrameLayout>
空のビューは、 empty view は、空の状態を表します。
ウィジェット全体のレイアウト ファイルに加えて、別のレイアウトを作成します。
コレクション内の各アイテムのレイアウトを定義するファイル(例:
書籍のコレクション内の各書籍のレイアウト。StackWidget
サンプルには次のものがあります。
すべてのアイテムが同じものを使用するため、アイテム レイアウト ファイル widget_item.xml
を 1 つだけにする
できます。
コレクションを持つウィジェットの AppWidgetProvider クラス
通常のウィジェットと同様に、
AppWidgetProvider
サブクラス
一般的に、
onUpdate()
。
作成する際の onUpdate()
の実装の主な違いは、
コレクションを含むウィジェットでは、
setRemoteAdapter()
。これにより、データを取得する場所をコレクション ビューに伝えます。
その後、RemoteViewsService
が次の実装を返します。
RemoteViewsFactory
に定義することで、ウィジェットが適切なデータを提供できます。ユーザーが
このメソッドを呼び出す場合は、
RemoteViewsService
と、更新するウィジェットを指定するウィジェット ID。
たとえば、StackWidget
サンプルで onUpdate()
を実装すると次のようになります。
このコールバック メソッドで、RemoteViewsService
を
ウィジェット コレクション:
Kotlin
override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { // Update each of the widgets with the remote adapter. appWidgetIds.forEach { appWidgetId -> // Set up the intent that starts the StackViewService, which // provides the views for this collection. val intent = Intent(context, StackWidgetService::class.java).apply { // Add the widget ID to the intent extras. putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME)) } // Instantiate the RemoteViews object for the widget layout. val views = RemoteViews(context.packageName, R.layout.widget_layout).apply { // Set up the RemoteViews object to use a RemoteViews adapter. // This adapter connects to a RemoteViewsService through the // specified intent. // This is how you populate the data. setRemoteAdapter(R.id.stack_view, intent) // The empty view is displayed when the collection has no items. // It must be in the same layout used to instantiate the // RemoteViews object. setEmptyView(R.id.stack_view, R.id.empty_view) } // Do additional processing specific to this widget. appWidgetManager.updateAppWidget(appWidgetId, views) } super.onUpdate(context, appWidgetManager, appWidgetIds) }
Java
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // Update each of the widgets with the remote adapter. for (int i = 0; i < appWidgetIds.length; ++i) { // Set up the intent that starts the StackViewService, which // provides the views for this collection. Intent intent = new Intent(context, StackWidgetService.class); // Add the widget ID to the intent extras. intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); // Instantiate the RemoteViews object for the widget layout. RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout); // Set up the RemoteViews object to use a RemoteViews adapter. // This adapter connects to a RemoteViewsService through the specified // intent. // This is how you populate the data. views.setRemoteAdapter(R.id.stack_view, intent); // The empty view is displayed when the collection has no items. // It must be in the same layout used to instantiate the RemoteViews // object. views.setEmptyView(R.id.stack_view, R.id.empty_view); // Do additional processing specific to this widget. appWidgetManager.updateAppWidget(appWidgetIds[i], views); } super.onUpdate(context, appWidgetManager, appWidgetIds); }
データを永続化する
このページで説明するように、RemoteViewsService
サブクラスには次の機能が用意されています。
リモート コレクション ビューの入力に使用される RemoteViewsFactory
。
具体的には、次の手順を行います。
サブクラス
RemoteViewsService
。RemoteViewsService
は、サービスである リモート アダプタがRemoteViews
をリクエストできます。RemoteViewsService
サブクラスに、RemoteViewsFactory
インターフェース。RemoteViewsFactory
は リモート コレクション ビュー(ListView
、GridView
、StackView
、およびそのビューの基になるデータ。お客様の 実装により、各オブジェクトのRemoteViews
オブジェクトが作成されます。 表します。このインターフェースはAdapter
のシンラッパーです。
サービスの単一のインスタンス、またはそこに含まれるデータを使用して、
維持します。静的でない限り、RemoteViewsService
にはデータを保存しないでください。条件
ウィジェットのデータを維持するには、
ContentProvider
のデータが
存続します。たとえば食料品店ウィジェットでは
食料品リストの各アイテムの状態を、サーバー ストレージなどの
SQL データベースです
RemoteViewsService
実装の主な内容は、
RemoteViewsFactory
。次のセクションで説明します。
RemoteViewsFactory インターフェース
RemoteViewsFactory
インターフェースを実装するカスタムクラスでは、
そのコレクション内のアイテムのデータが表示されます。そのために、
は、ウィジェット アイテムの XML レイアウト ファイルをデータのソースと結合します。この
データはデータベースから単純な配列まで何でもかまいません。StackWidget
サンプルの場合、データソースは WidgetItems
の配列です。RemoteViewsFactory
データをリモート コレクション ビューに接着するためのアダプターとして機能します。
診断用の問題に実装する必要がある 2 つの最も重要なメソッドは、
RemoteViewsFactory
サブクラスは
onCreate()
および
getViewAt()
。
初めてファクトリーを作成するときに、システムによって onCreate()
が呼び出されます。
ここでデータソースへの接続やカーソルを設定します。対象
たとえば、StackWidget
サンプルでは、onCreate()
を使用して、
WidgetItem
オブジェクト。ウィジェットがアクティブな場合、システムは
配列内のインデックス位置を使用してオブジェクトを表示し、
できます。
以下は、StackWidget
サンプルの RemoteViewsFactory
からの抜粋です。
onCreate()
メソッドの一部を示す実装です。
Kotlin
private const val REMOTE_VIEW_COUNT: Int = 10 class StackRemoteViewsFactory( private val context: Context ) : RemoteViewsService.RemoteViewsFactory { private lateinit var widgetItems: List<WidgetItem> override fun onCreate() { // In onCreate(), set up any connections or cursors to your data // source. Heavy lifting, such as downloading or creating content, // must be deferred to onDataSetChanged() or getViewAt(). Taking // more than 20 seconds on this call results in an ANR. widgetItems = List(REMOTE_VIEW_COUNT) { index -> WidgetItem("$index!") } ... } ... }
Java
class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { private static final int REMOTE_VIEW_COUNT = 10; private List<WidgetItem> widgetItems = new ArrayList<WidgetItem>(); public void onCreate() { // In onCreate(), setup any connections or cursors to your data // source. Heavy lifting, such as downloading or creating content, // must be deferred to onDataSetChanged() or getViewAt(). Taking // more than 20 seconds on this call results in an ANR. for (int i = 0; i < REMOTE_VIEW_COUNT; i++) { widgetItems.add(new WidgetItem(i + "!")); } ... } ...
RemoteViewsFactory
メソッド getViewAt()
は RemoteViews
オブジェクトを返します。
(データセット内の指定された position
のデータに対応する)を返します。こちらの
StackWidget
サンプルの RemoteViewsFactory
実装からの抜粋:
Kotlin
override fun getViewAt(position: Int): RemoteViews { // Construct a remote views item based on the widget item XML file // and set the text based on the position. return RemoteViews(context.packageName, R.layout.widget_item).apply { setTextViewText(R.id.widget_item, widgetItems[position].text) } }
Java
public RemoteViews getViewAt(int position) { // Construct a remote views item based on the widget item XML file // and set the text based on the position. RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_item); views.setTextViewText(R.id.widget_item, widgetItems.get(position).text); return views; }
個々のアイテムに動作を追加する
前のセクションでは、データをウィジェット コレクションにバインドする方法について説明しました。しかし、 個々のアイテムに動的な動作を追加する場合は、 ありますか?
onUpdate()
を使用してイベントを処理する
クラスでは、
setOnClickPendingIntent()
: オブジェクトのクリック動作を設定します。たとえば、
ボタンにより Activity
が起動されます。しかし、
個々のコレクション アイテムの子ビューに対して、この方法を使用することはできません。
たとえば、setOnClickPendingIntent()
を使用してグローバル ボタンを設定できます。
たとえば、アプリを起動する Gmail ウィジェットには表示されますが、
リストアイテムごとに異なります。
代わりに、コレクション内の個々のアイテムにクリック動作を追加するには、
setOnClickFillInIntent()
。この作業では、VM のペンディング インテント テンプレートを
コレクション ビューに追加してから、コレクション ビュー内の商品アイテムごとに
RemoteViewsFactory
のコレクション。
このセクションでは、StackWidget
サンプルを使用して、動作を追加する方法について説明します。
表示されます。StackWidget
のサンプルでは、ユーザーが上部ビューにタッチすると、
ウィジェットには「タッチビュー n」というメッセージ Toast
が表示されます。ここで、n は
タッチされたビューのインデックス(位置)。次のような仕組みになっています。
StackWidgetProvider
-AppWidgetProvider
サブクラス - 次のカスタム アクションを持つペンディング インテントを作成します。TOAST_ACTION
。ユーザーがビューをタップすると、インテントが起動してブロードキャスト
TOAST_ACTION
。このブロードキャストは、
StackWidgetProvider
クラスのonReceive()
メソッドにより、ウィジェットにToast
メッセージが表示されます。 クリックします。コレクション項目のデータは、RemoteViewsService
経由でRemoteViewsFactory
。
ペンディング インテント テンプレートをセットアップする
StackWidgetProvider
(
AppWidgetProvider
サブクラス)
ペンディング インテントを設定します。コレクションの個々のアイテムに
別のペンディング インテントを使用します。代わりに、コレクション全体でペンディング インテントが設定されます。
各アイテムが入力インテントを設定して、
動作をアイテムごとに指定できます。
このクラスは、ユーザーがタップしたときに送信されるブロードキャストも受け取ります。
表示されます。このイベントを onReceive()
メソッドで処理します。インテントの
アクションが TOAST_ACTION
の場合、ウィジェットは現在の「Toast
」というメッセージを表示します。
表示されます。
Kotlin
const val TOAST_ACTION = "com.example.android.stackwidget.TOAST_ACTION" const val EXTRA_ITEM = "com.example.android.stackwidget.EXTRA_ITEM" class StackWidgetProvider : AppWidgetProvider() { ... // Called when the BroadcastReceiver receives an Intent broadcast. // Checks whether the intent's action is TOAST_ACTION. If it is, the // widget displays a Toast message for the current item. override fun onReceive(context: Context, intent: Intent) { val mgr: AppWidgetManager = AppWidgetManager.getInstance(context) if (intent.action == TOAST_ACTION) { val appWidgetId: Int = intent.getIntExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID ) // EXTRA_ITEM represents a custom value provided by the Intent // passed to the setOnClickFillInIntent() method to indicate the // position of the clicked item. See StackRemoteViewsFactory in // Set the fill-in Intent for details. val viewIndex: Int = intent.getIntExtra(EXTRA_ITEM, 0) Toast.makeText(context, "Touched view $viewIndex", Toast.LENGTH_SHORT).show() } super.onReceive(context, intent) } override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { // Update each of the widgets with the remote adapter. appWidgetIds.forEach { appWidgetId -> // Sets up the intent that points to the StackViewService that // provides the views for this collection. val intent = Intent(context, StackWidgetService::class.java).apply { putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) // When intents are compared, the extras are ignored, so embed // the extra sinto the data so that the extras are not ignored. data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME)) } val rv = RemoteViews(context.packageName, R.layout.widget_layout).apply { setRemoteAdapter(R.id.stack_view, intent) // The empty view is displayed when the collection has no items. // It must be a sibling of the collection view. setEmptyView(R.id.stack_view, R.id.empty_view) } // This section makes it possible for items to have individualized // behavior. It does this by setting up a pending intent template. // Individuals items of a collection can't set up their own pending // intents. Instead, the collection as a whole sets up a pending // intent template, and the individual items set a fillInIntent // to create unique behavior on an item-by-item basis. val toastPendingIntent: PendingIntent = Intent( context, StackWidgetProvider::class.java ).run { // Set the action for the intent. // When the user touches a particular view, it has the effect of // broadcasting TOAST_ACTION. action = TOAST_ACTION putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME)) PendingIntent.getBroadcast(context, 0, this, PendingIntent.FLAG_UPDATE_CURRENT) } rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent) appWidgetManager.updateAppWidget(appWidgetId, rv) } super.onUpdate(context, appWidgetManager, appWidgetIds) } }
Java
public class StackWidgetProvider extends AppWidgetProvider { public static final String TOAST_ACTION = "com.example.android.stackwidget.TOAST_ACTION"; public static final String EXTRA_ITEM = "com.example.android.stackwidget.EXTRA_ITEM"; ... // Called when the BroadcastReceiver receives an Intent broadcast. // Checks whether the intent's action is TOAST_ACTION. If it is, the // widget displays a Toast message for the current item. @Override public void onReceive(Context context, Intent intent) { AppWidgetManager mgr = AppWidgetManager.getInstance(context); if (intent.getAction().equals(TOAST_ACTION)) { int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); // EXTRA_ITEM represents a custom value provided by the Intent // passed to the setOnClickFillInIntent() method to indicate the // position of the clicked item. See StackRemoteViewsFactory in // Set the fill-in Intent for details. int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0); Toast.makeText(context, "Touched view " + viewIndex, Toast.LENGTH_SHORT).show(); } super.onReceive(context, intent); } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // Update each of the widgets with the remote adapter. for (int i = 0; i < appWidgetIds.length; ++i) { // Sets up the intent that points to the StackViewService that // provides the views for this collection. Intent intent = new Intent(context, StackWidgetService.class); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); // When intents are compared, the extras are ignored, so embed // the extras into the data so that the extras are not // ignored. intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout); rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent); // The empty view is displayed when the collection has no items. It // must be a sibling of the collection view. rv.setEmptyView(R.id.stack_view, R.id.empty_view); // This section makes it possible for items to have individualized // behavior. It does this by setting up a pending intent template. // Individuals items of a collection can't set up their own pending // intents. Instead, the collection as a whole sets up a pending // intent template, and the individual items set a fillInIntent // to create unique behavior on an item-by-item basis. Intent toastIntent = new Intent(context, StackWidgetProvider.class); // Set the action for the intent. // When the user touches a particular view, it has the effect of // broadcasting TOAST_ACTION. toastIntent.setAction(StackWidgetProvider.TOAST_ACTION); toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]); intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent, PendingIntent.FLAG_UPDATE_CURRENT); rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent); appWidgetManager.updateAppWidget(appWidgetIds[i], rv); } super.onUpdate(context, appWidgetManager, appWidgetIds); } }
フィルイン インテントを設定する
RemoteViewsFactory
で、
ありますこれにより、個々のクリック アクションを区別できます。
グループ化します入力インテントが
PendingIntent
テンプレート:
アイテムがタップされたときに実行される最終的なインテント。
Kotlin
private const val REMOTE_VIEW_COUNT: Int = 10 class StackRemoteViewsFactory( private val context: Context, intent: Intent ) : RemoteViewsService.RemoteViewsFactory { private lateinit var widgetItems: List<WidgetItem> private val appWidgetId: Int = intent.getIntExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID ) override fun onCreate() { // In onCreate(), set up any connections or cursors to your data source. // Heavy lifting, such as downloading or creating content, must be // deferred to onDataSetChanged() or getViewAt(). Taking more than 20 // seconds on this call results in an ANR. widgetItems = List(REMOTE_VIEW_COUNT) { index -> WidgetItem("$index!") } ... } ... override fun getViewAt(position: Int): RemoteViews { // Construct a remote views item based on the widget item XML file // and set the text based on the position. return RemoteViews(context.packageName, R.layout.widget_item).apply { setTextViewText(R.id.widget_item, widgetItems[position].text) // Set a fill-intent to fill in the pending intent template. // that is set on the collection view in StackWidgetProvider. val fillInIntent = Intent().apply { Bundle().also { extras -> extras.putInt(EXTRA_ITEM, position) putExtras(extras) } } // Make it possible to distinguish the individual on-click // action of a given item. setOnClickFillInIntent(R.id.widget_item, fillInIntent) ... } } ... }
Java
public class StackWidgetService extends RemoteViewsService { @Override public RemoteViewsFactory onGetViewFactory(Intent intent) { return new StackRemoteViewsFactory(this.getApplicationContext(), intent); } } class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { private static final int count = 10; private List<WidgetItem> widgetItems = new ArrayList<WidgetItem>(); private Context context; private int appWidgetId; public StackRemoteViewsFactory(Context context, Intent intent) { this.context = context; appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); } // Initialize the data set. public void onCreate() { // In onCreate(), set up any connections or cursors to your data // source. Heavy lifting, such as downloading or creating // content, must be deferred to onDataSetChanged() or // getViewAt(). Taking more than 20 seconds on this call results // in an ANR. for (int i = 0; i < count; i++) { widgetItems.add(new WidgetItem(i + "!")); } ... } // Given the position (index) of a WidgetItem in the array, use the // item's text value in combination with the widget item XML file to // construct a RemoteViews object. public RemoteViews getViewAt(int position) { // Position always ranges from 0 to getCount() - 1. // Construct a RemoteViews item based on the widget item XML // file and set the text based on the position. RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_item); rv.setTextViewText(R.id.widget_item, widgetItems.get(position).text); // Set a fill-intent to fill in the pending // intent template that is set on the collection view in // StackWidgetProvider. Bundle extras = new Bundle(); extras.putInt(StackWidgetProvider.EXTRA_ITEM, position); Intent fillInIntent = new Intent(); fillInIntent.putExtras(extras); // Make it possible to distinguish the individual on-click // action of a given item. rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent); // Return the RemoteViews object. return rv; } ... }
コレクション データを最新の状態に保つ
図 2 は、コレクションを使用するウィジェットの更新フローを示しています。内容
ウィジェット コードが RemoteViewsFactory
とやり取りする方法と、
更新をトリガーします。
コレクションを使用するウィジェットでは、ユーザーに最新のコンテンツを提供できます。対象
たとえば Gmail ウィジェットでは、受信トレイの状況が一目でわかります。これを実現するには、
RemoteViewsFactory
とコレクション ビューをトリガーして、
表示されます。
これを行うには、
AppWidgetManager
で発信
notifyAppWidgetViewDataChanged()
。この呼び出しにより、RemoteViewsFactory
オブジェクトの
onDataSetChanged()
メソッドを使用すると、新しいデータをフェッチできます。
処理負荷の高いオペレーションは、同じプロジェクト内で同期的に実行できます。
onDataSetChanged()
コールバック。この通話は確実に終了します
メタデータまたはビューデータが RemoteViewsFactory
から取得される前に通知を受け取ります。マイページ
getViewAt()
内で処理負荷の高いオペレーションを実行することもできます。
メソッドを呼び出します。この呼び出しに時間がかかる場合、
RemoteViewsFactory
オブジェクト
getLoadingView()
メソッド - コレクション ビューの対応する位置に表示されます。
返されます。
RemoteCollectionItems を使用してコレクションを直接渡す
Android 12(API レベル 31)では、setRemoteAdapter(int viewId,
RemoteViews.RemoteCollectionItems
items)
が追加されています。
メソッドを使用すると、アプリで値を設定するときに、アプリがコレクションを直接渡すことができます。
コレクションビューが表示されます。この方法でアダプタを設定した場合、
RemoteViewsFactory
を実装します。このインターフェースを
notifyAppWidgetViewDataChanged()
。
この方法では、アダプターへのデータ入力が簡単になるだけでなく、
ユーザーがリストを下にスクロールしたときに新しいアイテムが入力されるまでの遅延を解消します。
新しいアイテムを表示します。以下の条件においては、この方法が推奨されます。
コレクション アイテムのセットが比較的少ない場合です。ただし、たとえば、
コレクションに多数の Bitmaps
が含まれていると、アプローチがうまくいきません。
setImageViewBitmap
に渡されます。
コレクションで一定のレイアウト セットを使用していない場合は、
一部のアイテムのみ存在する場合は、setViewTypeCount
を使用して
コレクションに含めることができる一意のレイアウトの最大数。これにより、
アプリ ウィジェットを更新する際に再利用できます。
簡素化された RemoteViews
コレクションを実装する方法の例を次に示します。
Kotlin
val itemLayouts = listOf( R.layout.item_type_1, R.layout.item_type_2, ... ) remoteView.setRemoteAdapter( R.id.list_view, RemoteViews.RemoteCollectionItems.Builder() .addItem(/* id= */ ID_1, RemoteViews(context.packageName, R.layout.item_type_1)) .addItem(/* id= */ ID_2, RemoteViews(context.packageName, R.layout.item_type_2)) ... .setViewTypeCount(itemLayouts.count()) .build() )
Java
List<Integer> itemLayouts = Arrays.asList( R.layout.item_type_1, R.layout.item_type_2, ... ); remoteView.setRemoteAdapter( R.id.list_view, new RemoteViews.RemoteCollectionItems.Builder() .addItem(/* id= */ ID_1, new RemoteViews(context.getPackageName(), R.layout.item_type_1)) .addItem(/* id= */ ID_2, new RemoteViews(context.getPackageName(), R.layout.item_type_2)) ... .setViewTypeCount(itemLayouts.size()) .build() );