Help us understand the problem. What is going on with this article?

Android の AppWidget で Snackbar を使う

More than 1 year has passed since last update.

概要

Android の AppWidget で Snackbar を使う方法について書きます。

What is "Snackbar"?

Toast に似た Android のポップアップ機能です。画面下からせり出し、一定時間が経過したら画面下へと引っ込みます。

特徴

  • 色を変えられる
  • ユーザに追加のアクションを提示できる
  • 下の方に出るので画面描画を阻害しない
  • Toast と同じようにすぐ消えるので、重要な通知ではなく確認程度に使う

実装

では早速使ってみましょう。

依存の追加

app/build.gradle に Design Support library の依存を追記して、sync してください。

app/build.gradle
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

snackbar.gif

AppWidget の各色をタップすると、その色の Snackbar が表示され、"Next!" と書かれたラベルをタップすると "Why?" という Toast を表示します。新旧共演です。

実装

DummyActivity

ポイントになるのは下記の4点です。

  1. AppCompatActivity を継承
  2. 透明テーマを使用
  3. onCreate メソッドでの overridePendingTransition(0, 0); で、 Activity 起動時の Transition を無効化
  4. StatusBar の透明化(APIレベル21以降)
  5. 自動で finish する Executor タスクの登録
  6. finish メソッドでのoverridePendingTransition(0, 0); で、 Activity 終了時の Transition を無効化

下記に詳述します。

1. AppCompatActivity を継承

Snackbar は AppCompatActivity でないと利用できないので、そうしてください。

2. 透明テーマを使用

下記の透明テーマを定義し、

app/src/main/res/values/styles.xml
<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 で設定してください。

app/src/main/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 でシンプルにこんな風にしてみました。

自動で_finish_する_Executor_タスクの登録
    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 を使える

リンク

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした