android 动画布局,Android动画总结——布局动画、转场动画

本文深入解析Android中的布局动画(LayoutAnimation与LayoutTransition)和转场动画(ActivityTransition),包括自定义动画效果、子View显示顺序与延迟、以及不同场景下的共享元素动画。掌握这些技巧,提升用户体验和界面过渡的优雅性。
摘要由CSDN通过智能技术生成

之前一篇文章总结了View动画、属性动画、帧动画,这篇文章继续总结布局动画、转场动画。

一、布局动画

布局动画的作用于ViewGroup,执行动画效果的是内部的子View。布局动画在android中可以通过LayoutAnimation或LayoutTransition来实现。

1.LayoutAnimation

LayoutAnimation实际上是一个View动画,用来控制子View显示时的动画效果。可以通过Java代码或者Xml文件来定义LayoutAnimation动画。

(1)通过Java代码来定义LayoutAnimation

定义子View的显示动画layout_item_anim_set.xml:

android:duration="300"

android:interpolator="@android:anim/accelerate_interpolator"

android:shareInterpolator="true">

android:fromAlpha="0.0"

android:toAlpha="1.0"/>

android:fromXDelta="500"

android:toXDelta="0"/>

以ListView为例,给ListView设置item的显示动画:

private void setLayoutAnimation() {

Animation animation = AnimationUtils.loadAnimation(this, R.anim.layout_item_anim_set);

LayoutAnimationController controller = new LayoutAnimationController(animation);

controller.setDelay(0.5f);

controller.setOrder(LayoutAnimationController.ORDER_NORMAL);

mListView.setLayoutAnimation(controller);

}

(2)通过Xml代码来定义LayoutAnimation:

layout_anim.xml

xmlns:android="http://schemas.android.com/apk/res/android"

android:animation="@anim/layout_item_anim_set"

android:animationOrder="normal"

android:delay="0.5">

在ListView所在布局中调用:

android:id="@+id/list_view"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:divider="#f1f1f1"

android:dividerHeight="1dp"

android:layoutAnimation="@anim/layout_anim"

android:listSelector="?android:attr/selectableItemBackground"/>

setDelay()方法以及android:delay属性表示子View动画显示的延迟时间比例。比如动画执行时间是300ms,延迟比例是0.5,那么延迟时间就是150ms,在Listview中,第一个item在延迟150ms开始动画后,第二个在300ms后开始动画,第三个在450ms后开始,以此类推。

setOder()方法以及android:animationOrder表示动画执行的顺序类型,共有三种:normal表示子View按顺序显示,reverse表示子View按逆序显示,random表示子View随机先后显示。

4e7bbe57ac8d

LayoutAnimation效果图

2.LayoutTransition

LayoutTransition用于在ViewGroup中有子View添加、删除、隐藏、显示时所有子View动画效果。LayoutTransition有5中动画变化形式

LayoutTransition.APPEARING:子View添加到容器中时的动画效果LayoutTransition.CHANGE_APPEARING:子View添加到容器中时,其他子View位置改变的动画效果

LayoutTransition.DISAPPEARING:子View被移除时的动画效果

LayoutTransition.CHANGE_DISAPPEARING:子View被移除时,其他子View的动画效果

LayoutTransition.CHANGING:子View在容器中位置变化时其他子View的动画效果

(1)使用默认的动画样式

只需要在使用的LinearLayout、FrameLayout、RelativeLayout等ViewGroup容器的布局文件中添加android:animateLayoutChanges="true"即可,系统会使用默认的LayoutTransition来实现子View添加、删除或变化是的动画效果。

4e7bbe57ac8d

默认的LayoutTransition效果

(2)使用自定义动画样式

private void init() {

mContainer = (LinearLayout) findViewById(R.id.container);

setLayoutTransition();

}

private void setLayoutTransition() {

LayoutTransition transition = new LayoutTransition();

// 子View添加到mContainer时的动画

Animator appearAnim = ObjectAnimator

.ofFloat(null, "rotationX", 90, 0)

.setDuration(transition.getDuration(LayoutTransition.APPEARING));

transition.setAnimator(LayoutTransition.APPEARING, appearAnim);

// 子Veiw从mContainer中移除时的动画

Animator disappearAnim = ObjectAnimator

.ofFloat(null, "rotationX", 0, 90)

.setDuration(transition.getDuration(LayoutTransition.DISAPPEARING));

transition.setAnimator(LayoutTransition.DISAPPEARING, disappearAnim);

// 子Veiw添加到mContainer中时其他子View的动画

PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 0);

PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 0);

PropertyValuesHolder pvhTranslationY = PropertyValuesHolder

.ofFloat("translationX", 0, 150, 0);

Animator changeAppearAnim = ObjectAnimator

.ofPropertyValuesHolder(mContainer, pvhLeft, pvhTop, pvhTranslationY)

.setDuration(transition.getDuration(LayoutTransition.CHANGE_APPEARING));

transition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeAppearAnim);

// 子View从mContainer中移除时其他子View的动画

PropertyValuesHolder outLeft = PropertyValuesHolder.ofInt("left", 0, 0);

PropertyValuesHolder outTop = PropertyValuesHolder.ofInt("top", 0, 0);

PropertyValuesHolder pvhTranslationYDis = PropertyValuesHolder

.ofFloat("translationX", 0, -150, 0);

ObjectAnimator changeDisAppearAnim = ObjectAnimator

.ofPropertyValuesHolder(mContainer, outLeft, outTop, pvhTranslationYDis)

.setDuration(transition.getDuration(LayoutTransition.CHANGE_DISAPPEARING));

transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeDisAppearAnim);

mContainer.setLayoutTransition(transition);

}

// 添加子View到第0个位置

public void addData(View view) {

View child = LayoutInflater.from(this)

.inflate(R.layout.item, mContainer, false);

mContainer.addView(child, 0);

}

// 移除第0个子View

public void deleteData(View view) {

if (mContainer.getChildCount() != 0) mContainer.removeViewAt(0);

}

在使用PropertyValuesHolder时,需要注意一下几点:

1.LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING必须使用PropertyValuesHolder构造动画才会有效果,其他任何方式构造动画都不会有效果。

2.在使用PropertyValuesHolder时,”left”、”top”属性就算不需要变化也必须要写,如果不需要变化可以写成:

PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 0);

PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 0);

3.ofInt,ofFloat中的参数值,第一个值和最后一个值必须相同,不然此属性所对应的的动画将被放弃,在此属性值上将不会有效果:

PropertyValuesHolder pvhTranslationY = PropertyValuesHolder

.ofFloat("translationX", 0, 150, 0);

4.使用的ofInt,ofFloat中,如果所有参数值都相同,也将不会有动画效果。

PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 0);

动画的参数全部相同,left这个属性的动画不会有任何效果。

4e7bbe57ac8d

自定义动画样式配置LayoutTransition效果

二、转场动画

1.Android 5.0之前转场动画

在Android 5.0以前实现转场动画是通过补间动画来实现,通常是在Activity中是overridePendingTransition(int enterAnim, int exitAnim)方法。

enterAnim和exitAnim两个参数对应的是两个View动画:

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_anim);

setStartActivityAnim();

}

private void setStartActivityAnim() {

overridePendingTransition(R.anim.activity_right_in, R.anim.activity_left_out);

}

入场动画activity_right_in.xml:

xmlns:android="http://schemas.android.com/apk/res/android"

android:duration="300"

android:fromXDelta="100%p"

android:toXDelta="0"/>

出场动画activity_left_out.xml:

xmlns:android="http://schemas.android.com/apk/res/android"

android:duration="300"

android:fromXDelta="0"

android:toXDelta="-100%p"/>

在Activity的onCreate中调用overridePendingTransition方法只对主动启动Activity有效,如果我们返回上一个Activity也需要同样的转场动画,就需要在finish方法也添加上这个方法。

@Override

public void finish() {

super.finish();

setEndActivityAnim();

}

private void setEndActivityAnim() {

overridePendingTransition(R.anim.activity_left_in, R.anim.activity_right_out);

}

finish时入场动画activity_left_in.xml:

xmlns:android="http://schemas.android.com/apk/res/android"

android:duration="300"

android:fromXDelta="-100%p"

android:toXDelta="0"/>

finish时出场动画activity_right_out.xml:

xmlns:android="http://schemas.android.com/apk/res/android"

android:duration="300"

android:fromXDelta="0"

android:toXDelta="100%p"/>

4e7bbe57ac8d

Android 5.0前转场动画效果

2.Android 5.0之后转场动画 Activity Transition

Android 5.0之后,谷歌引入了 Activity Transition 来实现交互更加友好的转场动画效果。

Tansition的类型共有三种:

进入 —— 决定Activity中的所有视图怎么进入屏幕

退出 —— 决定Activity中的所有视图怎么退出屏幕

共享元素 —— 决定两个Activity之间的过渡时怎么共享它们的视图

进入和退出包含如下动画效果:

explode(分解) —— 从屏幕中间进或出

slide(滑动) —— 从屏幕边缘进或出地

fade(淡出) —— 改变屏幕上视图的不透明度实现添加或移除视图的效果

共享元素包含如下动画效果:

changeBounds —— 改变目标视图的布局边界

changeClipBounds —— 裁剪目标视图边界

changeTransform —— 改变目标视图的缩放比例和旋转角度

changeImageTransform —— 改变目标图片的大小和缩放比例

说明:Tansition分类及动画效果说明参考《Android群英传》

先来看下Explode(分解)、Slide(滑动)、Fade(淡出)三种转场动画的使用。

第一个Activity中:

public void explode(View view) {

Intent intent = new Intent(this, NextTransitionActivity.class);

intent.putExtra("flag", "explode");

startActivity(intent,

ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle());

}

public void slide(View view) {

Intent intent = new Intent(this, NextTransitionActivity.class);

intent.putExtra("flag", "slide");

startActivity(intent,

ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle());

}

public void fade(View view) {

Intent intent = new Intent(this, NextTransitionActivity.class);

intent.putExtra("flag", "fade");

startActivity(intent,

ActivityOptionsCompat.makeSceneTransitionAnimation(this).toBundle());

}

启动的第二个Activity中:

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

switch (getIntent().getStringExtra("flag")) {

case "explode":

getWindow().setEnterTransition(new Explode());

getWindow().setExitTransition(new Explode());

break;

case "slide":

getWindow().setEnterTransition(new Slide());

getWindow().setExitTransition(new Slide());

break;

case "fade":

getWindow().setEnterTransition(new Fade());

getWindow().setExitTransition(new Fade());

break;

}

setContentView(R.layout.activity_next_transition);

}

在第二个Activity中可以通过在style中配置true

就不需要调用getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)。

4e7bbe57ac8d

共享元素转场动画,使用也比较简单:

@Override

public void onItemClick(AdapterView> parent, View view, int position, long id) {

TransitionAdapter.TransitionViewHolder holder = (TransitionAdapter.TransitionViewHolder) view.getTag();

View shareViewImg = holder.civImg;

View shareViewName = holder.tvName;

Intent intent = new Intent(this, NextTransitionActivity.class);

intent.putExtra("flag", "share");

startActivity(intent, ActivityOptionsCompat

.makeSceneTransitionAnimation(this,

Pair.create(shareViewImg, "shareView_img"),

Pair.create(shareViewName, "shareView_name"))

.toBundle());

}

这里使用ListView实现一个列表,列表中的头像和名字作为共享元素。在ListView的item的布局以及第二个启动的Activity的布局中,被共享的View都需要在布局文件中添加上相同android:transitionName属性,当然也可以在Java代码中通过ViewCompat.setTransitionName(View view, String transitionName)方法来设置共享View的transitionName。

我们给头像和名称分别指定android:transitionName="shareView_img"和android:transitionName="shareView_name"。

点击item后启动目标Activity时,指定的options参数为:

ActivityOptionsCompat.makeSceneTransitionAnimation(this,

Pair.create(shareViewImg,"shareView_img"),

Pair.create(shareViewName, "shareView_name"))

.toBundle());

通过options参数,可以利用Pair构造多个共享元素,但是共享元素View的共享名称transitionName必须一一对应。

4e7bbe57ac8d

共享元素转场动画效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值