当看官方文档时,一个脑袋两个大。比较简单的用法,感觉很复杂。
用法到比较简单,分3步走。
1. 创建Scene
定义 Scene对应的布局,这里有两个Scene,对应两个布局item1.xml和item2.xml
item1.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/view1"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="view1"
android:textColor="#FFF"
android:textSize="20dp" />
<TextView
android:id="@+id/view2"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="view2"
android:textColor="#FFF"
android:textSize="20dp" />
</RelativeLayout>
item2.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/view2"
android:layout_width="200dp"
android:layout_height="100dp"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="view2"
android:textColor="#FFF"
android:textSize="20dp" />
<TextView
android:id="@+id/view1"
android:layout_width="200dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="@color/colorAccent"
android:gravity="center"
android:text="view1"
android:textColor="#FFF"
android:textSize="20dp" />
</RelativeLayout>
注意:item1是动画的开始状态,item2是动画的结束状态,其中控件的ID需要一致
在activity的布局中定义一个帧布局FrameLayout作为Scene的rootView。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/rootview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
<include layout="@layout/item1" />
</FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="20dp"
android:orientation="horizontal">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮" />
</LinearLayout>
</LinearLayout>
在Activity中创建Scene:
public class MainActivity extends AppCompatActivity{
//注意当声明帧布局FrameLayout时用的是ViewGroup
private ViewGroup rootView;
private Scene startScene;
private Scene endScene;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//root布局(很重要)
rootView = (ViewGroup) findViewById(R.id.rootview);
//创建场景
startScene = Scene.getSceneForLayout(rootView, R.layout.item1, this);
endScene = Scene.getSceneForLayout(rootView, R.layout.item2, this);
}
}
这样就创建好了Scene。
2.实例化Transition
实例化Transition比较简单就是声明Transition,并new一下就可以了
private Transition transition;
、、、
public void onClick(View view) {
transition = new ChangeBounds();
}
、、、
如果这么简单就不拿出来单独讲了,这只是用的系统的Transition 就比较简单了。我们这里主要讲的是自定义的Transition,学习这里要学会属性动画。
我们先看一下源码:
public abstract class Transition implements Cloneable {
//看字面意思就是保存初始Scene的值
public abstract void captureStartValues(TransitionValues transitionValues);
//保存结束Scene的值
public abstract void captureEndValues(TransitionValues transitionValues);
/**
** @param sceneRoot 转换层次结构的根。
* @param startValues 初始Scene的目标值
* @param endValues 结束Scene的目标值
* 这个方法里根据初始值和结束值通过属性动画来设置动画
*/
public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,TransitionValues endValues) {
return null;
}
}
这是我自定义的Transition,还有点小问题,当没结束再次进行动画时,容易出屏幕。
DefineTransition.java
@TargetApi(Build.VERSION_CODES.KITKAT)
public class DefineTransition extends Transition {
private final static String TOP = "TOP";
private final static String BOTTOM = "BOTTOM";
private final static String LEFT = "LEFT";
private final static String RIGHT = "RIGHT";
//记录开始的状态
@Override
public void captureStartValues(TransitionValues transitionValues) {
View view = transitionValues.view;
Rect rect = new Rect();
view.getHitRect(rect);
//把初始值存储起来
transitionValues.values.put(TOP, rect.top);
transitionValues.values.put(BOTTOM, rect.bottom);
transitionValues.values.put(LEFT, rect.left);
transitionValues.values.put(RIGHT, rect.right);
}
@Override
public void captureEndValues(TransitionValues transitionValues) {
View view = transitionValues.view;
Rect rect = new Rect();
view.getHitRect(rect);
//把结束时的值存起来
transitionValues.values.put(TOP, rect.top);
transitionValues.values.put(BOTTOM, rect.bottom);
transitionValues.values.put(LEFT, rect.left);
transitionValues.values.put(RIGHT, rect.right);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues, TransitionValues endValues) {
if (startValues == null || endValues == null) {
return null;
}
final View endView = endValues.view;
final View startView = startValues.view;
//获取初始值
int startTop = (int) startValues.values.get(TOP);
int startBottom = (int) startValues.values.get(BOTTOM);
int startRight = (int) startValues.values.get(RIGHT);
int startLeft = (int) startValues.values.get(LEFT);
//获取结束值
int endTop = (int) endValues.values.get(TOP);
int endBottom = (int) endValues.values.get(BOTTOM);
int endRight = (int) endValues.values.get(RIGHT);
int endLeft = (int) endValues.values.get(LEFT);
//使用属性动画对特定的空间进行动画的设置
if (endView.getId() == R.id.view2) {
ValueAnimator animator;
if (startLeft == 0) {
int a = startLeft;
startLeft = -endLeft;
endLeft = a;
}
animator = ValueAnimator.ofInt(startLeft, endLeft);
animator.setDuration(2000);
endView.setY(startTop);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int current = (int) valueAnimator.getAnimatedValue();
endView.setTranslationX(current);
}
});
ValueAnimator positionAnimator;
if (startTop < 100) {
int a = startTop;
startTop = -endTop;
endTop = a;
}
positionAnimator = ValueAnimator.ofInt(startTop, endTop);
positionAnimator.setDuration(3000);
endView.setX(startLeft);
positionAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int current = (int) valueAnimator.getAnimatedValue();
ViewCompat.setTranslationY(endView, current);
}
});
AnimatorSet set = new AnimatorSet();
set.play(positionAnimator).after(animator);
return set;
}
if (endView.getId() == R.id.view1) {
ValueAnimator animator;
if (startLeft == 0) {
int a = startLeft;
startLeft = -endLeft;
endLeft = a;
}
animator = ValueAnimator.ofInt(startLeft, endLeft);
animator.setDuration(2000);
endView.setY(startTop);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int current = (int) valueAnimator.getAnimatedValue();
ViewCompat.setTranslationX(endView, current);
}
});
ValueAnimator positionAnimator;
if (startTop == 0) {
int a = startTop;
startTop = -endTop;
endTop = a;
}
positionAnimator = ValueAnimator.ofInt(startTop, endTop);
positionAnimator.setDuration(3000);
endView.setX(startLeft);
positionAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int current = (int) valueAnimator.getAnimatedValue();
ViewCompat.setTranslationY(endView, current);
}
});
//动画集合
AnimatorSet set = new AnimatorSet();
set.play(positionAnimator).after(animator);
return set;
}
return null;
}
}
在activity中
private Transition transition;
、、、
public void onClick(View view) {
//自定义的的transition
transition = new DefineTransition();
}
、、、
3.启动
这个就是应用TransitionManager.go();就启动了。
public void onClick(View view) {
//自定义的的transition
transition = new DefineTransition();
TransitionManager.go(endScene, transition);
}
注意:在代买中定义的startScene和endScene在代码中只能作为结束时的Scene。而初始的Scene,系统已经自动获取,就是当前你在屏幕中看到的界面,系统已自动捕获。