专栏首页小海编码日记[Android 基础]为页面跳转添加旋转动画

[Android 基础]为页面跳转添加旋转动画

无意间看到一篇关于页面跳转动画效果的博文,在Android源码API demo中也有相似的实现(FlipAnimation),这里写文以记之,实现后的效果如下图:


定义动画

从上面的gif动图我们可以看出,在两个页面跳转间加了旋转动画,那么如何实现这种动图呢?

最直观的感觉就是上一个页面从左侧旋转出,下一个页面从右侧旋转进入,一入一出共四个动画资源定义如下:

left_in.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:valueFrom="1.0"
        android:valueTo="0.0"
        android:propertyName="alpha"
        android:duration="0" />
    <!-- Rotate. -->
    <objectAnimator
        android:valueFrom="-180"
        android:valueTo="0"
        android:propertyName="rotationY"
        android:interpolator="@android:interpolator/accelerate_decelerate"
        android:duration="3000" />
    <objectAnimator
        android:valueFrom="0.0"
        android:valueTo="1.0"
        android:propertyName="alpha"
        android:startOffset="1500"
        android:duration="1" />
</set>

left_out.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Rotate. -->
    <objectAnimator
        android:valueFrom="0"
        android:valueTo="180"
        android:propertyName="rotationY"
        android:interpolator="@android:interpolator/accelerate_decelerate"
        android:duration="3000" />
    <!-- Half-way through the rotation (see startOffset), set the alpha to 0. -->
    <objectAnimator
        android:valueFrom="1.0"
        android:valueTo="0.0"
        android:propertyName="alpha"
        android:startOffset="1500"
        android:duration="1" />
</set>

right_in.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:valueFrom="1.0"
        android:valueTo="0.0"
        android:propertyName="alpha"
        android:duration="0" />
    <!-- Rotate. -->
    <objectAnimator
        android:valueFrom="180"
        android:valueTo="0"
        android:propertyName="rotationY"
        android:interpolator="@android:interpolator/accelerate_decelerate"
        android:duration="3000" />
    <objectAnimator
        android:valueFrom="0.0"
        android:valueTo="1.0"
        android:propertyName="alpha"
        android:startOffset="1500"
        android:duration="1" />
</set>

right_out.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Rotate. -->
    <objectAnimator
        android:valueFrom="0"
        android:valueTo="-180"
        android:propertyName="rotationY"
        android:interpolator="@android:interpolator/accelerate_decelerate"
        android:duration="3000" />
    <!-- Half-way through the rotation (see startOffset), set the alpha to 0. -->
    <objectAnimator
        android:valueFrom="1.0"
        android:valueTo="0.0"
        android:propertyName="alpha"
        android:startOffset="1500"
        android:duration="1" />
</set>

上述代码中使用ObjectAnimator标签定义了透明度和旋转动画,透明度动画是为了增加动画的流畅性,不显得那么突兀,其中比较重要的标记含义如下:

  • android:propertyName:指定动画类别,alpha为透明度动画,rotationY为旋转动画;
  • android:valueFrom:动画起始值;
  • android:valueTo:动画结束值;
  • android:duration:动画时长;

关于ObjectAnimator的详细信息我们留待下篇文章细节介绍。

使用ViewModel共享数据

随后我们新建两个Fragment以承载跳转前后的页面布局,那么接下来就是在点击事件发生时,做Fragment的替换了,此时做过类似需求的小伙伴估计已经了然于胸了,那么在这个过程中会有什么问题呢?

众所周知,Fragment依赖于Activity,那么我们在A Fragment中发生页面切换事件,此时是需要Activity进行FragmentTransaction的,大家的一般策略无非是:回调广播等策略,那么又没有更加省力的方式呢?

当然有啦,就在这一小节标题上,ViewModel,使用ViewModel在Activity和Fragment间共享数据,以实现界面跳转,下面来看具体的代码: MainPageViewModel.java

public class MainPageViewModel extends ViewModel {
    private MutableLiveData<Boolean> mIsShowingBack;
    public MutableLiveData<Boolean> isShowingBack(){
        if (mIsShowingBack == null){
            mIsShowingBack = new MutableLiveData<>();
        }
        return mIsShowingBack;
    }
}

mIsShowingBack主要用于标记是否需要跳入B页面,为true则跳入B页面,为false则跳入A页面。A ,B页面的两个Fragment如下所示:

CardFrontFragment.java[A页面]

public class CardFrontFragment extends Fragment {
    private MainPageViewModel mMainPageViewModel;
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mMainPageViewModel = ViewModelProviders.of(getActivity()).get(MainPageViewModel.class);
    }
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_front_layout,container,false);
        view.findViewById(R.id.front_imageView).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mMainPageViewModel.isShowingBack().setValue(true);
            }
        });
        return view;
    }
}

CardBackFragment.java[B页面]

public class CardBackFragment extends Fragment {
    private MainPageViewModel mMainPageViewModel;
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mMainPageViewModel = ViewModelProviders.of(getActivity()).get(MainPageViewModel.class);
    }
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_back_layout,container,false);
        view.findViewById(R.id.back_imageview).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mMainPageViewModel.isShowingBack().setValue(false);
            }
        });
        return view;
    }
}

观察数据变化切换页面

主要代码如下:

 private void initData(){
    mMainPageViewModel = ViewModelProviders.of(this).get(MainPageViewModel.class);
    mMainPageViewModel.isShowingBack().observe(this, new Observer<Boolean>() {
        @Override
        public void onChanged(@Nullable Boolean aBoolean) {
            flipCard(aBoolean);
        }
    });
}
@SuppressLint("ResourceType")
private void flipCard(boolean showingBack){
        getSupportFragmentManager()
                .beginTransaction()
                .setCustomAnimations(
                        R.anim.right_in, R.anim.right_out,
                        R.anim.left_in, R.anim.left_out)
                .replace(R.id.container, showingBack?new CardBackFragment():new CardFrontFragment())
                .commit();
}

这里比较共有两点比较关键:

1.观察ViewModel数据变化 2.使用setCustomAnimations为页面跳转设置自定义动画

完整代码参见链接: https://github.com/tuozhaobing/CsdnDemoCode/tree/master/FlipAnimationDemo

本文分享自微信公众号 - 小海编码日记(gh_1f87b8c00ede),作者:脱召兵

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-12-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [Android进阶]OFO首页实现小窥

    最近阅读量凄凄惨惨,难以为继,孤倍感无力,遂决定着眼于炫酷,造一些博眼球的东西以引流,比如说实现XXX页面效果,仿XXX页面效果等,各位看官如若觉得不错,还请动...

    小海编码日记
  • Android 基础[花式实现底部导航栏之TabLayout]

    前文中我们已经简单介绍了BottomNavigationView实现选项卡页面的细节,接下来我们继续花式实现底部导航栏之旅,本片中主要是使用TabLayout实...

    小海编码日记
  • Android 基础[花式实现底部导航栏之BottomNavigationView(2)]

    上篇文章中我们介绍了BottomNavigationView的使用细则,并学习了如何对BottomNavigationView设置一些自适应属性,接下来我们来学...

    小海编码日记
  • Android 入门程序 Kotlin版(1)

    4个组件 TextView,Button,TextEdit,ImageView依次纵向线性布局。

    用户6021899
  • Android实现加载对话框

    本文实例为大家分享了Android实现加载对话框的具体代码,供大家参考,具体内容如下

    砸漏
  • 微信朋友圈被折叠?会自动化不存在的(下)

    首先,使用 Android Studio 创建一个项目(这里以 JAVA 为例,Kotlin 类似)

    AirPython
  • Android基础控件RadioGroup使用方法详解

    本文为大家分享了Android基础控件RadioGroup的使用,供大家参考,具体内容如下

    砸漏
  • Android按钮美化样式的实现代码

    以上所述是小编给大家介绍的Android按钮美化样式的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对Za...

    砸漏
  • ViewFlipper实现上下翻滚轮播效果

    一种可以设置滑动动画的控件,只显示一行布局,在布局文件中的ViewFlipper控件中顺序写好每一行的布局

    砸漏
  • ViewFlipper实现文字轮播效果

    ViewFlipper实现文字轮播(仿淘宝头条垂直滚动广告),供大家参考,具体内容如下

    砸漏

扫码关注云+社区

领取腾讯云代金券