AdroidのToastを自作する方法

Androidアプリでユーザへの通知によく利用されるものの一つが「Toast」である。
簡潔なコードで記述でき、ユーザの注意を引くことができる。

今回はToastの様なものを自作する方法を紹介する。

元々存在するToastを自作する理由としては、自作する事により自由自在なToastを表示することができるためである。

<方法概要>

1.drawableディレクトリにshapeファイルを作成する
2.layoutディレクトリにviewファイルを作成する
3.自作Toastを表示するためのクラスを作成する

<方法詳細>

1.drawableディレクトリにshapeファイルを作成する

プロジェクトツリーの「res/drawable」で右クリックし、「New」->「Drawable resource file」を選択する。
f:id:MoonMtLab:20161101052722p:plain

表示されたダイアログに対し「File name」に「original_toast_shape」(任意の名前)、「Root element」に「shape」を入力し、「OK」ボタンを押下する。
f:id:MoonMtLab:20161101052753p:plain

drawableディレクトリの配下に「original_toast_shape.xml」ファイルが作成された事を確認する。
f:id:MoonMtLab:20161101052805p:plain

「original_toast_shape.xml」ファイルに下記の定義を加える。

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- 角丸の定義 -->
    <corners android:radius="15dp" />

    <!-- 背景色の定義 -->
    <solid android:color="#88AFEEEE" />

</shape>
2.layoutディレクトリにviewファイルを作成する

プロジェクトツリーの「res/layout」で右クリックし、「New」->「Layout resource file」を選択する
f:id:MoonMtLab:20161101052823p:plain

表示されたダイアログに対し「File name」に「original_toast_view」(任意の名前)、「Root element」に「RelativeLaout」を入力し、「OK」ボタンを押下する。
f:id:MoonMtLab:20161101052840p:plain

layoutディレクトリの配下に「original_toast_view.xml」ファイルが作成された事を確認する。
f:id:MoonMtLab:20161101052854p:plain

「original_toast_view.xml」ファイルを編集する。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="20dp">

    <TextView
        android:id="@+id/textMessage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:padding="20dp"
        android:textColor="#edafce"
        android:textSize="20dp"
        android:background="@drawable/original_toast_shape"/>
        <!-- ↑↑↑ original_toast_shapeを適用することで角丸を実現している -->

</RelativeLayout>

[ポイント]
TextViewの「android:background」に手順1で作成したshapeファイル「original_toast_shape」を設定することで、表示される自作Toastを角丸にすることができる。

3.自作Toastを表示するためのクラスを作成する

Androidに元々用意されたいるToastとインターフェイスをなるべく合わせるため、「OriginalToast」クラスを作成する。

「MainActivity」があるパッケージを右クリックし、「New」->「Java Class」を選択する。
f:id:MoonMtLab:20161101052919p:plain

表示されたダイアログに対し、「Name」に「OriginalToast」(任意の名前)、「Kind」に「Class」を入力し、「OK」ボタンを押下する。
f:id:MoonMtLab:20161101052931p:plain

作成された「OriginalToast.java」ファイルを編集する。

package biz.accele.sampleoriginaltoast;

import android.app.Activity;
import android.content.Context;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;

public class OriginalToast {

    private static Context _context;
    private static String  _message;
    private static int     _dispTime;

    public static OriginalToast makeText(Context context, String message, int dispTime){

        _context  = context;
        _message  = message;
        _dispTime = dispTime;

        return new OriginalToast();
    }

    public void show(){

        // ルートビューを取得する
        final View rootView = ((Activity)_context).findViewById(android.R.id.content).getRootView();

        // 自作Toast用(手順2で作成)のViewを取得する
        final RelativeLayout layout = (RelativeLayout) (((Activity)_context).getLayoutInflater().inflate(R.layout.original_toast_view, null));

        // 自作Toast用のViewからメッセージを表示するためのTextViewを取得する
        TextView textView =  (TextView)layout.findViewById(R.id.textMessage);

        // 表示するテキストを設定する
        textView.setText(_message);

        // ルートビューに自作Toast用のViewをaddする
        ((ViewGroup)rootView).addView(layout, new RelativeLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));

        // 自作Toastの削除を予約する
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {

                ((ViewGroup)rootView).removeView(layout);

            }
        }, _dispTime);
    }
}

<使用方法>

下記のコードで自作Toastを表示する事ができる。
Androidに元々用意されているToastに近い記述で、自作Toastを表示できることがわかる。

OriginalToast.makeText(<Context>, <表示する文字列>, <表示する時間(ミリ秒)>).show();

以下にボタンを押下したタイミングで、自作Toastを表示する例を示す。

MainActivity.java

package biz.accele.sampleoriginaltoast;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btn1 = (Button)findViewById(R.id.btn1);
        btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                // 手順3で作成した「OriginalToast」クラスを使用して自作Toastを表示する
                // 下記の場合「本日は晴天なり」が3秒間表示される
                OriginalToast.makeText(MainActivity.this, "本日は晴天なり", 3000).show();
            }
        });
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="biz.accele.sampleoriginaltoast.MainActivity">

    <Button
        android:id="@+id/btn1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="自作Toast表示"/>

</RelativeLayout>

<実行結果>

f:id:MoonMtLab:20161101052953p:plain

Enjoy Programing!!