# Android 转场动画
Android sdk 包里关于转场过度相关的包 android.transition android.transition
此包中的类为视图层次结构启用“场景和转换”功能。
# 转场效果必知
- Scence
Scence 视图层次结构状态的封装,包括该层次结构中的视图以及这些视图具有的各种值(与布局相关和其他)场景可以直接由布局层次结构定义,也可以通过代码定义场景,该场景在输入时动态设置场景。
- Transition
Transition是一种自动为输入新场景时发生的更改动画的机制。一些过渡功能是自动的。也就是说,进入一个场景可能会导致动画运行,淡出视图消失 changeBounds并调整更改的现有视图的大小,并淡化可见的视图。还有其他过渡可以为其他属性设置动画,例如颜色变化并且可以选择指定在特定场景变化期间进行。最后开发人员可以定义自己的Transition子类,这些子类监视特定的属性更改,并在这些属性更改值时运行自定义动画
- TransitionManager
用于指定特定场景更改的自定义过渡,以及使特定过渡发生的场景更改。
秉承着官方有不动手的原则下面的例子来自官方gitHub仓库: android/animation
# 场景一
ActivityA 跳转 ActivityB
ActivityB 退回 ActivityA
ActivityA:
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:columnWidth="120dp"
android:drawSelectorOnTop="true"
android:horizontalSpacing="@dimen/grid_spacing"
android:numColumns="auto_fit"
android:padding="@dimen/grid_spacing"
android:verticalSpacing="@dimen/grid_spacing" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.example.android.activityscenetransitionbasic.SquareFrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageview_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@null"
android:scaleType="centerCrop" />
</com.example.android.activityscenetransitionbasic.SquareFrameLayout>
<TextView
android:id="@+id/textview_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:maxLines="1"
android:padding="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:theme="@style/Theme.AppCompat" />
</LinearLayout>
ActivityB:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.example.android.activityscenetransitionbasic.SquareFrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageview_header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop" />
</com.example.android.activityscenetransitionbasic.SquareFrameLayout>
<TextView
android:id="@+id/textview_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:maxLines="2"
android:padding="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:theme="@style/Theme.AppCompat" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:text="@string/bacon_ipsum"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
</LinearLayout>
</ScrollView>
# 转场
/**
* Called when an item in the {@link android.widget.GridView} is clicked. Here will launch
* the {@link DetailActivity}, using the Scene Transition animation functionality.
*/
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Item item = (Item) adapterView.getItemAtPosition(position);
// Construct an Intent as normal
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
intent.putExtra(DetailActivity.EXTRA_PARAM_ID, item.getId());
// BEGIN_INCLUDE(start_activity)
/*
* Now create an {@link android.app.ActivityOptions} instance using the
* {@link ActivityOptionsCompat#makeSceneTransitionAnimation(Activity, Pair[])} factory
* method.
//该方法 用来创建可转场元素的集合
*/
@SuppressWarnings("unchecked")
ActivityOptionsCompat activityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(
MainActivity.this,
// Now we provide a list of Pair items which contain the view we can transitioning
// from, and the name of the view it is transitioning to, in the launched activity
new Pair<>(view.findViewById(R.id.imageview_item),
DetailActivity.VIEW_NAME_HEADER_IMAGE),
new Pair<>(view.findViewById(R.id.textview_name),
DetailActivity.VIEW_NAME_HEADER_TITLE));
// Now we can start the Activity, providing the activity options as a bundle
ActivityCompat.startActivity(MainActivity.this, intent, activityOptions.toBundle());
// END_INCLUDE(start_activity)
}
@SuppressWarnings("unchecked")
public static ActivityOptionsCompat makeSceneTransitionAnimation(Activity activity,
Pair<View, String>... sharedElements) {
if (Build.VERSION.SDK_INT >= 21) {
android.util.Pair<View, String>[] pairs = null;
if (sharedElements != null) {
pairs = new android.util.Pair[sharedElements.length];
for (int i = 0; i < sharedElements.length; i++) {
pairs[i] = android.util.Pair.create(
sharedElements[i].first, sharedElements[i].second);
}
}
return createImpl(ActivityOptions.makeSceneTransitionAnimation(activity, pairs));
}
return new ActivityOptionsCompat();
}
// BEGIN_INCLUDE(detail_set_view_name)
/*
* Set the name of the view's which will be transition to, using the static values above.
* This could be done in the layout XML, but exposing it via static variables allows easy
* querying from other Activities
*/
ViewCompat.setTransitionName(mHeaderImageView, VIEW_NAME_HEADER_IMAGE);
ViewCompat.setTransitionName(mHeaderTitle, VIEW_NAME_HEADER_TITLE);
// END_INCLUDE(detail_set_view_name)
/**
* Try and add a {@link Transition.TransitionListener} to the entering shared element
* {@link Transition}. We do this so that we can load the full-size image after the transition
* has completed.
*
* @return true if we were successful in adding a listener to the enter transition
* 添加 过渡 动画执行监听
*/
@RequiresApi(21)
private boolean addTransitionListener() {
final Transition transition = getWindow().getSharedElementEnterTransition();
if (transition != null) {
// There is an entering shared element transition so add a listener to it
transition.addListener(new Transition.TransitionListener() {
@Override
public void onTransitionEnd(Transition transition) {
// As the transition has ended, we can now load the full-size image
loadFullSizeImage();
// Make sure we remove ourselves as a listener
transition.removeListener(this);
}
@Override
public void onTransitionStart(Transition transition) {
// No-op
}
@Override
public void onTransitionCancel(Transition transition) {
// Make sure we remove ourselves as a listener
transition.removeListener(this);
}
@Override
public void onTransitionPause(Transition transition) {
// No-op
}
@Override
public void onTransitionResume(Transition transition) {
// No-op
}
});
return true;
}
// If we reach here then we have not added a listener
return false;
}