TransitionManagerについて

qnote Advent Calendar 私の投稿は二回目

先日、日本Androidの会主催のAndroid Bazaar and Conferenceに行ってきました。
こんなものがあったのかと思いまして、備忘録兼情報共有ということで書かせていただきます。

#とりあえず動画を見てください

まず公演の動画を見ていただくのが一番かと思いますので、URLを貼っておきます。
40分程ありますので、時間がある時に見てください。必見です。
https://www.youtube.com/watch?v=YMmuuuB-uxM

個人的にかなり勉強になりました。
基礎が大事。心にぐざぐざ刺さります。
そして驚いたのがTransitionManagerについて、サポートライブラリが出ていたということ。(勉強不足で申し訳ないです。。)
TransitionManagerは何となく知っていましたが、古いバージョンで使えなきゃ意味ないね。と完全にスルーしていました。

#確認

という事でかんたんに自分でも実装をしてみました。
TransitionManagerの入っているtransitionライブラリはSDKVersion14から使えます。
世の中に2.3系の端末は減ってきているのでほぼ使えるものであると思います。

build.gradleの中身はこんな感じにします。

```build.gradle
apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "24.0.1"
    defaultConfig {
        applicationId "exsample.yamada.samplesupporttransition"
        minSdkVersion 14
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile "com.android.support:support-v4:25.0.1" //追加
    compile 'com.android.support:appcompat-v7:25.0.1'
    compile 'com.android.support:transition:25.0.1' //追加
    testCompile 'junit:junit:4.12'
}

```

検証のためなので特に画面にはこだわらずかんたんに書き足してきます。

```MainaActivity.java
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.visible_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                TransitionManager.beginDelayedTransition((ViewGroup) findViewById(R.id.activity_main));
                TextView textView = (TextView) findViewById(R.id.text);
                textView.setVisibility(textView.getVisibility() == View.VISIBLE ? View.GONE : View.VISIBLE);
            }
        });

        findViewById(R.id.height_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                TransitionManager.beginDelayedTransition((ViewGroup) findViewById(R.id.activity_main));
                TextView textView = (TextView) findViewById(R.id.text);
                ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
                DisplayMetrics metrics = getResources().getDisplayMetrics();
                layoutParams.height = layoutParams.height == 0 ? (int) (20 * metrics.density) : 0;
                textView.setLayoutParams(layoutParams);
            }
        });

        findViewById(R.id.translation_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                TransitionManager.beginDelayedTransition((ViewGroup) findViewById(R.id.activity_main));
                TextView textView = (TextView) findViewById(R.id.text);
                DisplayMetrics metrics = getResources().getDisplayMetrics();
                int offset = (int) (300 * metrics.density);
                ViewCompat.setTranslationY(textView,  ViewCompat.getTranslationY(textView) == 0 ? offset : 0);
            }
        });

        findViewById(R.id.offset_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                TransitionManager.beginDelayedTransition((ViewGroup) findViewById(R.id.activity_main));
                TextView textView = (TextView) findViewById(R.id.text);
                DisplayMetrics metrics = getResources().getDisplayMetrics();
                int offset = (int) (300 * metrics.density);
                ViewCompat.offsetTopAndBottom(textView,  textView.getY() == 0 ? offset : -offset);
            }
        });
    }
}
```

```activity_main.xml
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    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"
    tools:context="exsample.yamada.samplesupporttransition.MainActivity">

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="20dp"
        android:text="Hello World!"/>

    <Button
        android:id="@+id/visible_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="visible"/>

    <Button
        android:id="@+id/height_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="85dp"
        android:layout_marginTop="20dp"
        android:text="height"/>

    <Button
        android:id="@+id/translation_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="170dp"
        android:layout_marginTop="20dp"
        android:text="translation"/>

    <Button
        android:id="@+id/offset_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:text="offset"/>
</RelativeLayout>

```

MainActivityにはボタンのアクションを追加しています。
ただ単にTextViewのvisibilityの切り替え、大きさや高さの変更を行っているのみです。
これだけで勝手にアニメーションを追加してくれるのです。

変更前に

```java
TransitionManager.beginDelayedTransition((ViewGroup) findViewById(R.id.activity_main));
```

とさえ書けば。

ここではrootViewをMainActivityとしていますが親のviewをセットすれば問題ないかと思います。
ListViewtの行内で行う場合には行のレイアウトを指定すれば良いのかな。(未確認です)

とても簡単ですね〜。
自分でアニメーションを書くとAnimationLisienerだのいろいろ書かなくてはなりませんが、一行足すのみでOKです。
アニメーションの途中で元に戻すのも問題なく行なってくれます。
もっと早く知っていれば、使える場面がたくさんあったのに。。。

実装してみて気になったのがViewCompat.setTranslationYを行うとアニメーションが効かないこと。
ViewCompat.offsetTopAndBottomは問題ないので何かあるのかな？

#まとめ
サポートライブラリ等の資料の見直しを行わなくては。
自分の知らない掘り出し物があるかも
もっともっと精進あるのみ！