概要
Android の AppWidget で Snackbar を使う方法について書きます。
What is "Snackbar"?
Toast に似た Android のポップアップ機能です。画面下からせり出し、一定時間が経過したら画面下へと引っ込みます。
特徴
- 色を変えられる
- ユーザに追加のアクションを提示できる
- 下の方に出るので画面描画を阻害しない
- Toast と同じようにすぐ消えるので、重要な通知ではなく確認程度に使う
実装
では早速使ってみましょう。
依存の追加
app/build.gradle に Design Support library の依存を追記して、sync してください。
dependencies {
def supportLibVersion = '25.3.1'
compile 'com.android.support:appcompat-v7:' + supportLibVersion
compile 'com.android.support:support-v4:' + supportLibVersion
compile 'com.android.support:design:' + supportLibVersion
}
メッセージを表示
ごく簡単なものは下記のコードで表示できます。見たところ、Context が View になっているほかは Toast とほぼ同じように書くことができます。
Snackbar.make(view, "Text", Snackbar.LENGTH_SHORT).show();
色を変える
Snackbar は色を変えることが可能です。その場合、一旦オブジェクトを保持して、getView() メソッドで View を取得して、setBackgroundColor
で任意の色を設定します。もちろん透過させることも可能です。
final Snackbar snackbar = Snackbar.make(view, "Text", Snackbar.LENGTH_SHORT);
snackbar.getView().setBackgroundColor(color);
Action
Snackbar はユーザに追加アクションを提示することが可能です。ラベルの Text と、押された時の Action を定義した Listener を setAction で渡します。
snackbar.setAction("Next!", new View.OnClickListener() {
@Override
public void onClick(final View v) {
Toast.makeText(v.getContext(), "Why?", Toast.LENGTH_SHORT).show();
}
});
注意
- AppCompatActivity でないと使えない……レガシーアプリで TabActivity を継承しているような場合は諦める必要がある
- View を必要とする……View を持たない箇所、特に AppWidget では使えない
AppWidget で Snackbar を使う
前述の通り、View を直接操作できない AppWidget では Snackbar を使うことができません。AppWidget 主体のアプリで、せっかくの機能を使えないのは残念なので、何とかならないかと考えました。
正攻法ではないですが、1つのアイデアとしてダミーの透明な Activity を表示し、そこの View を使って Snackbar を表示するというやり方を考えてみました。
サンプルコード
GitHub リポジトリ にアップしてあります。
サンプル GIF
AppWidget の各色をタップすると、その色の Snackbar が表示され、"Next!" と書かれたラベルをタップすると "Why?" という Toast を表示します。新旧共演です。
実装
ポイントになるのは下記の4点です。
- AppCompatActivity を継承
- 透明テーマを使用
- onCreate メソッドでの
overridePendingTransition(0, 0);
で、 Activity 起動時の Transition を無効化 - StatusBar の透明化(APIレベル21以降)
- 自動で finish する Executor タスクの登録
- finish メソッドでの
overridePendingTransition(0, 0);
で、 Activity 終了時の Transition を無効化
下記に詳述します。
1. AppCompatActivity を継承
Snackbar は AppCompatActivity でないと利用できないので、そうしてください。
2. 透明テーマを使用
下記の透明テーマを定義し、
<resources>
<!-- ...... -->
<style name="DummyTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:activityOpenExitAnimation">@null</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowAnimationStyle">@android:style/Animation</item>
<item name="android:windowIsTranslucent">true</item>
</style>
</resources>
AndroidManifest.xml で設定してください。
<activity
android:name=".DummyActivity"
android:label="@string/app_name"
android:theme="@style/DummyTheme"
>
4. StatusBar の透明化(APIレベル21以降)
Window クラスの setStatusBarColor で上のバーを透明に、下のバーを Snackbar と同じ色に設定します。
private void setStatusBarTransparent() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.setStatusBarColor(Color.TRANSPARENT);
window.setNavigationBarColor(mColor);
}
}
5. 自動で finish する Executor タスクの登録
そのままだと透明な Activity が残ってしまって邪魔なので、非同期のタスクで DummyActivity を finish()
させる必要があります。今回は Executors.newSingleThreadExecutor でシンプルにこんな風にしてみました。
private void executeFinisher() {
final ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
finish();
}
});
executorService.shutdown();
}
どうでもいいこと
Snackbar というのは軽食堂や移動アイスクリーム店を指すそうです。snickers ではないみたいです。
終わりに
AppWidget で Snackbar を使う方法について述べました。まともな方法ではなく、今後OSの制限で使えなくなる可能性もあるので、良い子は真似しないでください。
- Snackbar はよりデザイン性に優れユーザフレンドリなポップアップ
- ダミーの Activity を用意すれば AppWidget からでも Snackbar を使える