美文网首页Android
Android 转场动画Transition 、Share El

Android 转场动画Transition 、Share El

作者: kongjn | 来源:发表于2017-09-02 13:21 被阅读0次

    一款好的app没有动画是肯定不行的(尼古拉斯.赵四)

    今天在写了个Demo的加了一下转场动画,效果如下:

    GIF.gif

    此Demo包含了Transition 、Share Elements两种动画效果,分别在Activity和fragment中实现,API 19 以上支持,以下就显示没有动画效果

    Transition 的进场动画

    相关的方法在这里:

    转场动画作用与window上,Activity 中获取Window,使用 getWindow() 方法即可获取到:

    image.png
    • setExitTransition() :当A startB时,使A中的View退出场景的transition 在A中设置
    • setEnterTransition() :当A startB时,使B中的View进入场景的transition 在B中设置
    • setReturnTransition() :当B 返回A时,使B中的View退出场景的transition 在B中设置
    • setReenterTransition() : 当B 返回A时,使A中的View进入场景的transition 在A中设置
    • setAllowEnterTransitionOverlap():是否运行布局显示时重叠
    • setAllowReturnTransitionOverlap():是否运行布局显示时重叠

    需要配合使用才有对应的效果,单独使用是无效的(已实践)

    这些方法的参数大部分都有一个 Transition,介绍下:

    image.png

    Transition 的继承类是这些,就是平移动画玩出花来了。。。

    自定义的 Transition 也可以哦

    Visibility 类动画转场,可见性(目前就学了这个)
    image.png

    只有三个继承类:

    • Explode :扩散式
    • Fade:渐隐式
    • Slide:平移式

    首先要在onCreate中设置,要在setContentView前面哦:

    // 允许使用transitions  
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
    //或者在主题中加入
    <item name="android:windowContentTransitions" tools:targetApi="lollipop">true</item>
    //还要加一条,不然会出现白屏哦
    <item name="android:windowIsTranslucent">true</item>
    

    Acitivity1:

            Fade fade = new Fade();//渐隐
            fade.setDuration(500);
            Slide slide = new Slide(Gravity.END);//右边平移
            slide.setDuration(500);
            Explode explode = new Explode();//展开回收
            explode.setDuration(500);
            getWindow().setReenterTransition(slide);
            getWindow().setExitTransition(explode);
            getWindow().setAllowEnterTransitionOverlap(false);
            getWindow().setAllowReturnTransitionOverlap(false);
    
    ....Intent 代码
    
            Intent i = new Intent(this, target);
            ActivityOptions transitionActivityOptions = ActivityOptions.makeSceneTransitionAnimation(this);
    //      两种方法都能用,不要问我源码怎么实现,没空研究了
    //      ActivityOptionsCompat transitionActivityOptions =ActivityOptionsCompat.makeSceneTransitionAnimation(this);
            startActivity(i, transitionActivityOptions.toBundle());
    
    

    Acitivity2:

            Explode explode = new Explode();
            explode.setDuration(500);
            Slide slide = new Slide();
            slide.setDuration(500);
            slide.setSlideEdge(Gravity.START);
            getWindow().setEnterTransition(slide);
            getWindow().setReturnTransition(explode);
    
    GIF.gif

    简单实用!

    Share Elements 的进场动画

    • Activity 通过getWindow来设置,看源码。。。目测没有开放
    Window类源码
    • Fragment 中,这个开放了


      Fragment 源码
    • setSharedElementEnterTransition()
      当A startB 时,共享元素以A中的位置作为起始,B中的位置为结束来播放动画。在B中设置

    • setSharedElementReturnTransition()
      当B 返回A时,共享元素以B中的位置作为起始,A中的位置为结束来播放动画。在B中设置

    请看源码:一步两步找到里面的 AnimationInfo ,这个类保存了我们的动画

    Fragment 源码 Fragment 源码

    AnimationInfo 初始化的时候,有些设置了默认的过渡效果,为null的才是我们需要设置的

        static class AnimationInfo {
        ...
            private Object mEnterTransition = null;
            private Object mReturnTransition = USE_DEFAULT_TRANSITION;
            private Object mExitTransition = null;
            private Object mReenterTransition = USE_DEFAULT_TRANSITION;
            private Object mSharedElementEnterTransition = null; //手动设置
            private Object mSharedElementReturnTransition = USE_DEFAULT_TRANSITION; //系统有默认
            private Boolean mAllowReturnTransitionOverlap;
            private Boolean mAllowEnterTransitionOverlap;
    

    在Activity 中动画就不用我们考虑了,人家压根不给你设置,fragmentsetSharedElementEnterTransition需要我们自己来设置,setSharedElementEnterTransition有默认可以不设置,mAllowReturnTransitionOverlapmAllowEnterTransitionOverlap 都是默认为 false

    (必须)使用 Share Elements 前,需要设置共享元素的 transitionName

    //XML中设置
    android:transitionName="image1"
    //或者代码设置
    mImageView1.setTransitionName("image1");
    //或者
    Pair.create(imageView, "image1")
    

    上完成代码! Acitivity1:(共享元素四个两个imageView,两个TextView)

    Intent代码---
        //share elements 多个元素
        private void transitionToActivity(Class target, ImageView imageView, ImageView imageView2, TextView text1, TextView text2) {
            Pair[] pairs = new Pair[]{Pair.create(imageView, "image1"), Pair.create(imageView2, "image2"),
                    Pair.create(text1, "text1"), Pair.create(text2, "text2")};
            Intent i = new Intent(this, target);
            ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this, pairs);
            startActivity(i, transitionActivityOptions.toBundle());
        }
    

    Acitivity2:(这些只是设置给子元素而已,android:transitionName已经在XML中设置)

            Fade fade = new Fade();
            fade.setDuration(500);
            Slide slide = new Slide(Gravity.END);
            slide.setDuration(500);
            getWindow().setReturnTransition(fade);
            getWindow().setEnterTransition(slide);
    
    GIF.gif

    Share Elements Activity 和 fragment 交互

    activity1:

        //share elements 单个元素
        private void startActivity(Class target, ImageView imageView1) {
            Intent i = new Intent(this, target);
            ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this, imageView1, "image1");
            startActivity(i, transitionActivityOptions.toBundle());
        }
    

    activity4:

    public class Main4Activity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main4);
            Slide slideTransition = new Slide(Gravity.LEFT);
            slideTransition.setDuration(500);
            Fragment1 fragment1 = Fragment1.newInstance();
    
            fragment1.setReenterTransition(slideTransition);
            fragment1.setExitTransition(slideTransition);
            //共享元素动画设置
            fragment1.setSharedElementEnterTransition(new ChangeBounds());
            getSupportFragmentManager().beginTransaction().replace(R.id.fragment, fragment1)
                    .commit();
        }
    

    fragment1:

        private void addNextFragment() {
            Fragment2 fragment2 = Fragment2.newInstance();
    
            Slide slideTransition = new Slide(Gravity.RIGHT);
            slideTransition.setDuration(500);
    
            ChangeBounds changeBoundsTransition = new ChangeBounds();
            changeBoundsTransition.setDuration(500);
            
            fragment2.setEnterTransition(slideTransition);
            fragment2.setSharedElementEnterTransition(changeBoundsTransition);
    
            getFragmentManager().beginTransaction().replace(R.id.fragment, fragment2)
                    .addToBackStack(null)
                    .addSharedElement(mImageView,"image1")
                    .commit();
        }
    

    fragment2:

    我什么都写!
    

    最终效果图!!!:

    GIF.gif

    在真实项目当中,共享ImageView使用 Glide 读取同一个url,会导致内存不断的往上升,Share Elements 和 Glide 配合使用内存问题,都是英文一大串,看不懂没事,我已经实践过了,Glide 读取图片跳过缓存就可以了.skipMemoryCache(true),神坑

    共享元素转场貌似还是Fragment里面处理的比较好,丝滑般感受

    参考:深入理解共享元素变换
    分享即美德 源码点我

    相关文章

      网友评论

        本文标题:Android 转场动画Transition 、Share El

        本文链接:https://www.haomeiwen.com/subject/qfxrjxtx.html