欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android5.0新特性详解之全新的动画

程序员文章站 2024-03-06 08:01:07
 在material design设计中,为用户与app交互反馈他们的动作行为和提供了视觉上的连贯性。material主题为控件和activity的过渡提供了一些...

 在material design设计中,为用户与app交互反馈他们的动作行为和提供了视觉上的连贯性。material主题为控件和activity的过渡提供了一些默认的动画,在android l上,允许自定义这些动画:

touch feedback 触摸反馈

circular reveal 圆形展示

curved motion 曲线运动

view state changes 视图状态变化

vector drawables 矢量图动画

activity transitions 活动转场

触摸反馈

触摸反馈是指用户在触摸控件时的一种可视化交互,在android l之前,通常是通过press色变来凸显,但是因为是瞬间变化的效果,不如动画生动。

在android l使用了rippledrawable类,用一个水波纹扩散效果在两种不同的状态间过渡。

使用material design样式的应用,button默认带有该效果。除了默认的效果外,系统还提供了另外两种效果,我们只把button的背景指定为:

?android:attr/selectableitembackground`
?android:attr/selectableitembackgroundborderless`

任何view处于可点击状态,都可以使用rippledrawable来达到水波纹特效。

我们也可以通过设置rippledrawable的颜色属性来调节动画颜色,系统默认的颜色为主题的一个属性颜色:

android:colorcontrolhighlight,所以我们可以通过修改该颜色值来统一修改默认的水波纹颜色。android:coloraccent可以修改checkbox的选中颜色,更多颜色设置请参考主题。

系统的三种触摸反馈都是通过xml构建的,内容如下:

默认:

<ripplexmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorcontrolhighlight">
<item>
<inset
android:insetleft="4dp"
android:insettop="6dp"
android:insetright="4dp"
android:insetbottom="6dp">
<shape android:shape="rectangle">
<corners android:radius="2dp"/>
<solid android:color="?android:attr/colorbuttonnormal"/>
<padding android:left="8dp"
android:top="4dp"
android:right="8dp"
android:bottom="4dp"/>
</shape>
</inset>
</item>
</ripple>

?android:attr/selectableitembackground

<ripplexmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorcontrolhighlight">
<item android:id="@android:id/mask">
<color android:color="@android:color/white"/>
</item>
</ripple>

?android:attr/selectableitembackgroundborderless

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorcontrolhighlight"/>

代码设置

rippledrawablecolorstatelist statelist = getresources().getcolorstatelist(r.color.tint_state_color);
rippledrawable rippledrawable = new rippledrawable(statelist,null,null);
view.setbackground(rippledrawable);

圆形展示

我们通常会显示或者隐藏一个view,在android l之前,这是一个生硬瞬间变化动作,现在,有了一个新的api为此效果提供一个圆形的显示或者隐藏的动画效果。

revealanimator和之前的动画使用没什么区别,同样可以设置监听器和加速器来实现各种各样的特效,该动画主要用在隐藏或者显示一个view,改变view的大小等过渡效果。

通过viewanimationutils.createcircularreveal来创建一个动画,该api接受5个参数

view :操作的视图

centerx: 动画开始的中心点x

centery :动画开始的中心点y

startradius: 动画开始半径

startradius :动画结束半径

沿着中心的缩小的动画

animatoranimator = viewanimationutils.createcircularreveal(
view, //操作的视图
view.getwidth() / 2,//动画开始的中心点x
view.getheight() / 2,//动画开始的中心点y
view.getwidth(),//动画开始半径
0 //动画结束半径
);
animator.setinterpolator(newlinearinterpolator());
animator.setduration(1000);
animator.start();

从左上角扩展的圆形动画

animatoranimator = viewanimationutils.createcircularreveal(
view,0,0,0,(float) math.hypot(view.getwidth(), view.getheight()));
animator.setduration(1000);
animator.start();

曲线运动

曲线动画在android l之前我们可以通过继承位移动画重载applytransformation函数来实现运动轨迹算法,但是操作起来比较繁琐:

通过继承位移动画,来改写applytransformation来修改位移的轨迹

public classarctranslateanimationextendsanimation {
private float mfromxvalue,mtoxvalue,mfromyvalue,mtoyvalue;
private float mfromxdelta,mtoxdelta,mfromydelta,mtoydelta;
private pointf mstart,mcontrol,mend;
public arctranslateanimation(floatfromxvalue, floattoxvalue, floatfromyvalue, floattoyvalue) {
mfromxvalue = fromxvalue;
mtoxvalue = toxvalue;
mfromyvalue = fromyvalue;
mtoyvalue = toyvalue;
}
protected void applytransformation(floatinterpolatedtime,transformationt) {
float dx =calcbezier(interpolatedtime,mstart.x,mcontrol.x,mend.x);
float dy =calcbezier(interpolatedtime,mstart.y,mcontrol.y,mend.y);
t.getmatrix().settranslate(dx,dy);
}
public void initialize(intwidth, intheight, intparentwidth, intparentheight) {
super.initialize(width,height,parentwidth,parentheight);
mfromxdelta = resolvesize(absolute,mfromxvalue,width,parentwidth);
mtoxdelta = resolvesize(absolute,mtoxvalue,width, parentwidth);
mfromydelta = resolvesize(absolute,mfromyvalue,height,parentheight);
mtoydelta = resolvesize(absolute,mtoyvalue,height, parentheight);
mstart =newpointf(mfromxdelta,mfromydelta);
mend =newpointf(mtoxdelta,mtoydelta);
mcontrol =newpointf(mfromxdelta,mtoydelta);
}
private long calcbezier(floatinterpolatedtime, floatp0, floatp1, float p2) {
return math.round((math.pow((1- interpolatedtime),2) * p0)
+ (2 * (1-interpolatedtime) * interpolatedtime * p1) +
(math.pow(interpolatedtime,2) * p2);
}
}

现在我们有了更简单的实现方式。

objectanimator新增了path方式来构建动画,并且可以同时对x,y两个属性做动画,我们只用指定一个曲线的path,即可作出曲线的动画,可以用quadto/cubicto绘制贝塞尔曲线,也可以使用arcto绘制普通的弧线

新增了pathinterpolator动画插入器,新的基于贝塞尔曲线或路径对象的插入器。这个插入器指定了一个1x1正方形运动曲线,它使用(0,0)为锚点,(1,1)为控制点,作为构造函数的参数。
视图状态变化

android l在原有的图片选择器和颜色选择器上进行了增强,不仅是控件能根据不同的状态显示不同的背景图片,还能在两种状态切换时指定一个动画,来增加过渡效果,吸引用户眼球,以突出重点内容。

statelistanimator类和图片选择器,颜色选择器类似,可以根据view的状态改变呈现不同的动画效果,通过xml我们可以构建对应不同状态的动画合集,其使用方式也非常简单,在对应的状态指定一个属性动画即可:

<selectorxmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<set>
<objectanimator android:propertyname="translationz"
android:duration="200"
android:valueto="20dp"
android:valuetype="floattype"/>
</set>
</item>
<item android:state_enabled="true"android:state_pressed="false">
<set>
<objectanimator android:propertyname="translationz"
android:duration="200"
android:valueto="0"
android:valuetype="floattype"/>
</set>
</item>
</selector>

在xml中通过android:statelistanimator来指定状态动画,代码中可以通过animationinflater.loadstatelistanimator()加载动画,并使用view.setstatelistanimator()将其指定给view。

可以在状态切换的过程指定多个属性动画的合集,继承了material主题后,按钮默认拥有了z属性动画。如果想取消这种默认状态,可以把状态动画指定为null。

除了statelistanimator类指定状态切换的属性动画外,还可以通过animatedstatelistdrawable来指定状态切换的帧动画:

<animated-selectorxmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/pressed"android:drawable="@drawable/btn_check_15"
android:state_pressed="true"/>
<item android:id="@+id/normal" android:drawable="@drawable/btn_check_0"/>
<transition android:fromid="@+id/normal"android:toid="@+id/pressed">
<animation-list>
<item android:duration="20"android:drawable="@drawable/btn_check_0"/>
<item android:duration="20"android:drawable="@drawable/btn_check_1"/>
<item android:duration="20"android:drawable="@drawable/btn_check_2"/>
</animation-list>
</transition>
</animated-selector>

矢量图动画

前面我们学习了矢量图,animatedvectordrawable类让你能使一个矢量图动起来。矢量图动画比帧动画更平滑的展现图片的变化过程,并且无论在内存占用,还是包体积占用上都要优于帧动画。通常定义一个矢量图动画需要三步:

在drawable资源目录下定义一个矢量图

<vectorxmlns:android="http://schemas.android.com/apk/res/android"
android:height="64dp"
android:width="64dp"
android:viewportheight="600"
android:viewportwidth="600">
<group
android:name="rotationgroup"
android:pivotx="300.0"
android:pivoty="300.0"
android:rotation="45.0">
<path
android:name="v"
android:fillcolor="#000000"
android:pathdata="m300,70 l0,-70 70,70 0,0 -70,70z"/>
</group>
</vector>

在anim下顶一个objectanimator,并在动画中修改矢量图的path

<setxmlns:android="http://schemas.android.com/apk/res/android">
<objectanimator
android:duration="3000"
android:propertyname="pathdata"
android:valuefrom="m300,70 l0,-70 70,70 0,0 -70,70z"
android:valueto="m300,70 l0,-70 70,0 0,140 -70,0z"
android:valuetype="pathtype"/>
</set>

在drawable下定义一个animated-vector,并把drawable指向矢量图,把target中的动画指定为之前定义的objectanimator

<animated-vectorxmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vector_drawable">
<target
android:name="v"
android:animation="@anim/vector_anim"/>
</animated-vector>

转场动画

在android l之前,我们可以在startactivity之后调用overridependingtransition来指定activity的转场动画。现在android l给我们带来了更绚丽的转场动画。

新的转场动画分为两大类,一种是普通的过渡动画,另一种是共享元素的过渡动画。

要想使用新的转场动画,可以继承material design主题后在style风格中指定:

<stylename="defaulttheme"parent="android:theme.material">
<!-- 允许使用transitions -->
<item name="android:windowcontenttransitions">true</item>
<!-- 指定进入、退出、返回、重新进入时的transitions -->
<item name="android:windowentertransition">@transition/explode</item>
<item name="android:windowexittransition">@transition/explode</item>
<item name="android:windowreturntransition">@transition/explode</item>
<item name="android:windowreentertransition">@transition/explode</item>
<!-- 指定进入、退出、返回、重新进入时的共享transitions -->
<item name="android:windowsharedelemententertransition">@transition/change</item>
<item name="android:windowsharedelementexittransition">@transition/change</item>
<item name="android:windowsharedelementreturntransition">@transition/change</item>
<item name="android:windowsharedelementreentertransition">@transition/change</item>
</style>

也可以在activity的oncreate方法中进行代码设置:

// 允许使用transitions
getwindow().requestfeature(window.feature_content_transitions);
// 指定进入、退出、返回、重新进入时的transitions
getwindow().setentertransition(newexplode());
getwindow().setexittransition(newexplode());
getwindow().setentertransition(newexplode());
getwindow().setexittransition(newexplode());
// 指定进入、退出、返回、重新进入时的共享transitions
getwindow().setsharedelemententertransition(newchangetransform());
getwindow().setsharedelementexittransition(newchangetransform());
getwindow().setsharedelementreturntransition(newchangetransform());
getwindow().setsharedelementreentertransition(newchangetransform());

普通转场动画

所有继承自visibility类都可以作为进入、退出的过度动画。如果我们想自定义进入和退出时的动画效果,只需要继承visibility,重载onappear和ondisappear方法来定义进入喝退出的动画。系统提供了三种默认方式:

explode 从屏幕中心移入或移出视图

slide 从屏幕边缘移入或移出视图

fade 改变视图的透明度

想在xml中指定自定义的进入、退出的过度动画需要先对动画进行定义:

<transitionclass="my.app.transition.customtransition"/>

注意:其中customtransition是你自定义的动画,它必须继承自visibility。

想以普通转场动画的方式启动一个activity,必须在startactivity函数中传递一个activityoptions的bundle对象:

activityoptionsoptions = activityoptions.makescenetransitionanimation(activity);
startactivity(intent,options.tobundle());

如果想让返回也具备转场效果,那么在返回的activity中不要再调用finish函数,而是应该使用finishaftertransition来结束一个activity,该函数会等待动画执行完毕才结束该activity。

共享转场动画

当两个activity具备某些相遇的元素时,共享转场动画将是一个非常好的选择。使用转场动画需要将相同的元素通过android:transitionname或者view.settransitionname设置为相同的名称,这样系统才能区分出相同的元素。

共享转场动画支持以下共享元素:

changebounds 对目标视图的大小进行动画

changeclipbounds 对目标视图的剪裁大小进行动画

changetransform 对目标视图进行缩放、旋转、位移动画

changeimagetransform 对目标图片进行缩放

通过下面的函数启动一个共享元素动画:

activityoptionsoptions = activityoptions.makescenetransitionanimation(activity,view, "name");
startactivity(intent,options.tobundle());

如果有多个共享元素,则可以通过pair进行包装处理:

activityoptionsoptions = activityoptions.makescenetransitionanimation(activity,pair.create(view1,"name1"),pair.create(view2,"name2"));
startactivity(intent,.tobundle());

返回时如果需要具备转场动画,那么也需要用finish函数替代finishaftertransition来结束一个activity。

共享转场动画通常可以根据指定的元素判断出合适的转场动画效果,不需要我们做额外的处理,也可以通过之前学习的方法进行指定共享元素转场动画效果。

组合转场动画

我们可以把多个转场动画进行组合,作出更具个性的转场效果,在资源文件中通过以下方式:

<transitionsetxmlns:android="http://schemas.android.com/apk/res/android">
<explode/>
<transition class="my.app.transition.customtransition"/>
<<changeimagetransform/>
</transitionset>

代码中我们可以通过transitionset类组合多个转场动画:

transitionsettransitionset =new transitionset();
transitionset.addtransition(newfade());
transitionset.addtransition(newchangebounds());

组合可以同时针对普通转场动画和共享元素转场动画。

转场动画也可以像普通动画一样设置持续时间,延期执行时间,速率插入器,以及动画的监听等。

转场动画通常是对整个布局起作用,如果我们想对某个特定的view实施转场动画,可以把该view设置为转场动画的target,这样转场动画将只对特定的view起作用。共享元素的动画的target需要指定为transitionname

以上所述是小编给大家介绍的android5.0新特性详解之全新的动画,希望对大家有所帮助