LoginSignup
71
70

More than 5 years have passed since last update.

画面遷移を滑らかに (Activity Transitions)

Posted at

今更ながらActivity Transitions

Android Developersを読みながら,Activity Transitionsを実装しました.
ezgif.com-optimize.gif
やったことを書きます.

手順

やったことは大きく分けて3つでした.

  1. Activity Transitions用のテーマの作成
  2. 2つのActivityで共有するViewを決める
  3. startActivityをActivity Transitons用に書き換える

ActivityTransitions用のテーマの作成

今のテーマはこうなってます.

res/values/styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/primary</item>
    <!-- 省略 -->
</style>

それをこうしておきます.

res/values/styles.xml
<style name="AppTheme" parent="AppTheme.Base" />

<style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/primary</item>
    <!-- 省略 -->
</style>

AppThemeにあった内容を,新しく作ったAppTheme.Baseに移しました.

ActivityTransitionsに必要な属性は,minSdkVersionが21以上でないと使えません.
minSdkVersionは変えたくないので,res/values-v21/styles.xmlで属性の追加を行います.

res/values-v21/styles.xmlを作成し,以下の内容を書きます.

res/values-v21/styles.xml
   <style name="AppTheme" parent="AppTheme.Base">    <!-- AppTheme.Baseを継承 -->
        <item name="android:windowContentTransitions">true</item>
        <item name="android:windowAllowEnterTransitionOverlap">true</item>
        <item name="android:windowAllowReturnTransitionOverlap">true</item>
        <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>
        <item name="android:windowSharedElementExitTransition">@android:transition/move</item>
    </style>

AppTheme.Baseを作ったのは,ここで余計なコードを書かないためです.

そして,遷移を行う2つのアクティビティImageListActivityImageDetailActivityに,
このテーマを適用します.

AndroidManifest.xml
<activity
    android:name=".ui.ImageListActivity"
    android:theme="@style/AppTheme">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name=".ui.ImageDetailActivity"
    android:theme="@style/AppTheme" />

これで,テーマの設定は完了です.

2つのActivityで共有するViewを決める

リストから詳細画面への遷移なので,クリックした画像(ImageView)を共有することにします.
変更するのは,共有するViewを定義している2つのレイアウトファイルです.

こちらも,minSdkVersionが21より小さいアプリでも対応できるよう,
res/layout-v21というディレクトリを作って,そちらに変更を行ったファイルを置いていきます.

具体的には,
res/layout/row_list.xmlは,res/layout-v21/row_list.xmlにコピーして,res/layout-v21/row_list.xmlの方で変更を行います.

では,res/layout-v21にコピーした,リストのlayout定義ファイルのImageViewに変更を加えます.
ListViewのArrayAdapterの中で,このように使っているレイアウトファイルのことです.
convertView = mInflater.inflate(R.layout.row_list, parent, false);

res/layout-v21/row_list.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/row_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/row_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:transitionName="@string/trans_name" />    <!-- new line -->

    <!-- 省略 -->

android:transitionName="@string/trans_name"を共有したいImageViewの属性に追加しました.
@string/trans_nameは下のように定義した,ただの文字列です.

res/values/strings.xml
<string name="trans_name">list_to_detail</string>

詳細画面のレイアウトファイルでも同じことをします.

res/layout-v21/activity_detail.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/detail_parent"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/detail_image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:transitionName="@string/trans_name" />    <!-- new line -->

    <!-- 省略 -->

android:transitionName="@string/trans_name"を共有したいImageViewの属性に追加しました.

このandroid:transitionNameによって,
リストの画像は詳細画面のどこに移動すれば良いのか分かるようになります.

あとは,startActivityの部分を書き換えれば完成です.

startActivityをActivityTransitions用に書き換える

リストのクリックに合わせて詳細画面に行く部分はこんな感じでした.

ImageListActivity.java
mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        ListItem item = mAdapter.getItem(position);
        Intent intent = new Intent(mActivity, ImageDetailActivity.class);
        intent.putExtra(ImageDetailActivity.EXTRA_CONTENT, item.toJson());
        startActivity(intent);
    }
});

それがこうなります.

ImageListActivity.java
mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
             mActivity,
             view.findViewById(R.id.row_image),
             getString(R.string.trans_name) );
         ListItem item = mAdapter.getItem(position);
         Intent intent = new Intent(mActivity, ImageDetailActivity.class);
         intent.putExtra(ImageDetailActivity.EXTRA_CONTENT, item.toJson());
         ActivityCompat.startActivity(activity, intent, options.toBundle());
    }
});

これで完成です.

最後に

GitHubにあった,MaterialEverywhereMaterialDesignSampleが,とても参考になりました.

参考URL

71
70
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
71
70