实现朋友圈图片查看的转场动画+滑动返回,RecyclerView to ViewPager。
RecyclerView to ViewPager 动画实现
下面介绍的便是RecyclerView 到 ViewPager的Shared Element transition动画,如朋友圈那样的。
SourceActivity(RecyclerView) —> DestinationActivity(ViewPager)
先阅读官方的Shared Element Transitions文档
总共5个步骤:
- Enable window content transitions in your theme.
- Specify a shared elements transition in your style.
- Define your transition as an XML resource.
- Assign a common name to the shared elements in both layouts with the android:transitionName attribute.
- Use the ActivityOptions.makeSceneTransitionAnimation() method.
在主题中启动 window content transitions动画, 设置Shared Element transition 动画, 路径
res/values-v21/styles.xml
1 | <item name="android:windowContentTransitions">true</item> |
定义 Shared Element Transition 动画, 路径
res/transition/change_image_transform.xml
1 |
|
RecyclerView, ViewPager都用到Adpter,自然不能在xml布局中设置 transitionName 了。
利用 View.setTransitionName()动态设置,在Adapter中绑定视图时设置transitionName。
做了初步了解后,应该知道Shared Element transition动画是需要一个一对一的关系来确定动画的。
下面的步骤也不可少:
一、 每个View应该有唯一 transitionName,不做详解。
二、 需要等待 ViewPager 开始显示图片后才启用转场动画。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//简化代码
public class DestinationActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//延迟动画
postponeEnterTransition();
}
}
public class PhotoAdapter extends PagerAdapter {
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(container.getContext());
//....省略
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
String name = container.getContext()
.getString(R.string.transition_name, adapterPosition, position);
imageView.setTransitionName(name);
if (position == current) {
//初始化当前显示的ImageView时,设置一个callback开启转场动画
setStartPostTransition(imageView);
}
}
}
}
// @TargetApi(21)
private void setStartPostTransition(final View sharedView) {
sharedView.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
// @Override
public boolean onPreDraw() {
sharedView.getViewTreeObserver().removeOnPreDrawListener(this);
startPostponedEnterTransition();
return false;
}
});
}
}
三、 ViewPager 中左右滑动后返回时要通知 SourceActivity.class。
SourceActivity.onActivityReenter();
startActivityForResult();
setResult(RESULT_OK, intent);
这三个函数配合即可在 SourceActivity.class 中获取到变动通知。
1 | // @Override |
四、 既然有所变动,那么原先一对一的关系有所变动了,下面两个函数可处理这种情况:
1 | public class DestinationActivity extends AppCompatActivity { |
滑动返回实现
- 为 DestinationActivity.class 设置透明背景主题, 路径
/res/values/styles.xml
1 | <style name="AppTheme.Transparent" parent="AppTheme"> |
- 定义一个 DismissFrameLayout 用来包裹 ImageView, 实现手势检测, 动态更新 ImageView 位置, 动态设置 DestinationActivity.class 背景透明度。
Code tell everything
Demo