techium

このブログは何かに追われないと頑張れない人たちが週一更新をノルマに技術情報を発信するブログです。もし何か調査して欲しい内容がありましたら、@kobashinG or @muchiki0226 までいただけますと気が向いたら調査するかもしれません。

MaterialDesignのLoading中のProgressを作る

Motivation

Material Designのガイドラインのコレが気に入ったので、汎用的に使えるようにFragmentで書いてみた。

Progress & activity - Components - Google design guidelines

Progress Barを実装する

Material DesignのProgress BarはSupportLibraryに実装されているものを持ってくればOK。
具体的にはappcompat-v7のstyle="@style/Widget.AppCompat.ProgressBar.Horizontal"を利用する。

        <ProgressBar
                android:id="@+id/progress_bar"
                android:layout_below="@+id/text"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="16dp"
                style="@style/Widget.AppCompat.ProgressBar.Horizontal"
                android:layout_width="144dp"
                android:layout_height="wrap_content"
                android:indeterminate="true"/>

また、テキストについてはtextAppearanceに"@style/TextAppearance.AppCompat.XXXX"を利用すると良い。
XXXXの部分は、ここを参考にして決める。

ここでは、Fragmentの形式で実装したので上記を持つFragmentを生成する。
テンプレと大差無い状態。

public class LoadingFragment extends Fragment {

    public LoadingFragment() {
        // Required empty public constructor
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_loading, container, false);
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }
}

FadeIn/FadeOutを実装する

Fragmentに実装したので、FragmentTransactionを利用して開始時と置き換え時にアニメーションを行う。
FragmentTransactionを利用したアニメーションを作る場合は、FragmentTransaction.setTransitionを使う。
setTransitionに設定したint値に対し、開始/終了時にFragment.onCreateAnimation()が呼び出されるようになる。

まず、Fragment.onCreateAnimation()の実装を行う。

    @Override
    public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
        if(transit == FragmentTransaction.TRANSIT_FRAGMENT_OPEN){
            if(enter){
                return AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in);
            }else{
                return AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out);
            }
        }
        return super.onCreateAnimation(transit, enter, nextAnim);
    }

メソッドの引数のtransitにsetTransitionに指定したint値が指定子として入力される。
また、引数のenterに開始時か終了時かを判断するためのboolean値が入力される。
これらを用いて、Animationクラスを返せば、そのときに指定したアニメーションが実行されるようになる。

Activityからの呼び出し時(Replace/Add)にsetTransitionする

最後にreplace/addする際に、setTransitionすれば期待通りに動作する。

呼び出し時のコードはこちら

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mBinding = DataBindingUtil.setContentView(MainActivity.this, R.layout.activity_main);
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, new LoadingFragment())
                    .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                    .commit();
        }
        getSomething();
    }

setTransitionにFragmentTransaction.TRANSIT_FRAGMENT_OPENを指定している。
それは前述の通り、Fragment.onCreateAnimationでの判断条件に利用している。

サンプルコード

だいたい期待通りに動いている。

GitHub - ShinjiKobayashi/LoadingProgressSample