SnackBar
の内部からActivity
を表示する場合、rootView
を使用できます。しかし、SnackBar
が利用できない場合はService
の内部からView
を表示する必要があります。どうすればこれを達成できますか?
裏話として:アクティビティは、タスクを実行するためのサービスを開始します。 Service
は、状況に応じてSnackBar
を表示する必要があります。そのためだけにService
にバインドしたくありません。では、どうすればこれを達成できますか?通常はToast
を表示できますが、ユーザーがメッセージを読んで確認できるようにする必要があります。
Snackbar
を表示するには、 View
が必要です。したがって、状態に応じてアプリにスナックバーを表示する場合は、 Service
を表示します。 Activity
にバインドするか、 LocalBroadcastManager
を介してメッセージをブロードキャストし、View
にメッセージを表示する必要があります。
それを回避する方法は他にないと思います。何らかの方法でActivity
またはFragment
と通信する必要があります。
スナックバーはコンテキストのみを必要とするトーストとは異なりますので、アプリから表示したい場合は、クラスではできないと思いますAndroidによって提供されます。
設計ガイドライン から:
配置
スナックバーは画面上のほとんどの要素の上に表示され、高さはフローティングアクションボタンと同じです。ただし、ダイアログ、ボトムシート、ナビゲーションドロワーよりも標高が低くなります。
明示的ではありませんが、アプリビュー内にのみ表示されるという結論に達することができます。したがって、繰り返しになりますが、visibleビューと何らかの方法で通信する必要があります。
メッセージのブロードキャストに関するスニペット:
送信者(サービス上)
private void doSendBroadcast(String message) {
Intent it = new Intent("EVENT_SNACKBAR");
if (!TextUtils.isEmpty(message))
it.putExtra(EXTRA_RETURN_MESSAGE,message);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(it);
}
受信者(アクティビティ上)
private BroadcastReceiver mMessageReceiver = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Other stuff.
mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Do something
}
};
}
@Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("EVENT_SNACKBAR"));
}
バインドされたサービスの詳細 ここ 。
そしてLocalBroadcastManager
について この質問について 。
更新:EventBus を使用してvisibleパブリッシャー/サブスクライバーの方法で機能するビュー。 スティッキーイベント の概念を利用して、アプリが再び表示されたらSnackbar
が表示されるようにすることもできます。
イベントバスの使い方については、私の この回答 をご覧ください。
LocalBroadcastManager
内の Service
を介していつでもブロードキャストを送信できます
_LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("SERVICE_DID_SOMETHING"));
_
次に、Activity
で BroadcastReceiver
を使用してSnackbar
を表示します
_private final ServiceReceiver _serviceReceiver = new ServiceReceiver();
@Override
protected void onResume() {
super.onResume();
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("SERVICE_DID_SOMETHING");
LocalBroadcastManager.getInstance(this).registerReceiver(_serviceReceiver, intentFilter);
}
@Override
protected void onPause() {
super.onPause();
try {
LocalBroadcastManager.getInstance(this).unregisterReceiver(_serviceReceiver);
} catch (Exception ex) {
Log.e(TAG, "Error unregistering ServiceReceiver", ex);
}
}
// region ServiceReceiver
private class ServiceReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: Show your Snackbar here...
}
}
// endregion
_
送信したIntent
を使用して、必要に応じて追加のデータを渡し、それをBroadcastReceiver.onReceive(Context context, Intent intent)
で引き出すことができます。
SDKが提供するデフォルトのSnackBar
を使用してこれを行うことはできません。これは、常にビューが必要になるためです。
目的を果たすために、 これ のようなSnackBarを模倣する外部ライブラリを使用できます。
複数のアクティビティにまたがって表示されるアプリケーションコンテキストでスナックバーを作成する方法: https://stackoverflow.com/a/37707741/1185087