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

MaterialShowcaseViewでAndroidアプリのチュートリアルを実装する

More than 1 year has passed since last update.

私が作ったRSSリーダーでチュートリアルを追加しました。というのもインストールされてもすぐアンインストールされているようで、説明が足りなかったかな・・・と思い始めたためです。
実装を自分でやってもよかったのですが、デザイン的なセンスがないのと、ある程度テンプレート化されたものがあるのではということでライブラリを探しました。
今回はMaterialShowcaseViewというライブラリを使ってチュートリアルを実装してみました。

tutorial

設定

GitHubのページ通りにbuild.gradleを編集

プロジェクトのbuild.gradle

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

アプリのbuild.gradle

dependencies {
  compile 'com.github.deano2390:MaterialShowcaseView:1.1.0@aar'
}

使い方

MaterialShowcaseViewでは特定のViewにハイライトを当ててチュートリアルを行います。
実装できるパターンとしては、(1)単純に追加ボタンなど1つだけを説明するパターンと、(2)ボタン1を押して次にボタン2を押して・・・といったように連続して説明をするパターンがあります。

今回の場合は最初のRSS購読のチュートリアルを入れました。
RSS購読の流れとしては

  1. メイン画面からToolbarの「+」ボタンを押し、検索画面に行く(メイン画面)
  2. RSSを購読するサイト検索する(検索画面)
  3. サイトを開いたら追加ボタンを押す(検索画面)

です。

まずメイン画面で実装した単純に追加ボタンなど1つだけを説明するパターンです。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Menu settings...

    // Start tutorial at first time
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            View view = findViewById(R.id.add);
            new MaterialShowcaseView.Builder(TopActivity.this)
                    .setTarget(view)
                    .setContentText(R.string.tutorial_go_to_search_rss_description)
                    .setDismissText(R.string.tutorial_next)
                    .singleUse(SHOWCASE_ID)
                    .setListener(new IShowcaseListener() {
                        @Override
                        public void onShowcaseDisplayed(MaterialShowcaseView materialShowcaseView) {

                        }

                        @Override
                        public void onShowcaseDismissed(MaterialShowcaseView materialShowcaseView) {
                            goToRssSearch();
                        }
                    })
                    .show();
        }
    });
    return true;
}

Builderパターンを使ってMaterialShowcaseView.Builderを作成していきます。今回はToolbar上の「+」ボタン(R.id.add)にハイライトを当てたかったのでonCreateOptionsMenu()の中でチュートリアルを作成します。
まずsetTarget()でハイライトするViewを指定します。次にチュートリアルの説明文と、チュートリアルを消す部分のテキストを設定します。singleUse()でIDを指定することで初回のみチュートリアルを表示し、同じIDのチュートリアルは今後表示しないように設定できます。今回はチュートリアルが閉じたときに次の画面(検索画面)に移りたかったので、setListener()でIShowcaseListenerをセットし、チュートリアルが閉じられたときに呼ばれるonShowcaseDismissed()で次の画面に飛んでいます。設定が終わったら最後にshow()でチュートリアルを表示します。

使ったメソッドのまとめです。

メソッド 説明
setTarget(View view) ハイライトするViewを指定
setContentText(int resource) 説明文を指定
setDismissText(int resource) タップして閉じる部分の文を指定
singleUse(String showCaseId) 1度だけの表示を管理するためのID。これを設定するとアンインストールしない限りは同じIDのチュートリアルは表示されない
setListener(IShowcaseListener listener) リスナの設定。表示時、消えた時のハンドリング
show() 表示する

次に検索画面で実装した連続して説明をするパターンです。

@Override
public boolean onCreateOptionsMenu(Menu menu) { 
    // Menu settings...

    // Start tutorial at first time
    new Handler().post(new Runnable() {
        @Override
        public void run() {
            View view = findViewById(R.id.search_rss);
            ShowcaseConfig config = new ShowcaseConfig();
            config.setDelay(500); // half second between each showcase view

            MaterialShowcaseSequence sequence = new MaterialShowcaseSequence(FeedSearchActivity.this, SHOWCASE_ID);
            sequence.setConfig(config);

            // Search tutorial
            sequence.addSequenceItem(
                    new MaterialShowcaseView.Builder(FeedSearchActivity.this)
                            .setTarget(view)
                            .setContentText(R.string.tutorial_search_rss_description)
                            .setDismissText(R.string.tutorial_next)
                            .build()
            );

            // Add button tutorial
            sequence.addSequenceItem(
                    new MaterialShowcaseView.Builder(FeedSearchActivity.this)
                            .setTarget(fab)
                            .setContentText(R.string.tutorial_add_rss_description)
                            .setDismissText(R.string.tutorial_close)
                            .setDismissOnTouch(true)
                            .build()
            );

            // Open software keyboard if tutorial already finished
            if (sequence.hasFired()) {
                searchView.setIconified(false);
            }

            sequence.start();
        }
    });
    return true;
}

今度はMaterialShowcaseSequenceというクラスのインスタンスを作り、MaterialShowcaseViewのインスタンスを追加していってチュートリアルの流れを作ります。

さきほどと同様にBuilderパターンでMaterialShowcaseView.Builderを作っていき、今回は最後にbuild()を呼ぶことでMaterialShowcaseViewを作り、MaterialShowcaseSequenceに追加します。これを繰り返すことでチュートリアルを表示→閉じる→チュートリアルを表示→閉じる→・・・と流れを作れます。作り終わったらstart()でチュートリアルを始めます。

注意した点

Toolbar上のViewがNullになる

onCreateOptionsMenu()の中でViewをfindViewById()で取るとNullが返ってきて落ちるという現象がありました。Handler#post()を使うことで遅延を発生させてこれを回避しました。

参考

How To Get Action View Of Menu Item?

チュートリアル中にキーボードが開かないようにする

検索画面では開いたときにすぐキーボードが開くようにsearchView.setIconified(false)を呼んでいたのですが、チュートリアル中は邪魔です。MaterialShowcaseSequence#hasFired()でチュートリアルが既に終わったかを判定できるので、チュートリアルでないときのみキーボードを開くようにしました。

// Open software keyboard if tutorial already finished
if (sequence.hasFired()) {
    searchView.setIconified(false);
}

終わりに

MaterialShowcaseViewを使うことでかなり簡単にチュートリアルを作成しました。さくっと作れるので、凝ったチュートリアルが必要でなければこれで十分かなと思います。以上です。

Why do not you register as a user and use Qiita more conveniently?
  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
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