2018年9月7日金曜日

Android Activity Transitions の対象をグループ化する

ActivityTransition に Slide を指定すると、デフォルトでは View ごとに別々にアニメーションします。

例えばボタンを縦に並べた Activity に Slide で enter すると、スライド中はボタンの間隔が広がって、徐々に詰まっていきます。

左 → 右 : スライド中


ボタン同士の配置そのままに Slide させるには、ボタンの親の ViewGroup の setTransitionGroup() で true をセットします。 class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) button.setOnClickListener { startActivity( Intent(this, MainActivity2::class.java), ActivityOptions.makeSceneTransitionAnimation(this).toBundle() ) } } } class MainActivity2 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.requestFeature(Window.FEATURE_CONTENT_TRANSITIONS) window.enterTransition = Slide() window.exitTransition = Slide() setContentView(R.layout.activity_main2) // これを追加 constraintLayout.isTransitionGroup = true } }

左 → 右 : スライド中



解説

ViewGroup の captureTransitioningViews() で isTransitionGroup() が false の場合、各子 View の captureTransitioningViews() を呼びます。 View の captureTransitioningViews() では VISIBLE な場合自身を transition するリストに追加します。

つまり、ViewGroup の setTransitionGroup() で true をセットすると、その ViewGroup が transition するリストに追加され、子 View はされなくなります。 public abstract class ViewGroup ... { ... /** @hide */ @Override public void captureTransitioningViews(List<View> transitioningViews) { if (getVisibility() != View.VISIBLE) { return; } if (isTransitionGroup()) { transitioningViews.add(this); } else { int count = getChildCount(); for (int i = 0; i < count; i++) { View child = getChildAt(i); child.captureTransitioningViews(transitioningViews); } } } ... } public class View ...{ ... public void captureTransitioningViews(List<View> transitioningViews) { if (getVisibility() == View.VISIBLE) { transitioningViews.add(this); } } ... }


0 件のコメント:

コメントを投稿