上一篇文章,我简单地介绍了MTransition,请查看链接:MTransition介绍和使用 ---- 一个页面切换动画库(Android)
这里我将较为详细地用示例代码说明下MTransition的使用。
在下面的代码示例中,我们都假设需要用MTransition完成一个从ActivityA到ActivityB的过场动画,并称ActivityA为FromPage,称ActivityB为ToPage;
基础用法(请参考Demo0、Demo1、Demo2)
Step1、
在FromPage打开ToPage之前,需要创建一个MTransition实例,并通过setContainer()
告诉FromPage的最外层父容器View是什么,和通过addTransitionView()
设置FromPage中参与过场动画的View(参考代码Example2EntryActivity.java):
final MTransition transition = MTransitionManager.getInstance().createTransition("example");
transition.fromPage().setContainer(mPage, new ITransitPrepareListener() {
@Override
public void onPrepare(MTransitionView container) {
transition.fromPage().addTransitionView("icon", view.findViewById(R.id.item_icon));
transition.fromPage().addTransitionView("name", view.findViewById(R.id.item_name));
transition.fromPage().addTransitionView("snapshot", view.findViewById(R.id.item_snapshot));
transition.fromPage().addTransitionView("container", mPage);
}
});
Step2、
(非Activity的情况可以忽略这一步)
在FromPage打开ToPage,一般情况下,FromPage和ToPage都是Activity,这时需要在startActivity()之后,紧接调用以下代码:
startActivity(intent);
MTranstionUtil.removeActivityAnimation(YourActivity.this);
这一步的作用是,Android默认会给Acitivty一个进场和退场的动画,调用这个代码可以暂时移除Android的默认动画
,防止和MTransition的动画冲突;
Step3、
在打开ToPage之后,并且在ToPage显示之前(注意,一定要在显示之前,这个时机一般是在View创建完成之后,例如onCreate等),获取在FromPage创建的MTransition实例,同样地,告诉ToPage的最外层父容器View是什么,和通过addTransitionView()
设置ToPage中参与过场动画的View;
同时这里可以获取FromPage和ToPage所有参与动画的View,通过"alpha()、translate()、transitTo()"
等接口,表明这些View要如何做动画;
也可以通过"above()、below()"
接口去调整View的显示层级(参考代码Example2DetailActivity.java):
final MTransition transition = MTransitionManager.getInstance().getTransition("example");
transition.toPage().setContainer(mAppDetailPage, new ITransitPrepareListener() {
@Override
public void onPrepare(MTransitionView container) {
container.alpha(0f, 1f);
MTransitionView icon = transition.toPage().addTransitionView("icon", mAppDetailPage.mImage);
MTransitionView name = transition.toPage().addTransitionView("name", mAppDetailPage.mName);
transition.fromPage().getTransitionView("icon").above(icon).transitTo(icon, true);
transition.fromPage().getTransitionView("name").above(name).transitTo(name);
}
});
Step4、
最后,同样是在ToPage显示之前,调用MTransition.start()
方法,去启动整个过场动画:
transition.setDuration(500); // 整个动画时长
transition.start();
如果有需要,你可以设置监听器,去监听过场动画的过程:
transition.setOnTransitListener(new TransitListenerAdapter() {
@Override
public void onTransitEnd(MTransition transition, boolean reverse) {
// do somthing
}
});
反向动画
MTransition提供了reverse()
接口,可以实现过场动画原路径反向播放,方便你在ToPage返回FromPage的时候调用:
@Override
public void onBackPressed() {
final MTransition transition = MTransitionManager.getInstance().getTransition("example");
transition.reverse();
}
一般情况下,在反向动画执行完毕之后,你需要关闭Activity或者做其他操作,这时需要配合监听器Listener去实现:
transition.setOnTransitListener(new TransitListenerAdapter() {
@Override
public void onTransitEnd(MTransition transition, boolean reverse) {
if (reverse) {
// reverse为true代表动画是反向的
finish();
MTranstionUtil.removeActivityAnimation(Example2DetailActivity.this);
}
}
});
跟手动画
跟手动画是MTransition与其他过场动画库(尤其是Android自带的Transition)与众不同的地方,是本库的亮点之一;
事实上,跟手动画的核心是MTransition提供了setProgress()
接口,可以让你随时让动画播放其中的某一帧,这样你就可以按照自己的喜好
,结合TouchEvent事件去实现跟手动画,具体请参考代码库的Demo,如Example10DetailActivity.java;
必须注意一点:由于MTransition动画必须要FromPage和ToPage都存在的情况下才能执行,所以一般情况下,FromPage打开ToPage的过场动画很难用跟手实现(可以实现,只是比较麻烦);ToPage返回FromPage的跟手动画则比较容易;
这里简单说明跟手动画的实现逻辑:
Step1、在跟手动画执行之前,需要调用onBeginDrag():
Step2、根据需要去控制动画执行的进度;
Step3、调用gotoFloor()或者gotoCeil()去完成动画;
@Override
public boolean onTouch(View v, MotionEvent event) {
boolean result = false;
int scrolly = scrollView.getScrollY();
int action = event.getAction();
if (action == MotionEvent.ACTION_DOWN) {
mBeginDrag = false;
mDownY = (int) event.getY();
mDownScrollY = scrolly;
} else if (action == MotionEvent.ACTION_MOVE) {
int delta = (int) (event.getY() - mDownY);
if (mDownScrollY <= 0 && delta > 20) {
// 当下拉达到一定阈值,则开始跟手动画
transition.onBeginDrag();
mBeginDrag = true;
}
if (mBeginDrag) {
// 根据滑动距离,控制动画的进度
transition.setProgress(1f - delta / (float) scrollView.getMeasuredHeight());
result = true;
}
} else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
if (mBeginDrag) {
int delta = (int) (event.getY() - mDownY);
float progress = 1f - delta / (float) scrollView.getMeasuredHeight();
// 手指松开时,根据情况让动画走完或者回退
if (progress < 0.7f) {
transition.gotoCeil();
} else {
transition.gotoFloor();
}
result = true;
}
}
return result;
}
自定义动画View,可以结合Lottie或者其他动画库
MTransition已经提供了一堆基础的动画api,例如平移、旋转、缩放、透明度等。这些api已经可以满足大部分需求,但是如果你需要一些形变或者更加复杂的动画,
你就需要自定义动画。
step1、将你的自定义动画View实现ITransitional
接口
step2、调用replaceBy()
接口,将你的自定义动画View替换原本的View,让它在过渡动画过程中做动画
该方案可以结合Lottie或者其他动画库,实现一些非常酷炫的效果,如下图,具体请参考本仓库代码中的Demo5、6、7;
有用的Q&A:
Q:为什么我的过场动画背景是白色的?
A:
1、首先请确保设置给FromPage和ToPage的最外层父容器是有背景的,正常情况下,MTransition动画是跟原本View一样的背景;
2、MTransition会默认给FromPage和ToPage的Container设置一层白色背景,防止原View背景是透明的情况,可以参看源代码MTransitionPage.setContainer()的实现。如果你有需要干掉白色背景,你可以自行通过MTransitionPage.getContainer().setBgColor()去修改颜色;
Q:待补充