动画框架(4)-共享元素动画和场景切换

主目录见:Android高级进阶知识(这是总目录索引)
 我们都知道,在5.0之后引入了很多新的转场动画,使过渡更加的合理化了,适当地加入动画能使你的app看起来眼前一亮,第一印象取胜,所以我们有理由来学习它,为了有兴趣看下去,我们先亮出效果,录屏有点卡顿,实际比较流畅:

效果图

想要代码的可以直接[点击下载],然后适当地在自己app里面放飞吧。

一.目标

 今天的目标比较单纯,就是为了给我们的应用程序增加点吸引力,使别人有兴趣玩你的app,所以目标有以下:
1.练习使用共享元素动画和TransitionManager;
2.能在适当的时候使用这些动画。

二.代码分析

 Material Design 为场景切换提供了非常优雅的视觉效果,在进入和退出页面,元素共享页面的时候都可以添加想要的效果,而且能让你感觉运动就应该是这样的,这样其实就已经成功了。

1.过渡效果

 过渡这个地方我是在例子里面顺便加入的,但是防止有的人这个都没有用过,这里就提一下,过渡的场景如下:
1.首先打开A页面
2.然后A页面跳转到B页面
3.接着回到A页面
首先针对这几个场景我们可以设置的方法有下面几个:

1.android:windowEnterTransition                    首次进入显示的动画
2.android:windowExitTransition                    启动新 Activity ,此页面退出的动画
3.android:windowReenterTransition                    重新进入的动画。即第二次进入,可以和首次进入不一样。
4.android:windowReturnTransition                    调用 finishAfterTransition() 退出时,此页面退出的动画

即可以调用getWindow().setReenterTransition(new Explode())等,其他方法类似。传进去的参数是效果,页面切换的动画有以下三个:
1.Explode:从中心移入或移出

Explode

2.Slide:从边缘移入或移出
Slide

3.Fade:调整透明度产生渐变
Fade

这些就是页面切换会设置的动画效果,这些效果还可以设置一些属性:

// 设置动画的时间。类型:long 
transition.setDuration(); 
// 设置修饰动画,定义动画的变化率,具体设置往下翻就看到了
transition.setInterpolator();
 // 设置动画开始时间,延迟n毫秒播放。类型:long
transition.setStartDelay();
 // 设置动画的运行路径
 transition.setPathMotion(); 
// 改变动画 出现/消失 的模式。Visibility.MODE_IN:进入;Visibility.MODE_OUT:退出。
 transition.setMode(); 
// 设置动画的监听事件
 transition.addListener()

好了,借鉴和总结了下这个,我们就进入今天的主题吧

2.共享元素动画

首先我们为了演示这个动画,我们弄了个RecyclerView,然后在点击某个item的时候加入动画,为了使用共享元素动画。
1.我们首先要在setContentView方法前加入:

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

或者你可以直接在style文件中设置如下,然后加入Activity中去:

<item name="android:windowContentTransitions">true</item>

2.然后在要共享运动的地方加上共享元素标识,首先在A页面如下:

RecyclerView中的item_content

然后我们看下要跳转页面B的布局下面添加相同transitionName:

跳转页面的布局添加

3.现在准备工作做完了,我们现在可以在A页面启动B页面了,代码如下:

        mAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Intent intent = new Intent(MainActivity.this,DetailActivity.class);
//               startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this,view.findViewById(R.id.ivChallenger),"sharedChallenger").toBundle());
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this,
                                          Pair.create(view.findViewById(R.id.ivChallenger),"sharedChallenger"),
                                          Pair.create(view.findViewById(R.id.tvTitle),"sharedTitle"),
                                          Pair.create(view.findViewById(R.id.tvContent),"sharedContent")).toBundle());
                }else{
                    ActivityTransitionLauncher.with(MainActivity.this).from(view.findViewById(R.id.ivChallenger)).launch(intent);
                }
            }
        });

我们看到这段代码里面判断了Android的版本,为了做兼容,我们这里引入了一个兼容库,如果版本低于21的话我们就走兼容库,兼容库地址请点击,效果没有谷歌原生好,但是可以做个替代方案。然后我们看到这里会把想要共享元素的都用Pair设置进去,然后我们调用ActivityOptions的makeSceneTransitionAnimation()方法,最后用toBundle()转化为Bundle对象传给startActivity()方法即可。
4.最后我们在要跳转的页面加入如下的代码:

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//        getWindow().setEnterTransition(new Slide());//从场景的边缘移入或移出
            getWindow().setEnterTransition(new Fade());//调整透明度产生渐变效果
//        getWindow().setEnterTransition(new Explode());//从场景的中心移入或移出

            ChangeBounds changeBounds = new ChangeBounds();//改变目标视图的布局边界
//        ChangeTransform changeTransform = new ChangeTransform();//改变目标视图的缩放比例和旋转角度
//        ChangeImageTransform changeImageTransform = new ChangeImageTransform();//改变目标图片的大小和缩放比例
//        ChangeClipBounds changeClipBounds = new ChangeClipBounds();//裁剪目标视图边界
//        changeBounds.setDuration(1000);
            getWindow().setSharedElementEnterTransition(changeBounds);
        }else{
            ActivityTransition.with(getIntent()).to(findViewById(R.id.ivChallenger))
                    .duration(300).start(savedInstanceState);
        }

同样的我们也加入了版本的判断来做兼容,这里有这么多注释掉的代码是为了大家看到共享元素的动画可以设置的动画效果有这么多。(ChangeBounds,ChangeTransform,ChangeImageTransform,ChangeClipBounds)这些效果已经注释有说明,这里就不贴出来这些效果的演示,大家可以下载我的代码然后打开看看效果。好啦。共享元素使用不是非常难,就是有兼容性问题,不过我们相信不久的将来我们会不需要做兼容了。(这里的setEnterTransition()方法和setSharedElementEnterTransition()方法同样可以在xml中设置)

3.场景切换(TransitionManager)

这个动画也是很酷的,我也是这次弄共享元素动画时候get到的,大家可以看看,还是蛮炫的。首先我们在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/flScene"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="400dp">

    </FrameLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btnSwitchScene"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="切换场景"
           />
        <Button
            android:id="@+id/btnSwitchScene1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="切换场景1"
            />
        <Button
            android:id="@+id/btnSwitchScene2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="切换场景2"
            />
    </LinearLayout>
</LinearLayout>

其中FrameLayout就是到时放我们场景的地方,每个场景对应于一个布局。在代码onCreate里面我们获取每个场景代码如下:

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void setupLayout(){
        scene0 = Scene.getSceneForLayout(flScene,R.layout.detail_activity,this);
        scene1 = Scene.getSceneForLayout(flScene,R.layout.detail_activity_scene,this);
        scene2 = Scene.getSceneForLayout(flScene,R.layout.detail_activity_scene1,this);
        scene3 = Scene.getSceneForLayout(flScene,R.layout.detail_activity_scene2,this);
    }

其中第一个参数flScene是对应于容器FrameLayout的,第二个参数是场景的布局,第三个是Context。大家只要对应上去就可以了。我这里还添加了进入的动画:

    getWindow().setEnterTransition(new Slide());
        getWindow().getEnterTransition().addListener(new Transition.TransitionListener() {
            @Override
            public void onTransitionStart(Transition transition) {

            }
            @Override
            public void onTransitionEnd(Transition transition) {
                TransitionManager.go(scene3);
            }
            @Override
            public void onTransitionCancel(Transition transition) {

            }
            @Override
            public void onTransitionPause(Transition transition) {

            }
            @Override
            public void onTransitionResume(Transition transition) {

            }
        });

然后我监听了动画的执行过程,在执行完毕的时候进入到场景scene3。然后其他场景就是点击页面中的按钮中进入,分别如下:

1. TransitionManager.go(scene0, new ChangeBounds());
2.//TransitionManager.go(scene1, TransitionInflater.from(TransitionManagerActivity.this)
//.inflateTransition(R.transition.slide_and_changebounds));
  TransitionManager.go(scene1,TransitionInflater.from(TransitionManagerActivity.this).
                        inflateTransition(R.transition.slide_and_changebounds_sequential_with_interpolators));
3.  TransitionManager.go(scene2,TransitionInflater.from(TransitionManagerActivity.this)
                        .inflateTransition(R.transition.slide_and_changebounds_sequential));

其中inflateTransition进来的动画就是跟我们共享元素支持的动画一样,我们看其中一个transition包中slide_and_changebounds_sequential.xml:

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
               android:duration="@integer/anim_duration_long"
               android:transitionOrdering="sequential">
    <slide/>
    <changeBounds/>
</transitionSet>

我们看到这个就是我们前面支持动画的xml写法而已。
总结:到这里我们要讲的动画已经都讲完成了,动画还得大家下载代码下来看下效果,这样印象比较深刻,希望大家都能做出Awesome Application!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容