你们好!wo又来了。。。几天不见甚是想念!!!最近因为比较忙,请原谅个人懒惰!!!写关于MaterialDesign的文章已经有好几篇了。昨天无心间看见了一个关于过分动画的概念,因此今天想和你们分享一下关于过分动画的实战!这里唠叨一下,网上不少文章都是针对于页面跳转的动画,其实过渡动画不光能够实现页面跳转,对一些控件也是能够生效的。android
若是你想直接案例解析的话,能够直接从第三条开始看!!!git
先简单看一下效果:github
关于过分动画,是在Android5.0中提出的。它经过运动和切换不一样状态之间的元素来产生各类动画效果。开始的时候,没有对低版本进行适配,github上有位大神进行了相应的适相似配(使用方式) 地址以下,后来在support包中添加了对低版本的适配,因此使用的时候要注意,不然会出现警告的。。。bash
大致的继承关系以下:markdown
这个动画管理类,主要协调相应的动画管理。重要的API有如下几个:app
这个主要是针对根试图的过渡方法:这里主要是处理一个页面中的过渡! 这个方法还有一个重载的方法:ide
beginDelayedTransition(@NonNull final ViewGroup sceneRoot)
beginDelayedTransition(@NonNull final ViewGroup sceneRoot, @Nullable Transition transition)
复制代码
这里的动画过渡类型有如下几类:oop
具体代码以下:布局
mCl_root = findViewById(R.id.cl_root); mTvText = findViewById(R.id.tv_text); // Slide slide = new Slide(Gravity.BOTTOM); // Explode explode = new Explode(); Fade fade = new Fade(); TransitionManager.beginDelayedTransition(mCl_root, fade); if (mTvText.getVisibility() == View.VISIBLE) { mTvText.setVisibility(View.GONE); } else { mTvText.setVisibility(View.VISIBLE); } 复制代码
上面会有三种效果,这里建议你们本身设置如下看看效果!测试
若是你想设置动画的一些其余属性的话,能够这样:
fade.setDuration(300);//设置动画时长
fade.setInterpolator(new FastOutSlowInInterpolator());//设置插值器
fade.setStartDelay(200);//设置延时
复制代码
上面全部都有这些属性的!!!
这里注意一点,若是你想要使用缩放、颜色、旋转变化的话,那个适配的库中有!其实就是继承了Transition这个类,本身去实现罢了!感兴趣的童鞋能够去试试。。。
说实话,这个东西我研究了很久,各类百度才理解了怎么用,原谅个人愚笨。。。先说说我对这个东西的理解啊!从一个布局文件过渡到另外一个布局文件(注意,这里是布局文件的过渡)。我不知道怎么用语言去形容。。。
我们看图吧!
上面的图你们都看懂了吧!其实就是两个布局文件的过渡,中间全部的过渡都是TransitionManager帮咱们封装完成的,你能够选择相应的样式进行显示!咱们看看具体的代码实现吧!
首先要给你们说个类,这个类在此过分动画中起着相当重要的做用,这个类就是
Scene
,注释里解释为一个视图层次,也就至关于上面提到的布局文件过渡中的布局,其实这个东西你理解成布局也是能够的!
Scene getSceneForLayout(@NonNull ViewGroup sceneRoot, @LayoutRes int layoutId, @NonNull Context context)
复制代码
这样就能够建立一个相应的视图层级了!下面咱们来讲代码:
由于是两个布局文件的过渡,因此这里咱们须要一个总布局,两个供切换的布局,这里你可能不太明白,一会就明白了!!!相信我,不行你向我丢BUG;
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/cl_root" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.jinlong.newmaterialdesign.animation.TransitionManagerActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimaryDark" app:title="展现动画效果" app:titleTextColor="@android:color/white" /> <Button android:id="@+id/btn_animation" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="animation" android:text="实现动画变换" app:layout_constraintTop_toBottomOf="@id/toolbar" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="scene" android:text="变换动画" app:layout_constraintLeft_toRightOf="@id/btn_animation" app:layout_constraintTop_toBottomOf="@id/toolbar" /> <TextView android:id="@+id/tv_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="20dp" android:text="请注意这些文字的变化" app:layout_constraintTop_toBottomOf="@id/btn_animation" /> <FrameLayout android:id="@+id/rl_root" android:layout_width="match_parent" app:layout_constraintTop_toBottomOf="@id/tv_text" android:layout_height="200dp"> <include layout="@layout/scene1" /> </FrameLayout> </android.support.constraint.ConstraintLayout> 复制代码
这里主要看FrameLayout中包裹的那个布局,这是一个布局文件!都是基于这里来的!!!
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="200dp"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/civ_1" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:src="@mipmap/heard_1" /> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/civ_2" android:layout_width="80dp" android:layout_height="80dp" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="20dp" android:layout_marginRight="20dp" android:src="@mipmap/heard_2" /> </RelativeLayout> 复制代码
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="200dp"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/civ_2" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginLeft="20dp" android:layout_marginTop="20dp" android:src="@mipmap/heard_2" /> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/civ_1" android:layout_width="80dp" android:layout_height="80dp" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="20dp" android:layout_marginRight="20dp" android:src="@mipmap/heard_1" /> </RelativeLayout> 复制代码
两个布局的展示形式是这样的。仔细的小伙伴可能看到了,两个布局的展现形式是同样的,只是两个控件的位置互换了一下。其实动画的表现形式就是那个男孩的头像从左上角移动到右下角,女孩的头像从右下角移动到左上角,正好的两个布局的展示形式。因此讲到这里我像你就会明白为何我一直强调是布局文件的移动了吧!
FrameLayout layout = findViewById(R.id.rl_root);
mScene1 = Scene.getSceneForLayout(layout, R.layout.scene1, this);
mScene2 = Scene.getSceneForLayout(layout, R.layout.scene2, this);
TransitionManager.go(mScene1);
复制代码
这里建立了两个视图层次,开始的时候,直接默认显示到视图图层1,点击按钮进行以下操做:
TransitionManager.go(isScene2 ? mScene1 : mScene2,new ChangeBounds());
isScene2 = !isScene2;
复制代码
这里经过一个变量进行判断,若是显示的是视图图层2就切换到图层1,不然相反!就能实现上面的效果了!!!总体代码就不贴了,本身动手试一下,这样记得牢靠!其实不仅局限于这种表现形式。若是三个的话,你建立三个视图图层也是能够切换的。这个你就要发挥想象空间了!
关于这个类,能够简单理解为动画集合,能够合并多个动画一块儿显示出来。
TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(slide);
transitionSet.addTransition(fade);
复制代码
这样就能直接把上面的过渡叠加起来了!
这里我以为有必要说明如下xml的使用,首先要明确,这个布局的放置位置res/transition/xxx.xml。这里先贴一个总体的xml我在逐一讲解:
<?xml version="1.0" encoding="utf-8"?> <transitionSet xmlns:android="http://schemas.android.com/apk/res/android" android:transitionOrdering="sequential"><!--是否按照顺序执行--> <fade android:duration="500"> <targets> <target android:targetId="@id/toolBar"/> <target android:targetId="@android:id/statusBarBackground"/> <target android:targetId="@id/tv_show"/> </targets> </fade> <slide android:startDelay="600"> <targets> <target android:targetId="@id/icon_sf"/> </targets> </slide> <slide android:startDelay="700"> <targets> <target android:targetId="@id/icon_bh"/> </targets> </slide> <slide android:slideEdge="left" android:startDelay="500"> <targets> <target android:targetId="@id/tv_show"/> </targets> </slide> </transitionSet> 复制代码
基本上能用到的属性就这么多!!!其实这个清单文件里面主要维护的是哪一个控件须要那种过渡。就酱紫!!!
讲了这么多你是否是仍是一脸懵逼,其实我也是,不知道怎么去表达,因此我准备用实例去讲解,便于本身的记忆和你的理解!!!
终于到了本文的重点了,其实我开始学这个东西的时候也是一脸懵逼,不太理解,可是后来看到代码的时候,就不那么费劲了。。。。先从首页顶部那个图片开始提及吧!
关于上面的动画效果,主要记住共享这个概念,为何这么说呢?由于上面这个动画是根据共享去关联的。所谓的依靠共享,主要是这个View过渡到下一个View的相应展示形式!那么就存在一个问题了,共享你必须两个View有共同的一个View,而后存在共同的ID。不然下个页面怎么知道你想要拿什么和我共享呢?这里暂时定一下Activity页面A(后面用A代替)和Activity页面B(后面用B代替)。
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/cl_root" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.jinlong.newmaterialdesign.animation.TransitionManagerActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimaryDark" app:title="展现动画效果" app:titleTextColor="@android:color/white" /> <LinearLayout android:id="@+id/ll_shared" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp" android:onClick="sharedAnimation" android:orientation="horizontal" app:layout_constraintTop_toBottomOf="@id/toolbar"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/civ_heard" android:layout_width="50dp" android:layout_height="50dp" android:src="@mipmap/heard_1" /> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginLeft="30dp" android:text="这是一个标题栏目" /> </LinearLayout> </android.support.constraint.ConstraintLayout> 复制代码
这里注意上面的CircleImageView控件的ID和TextView控件的ID,上面说了,后面会用到!
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.jinlong.newmaterialdesign.animation.SharedActivity"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimaryDark" app:title="展现动画效果" app:titleTextColor="@android:color/white" /> <LinearLayout android:id="@+id/fl_top" android:layout_width="match_parent" android:layout_height="200dp" android:gravity="center" android:orientation="vertical" app:layout_constraintTop_toBottomOf="@id/toolbar"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/civ_heard" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/heard_1" android:transitionName="shared_image" /> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="20dp" android:text="这也是相应的标题" android:transitionName="shared_textview" /> </LinearLayout> </android.support.constraint.ConstraintLayout> 复制代码
这里的ID和上面的ID是同样的。而且注意这里面设置的transitionName标签,这个标签是设置共享内容的,立刻你就会知道为何了。。。
CircleImageView civHead = findViewById(R.id.civ_heard); TextView tvTitle = findViewById(R.id.tv_title); Intent intent = new Intent(this, SharedActivity.class); ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this, new Pair<View, String>(civHead, "shared_image"), new Pair<View, String>(tvTitle, "shared_textview")); startActivity(intent, optionsCompat.toBundle()); 复制代码
看了上面的内容,我相信你能写出下面的动画效果了!
其实后面那个圆形扩散的效果是在5.0之后才有的效果(使用的是ViewAnimationUtils),因此要使用的话,必须在5.0机器上测试。不然是没有效果的!!!代码是这样的...
Animator circularReveal = ViewAnimationUtils.createCircularReveal(mImage_bg, 0, mImage_bg.getHeight(), 0, Math.max(mImage_bg.getHeight(), mImage_bg.getWidth()));
mImage_bg.setBackgroundColor(Color.BLACK);
circularReveal.setDuration(600);
circularReveal.start();
复制代码
其实用到的只有一个API方法Animator createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius)
这里面的参数基本上就是中心点坐标,扩散半径的肯定,这里就不作太多解释了!这个你能够在在21的版本试一下就能够了!
在B页面其实也是能够设置相应的入场动画的
穿插一个问题,就是Transition怎么从xml中引入
TransitionInflater.from(this).inflateTransition(R.transition.return_slide)
复制代码
这里的Transition能够是一个具体的子类,也能够是一个清单文件。剩下的就是发挥你们的想象空间了!把上面的页面剩下的代码贴一下,就结束今天的内容吧!感受篇幅有点长,感兴趣的同窗,能够看看我GitHub里面的项目!!!
这篇文章我写了好几天,不知道该怎么去写,感受写的有点乱,但愿你们不要介意,有什么不懂的留言给我,我必定及时回复......今天就酱紫了!