android5动画,Android动画效果之自定义ViewGroup添加布局动画(五)

前言:

前面几篇文章介绍了补间动画、逐帧动画、属性动画,大部分都是针对View来实现的动画,那么该如何为了一个ViewGroup添加动画呢?今天结合自定义ViewGroup来学习一下布局动画。本文将通过对自定义图片选择控件设置动画为例来学习布局动画。

自定义一个显示多行图片的ViewGroup:

这里不再对自定义控件做解说,想了解的可以看下以下几篇文章

•Android自定义控件之基本原理(一)

•Android自定义控件之自定义属性(二)

•Android自定义控件之自定义组合控件(三)

•Android自定义控件之自定义ViewGroup实现标签云(四)

声明几个属性值:

GridImageViewGroup.java 代码

public class GridImageViewGroup extends ViewGroup {

private int childVerticalSpace = 0;

private int childHorizontalSpace = 0;

private int columnNum = 3;

private int childWidth = 0;

private int childHeight = 0;

public GridImageViewGroup(Context context, AttributeSet attrs) {

super(context, attrs);

TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.GridImageViewGroup);

if (attributes != null) {

childVerticalSpace = attributes.getDimensionPixelSize(R.styleable.GridImageViewGroup_childVerticalSpace, 0);

childHorizontalSpace = attributes.getDimensionPixelSize(R.styleable.GridImageViewGroup_childHorizontalSpace, 0);

columnNum = attributes.getInt(R.styleable.GridImageViewGroup_columnNum, 3);

attributes.recycle();

}

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int rw = MeasureSpec.getSize(widthMeasureSpec);

int rh = MeasureSpec.getSize(heightMeasureSpec);

int childCount = getChildCount();

if (childCount > 0) {

childWidth = (rw - (columnNum - 1) * childHorizontalSpace) / columnNum;

childHeight = childWidth;

int vw = rw;

if (childCount < columnNum) {

vw = childCount * (childHeight + childVerticalSpace);

}

int rowCount = childCount / columnNum + (childCount % columnNum != 0 ? 1 : 0);

int vh = rowCount * childHeight + (rowCount > 0 ? rowCount - 1 : 0) * childVerticalSpace;

setMeasuredDimension(vw, vh);

}

}

@Override

protected void onLayout(boolean changed, int l, int t, int r, int b) {

int left = 0;

int top = 0;

int count = getChildCount();

for (int i = 0; i < count; i++) {

View child = getChildAt(i);

left = (i % columnNum) * (childWidth + childHorizontalSpace);

top = (i / columnNum) * (childHeight + childVerticalSpace);

child.layout(left, top, left + childWidth, top + childHeight);

}

}

在xml中引用:

android:id="@+id/image_layout"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="10dp"

android:animateLayoutChanges="true"

lee:childHorizontalSpace="10dp"

lee:childVerticalSpace="10dp"

lee:columnNum="3"/>

在Activity中调用:

private void initViews() {

mImageViewGroup = (GridImageViewGroup) findViewById(R.id.image_layout);

ImageView imageView = new ImageView(this);

imageView.setImageResource(R.mipmap.add_image);

imageView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

addImageView();

}

});

mImageViewGroup.addView(imageView);

}

public void addImageView() {

final ImageView imageView = new ImageView(MainActivity4.this);

imageView.setImageResource(R.mipmap.lottery);

imageView.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

mImageViewGroup.removeView(imageView);

}

});

mImageViewGroup.addView(imageView, 0);

}

实现效果如下:

e8adbdcb15e516c28bd43b00e28857a2.png

布局动画产生的背景:

凡事总要问个明白,为何要引入布局动画呢?其实通过上面的实现效果可以看出,在添加和删除图片时都显得很突兀,不知道该用什么语言形容了,总之就是感觉不舒服。其实我平时在开发中调用View.setVisibility()方法时也会有这种感受,这也是布局动画产生的一个背景吧。

布局动画:

布局动画是指ViewGroup在布局时产生的动画效果 。实现布局动画有如下几种方式

第一种方式:在xml中,对ViewGrope设置android:animateLayoutChanges="true"属性:

android:id="@+id/image_layout"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="10dp"

android:animateLayoutChanges="true"

lee:childHorizontalSpace="10dp"

lee:childVerticalSpace="10dp"

lee:columnNum="3"/>

就这么简单的一句话实现的效果就可以实现了,看看效果如何

ffa1fcaf892c0bc9914b4b6138c9072a.png

这种方式虽然简单但是实现的布局动画比较单一,下面看第二种方式。

第二种方式:LayoutTransition实现

LayoutTransition mLayoutTransition = new LayoutTransition();

//设置每个动画持续的时间

mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, 50);

mLayoutTransition.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 50);

mLayoutTransition.setStagger(LayoutTransition.APPEARING, 50);

mLayoutTransition.setStagger(LayoutTransition.DISAPPEARING, 50);

PropertyValuesHolder appearingScaleX = PropertyValuesHolder.ofFloat("scaleX", 0.5f, 1.0f);

PropertyValuesHolder appearingScaleY = PropertyValuesHolder.ofFloat("scaleY", 0.5f, 1.0f);

PropertyValuesHolder appearingAlpha = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);

ObjectAnimator mAnimatorAppearing = ObjectAnimator.ofPropertyValuesHolder(this, appearingAlpha, appearingScaleX, appearingScaleY);

//为LayoutTransition设置动画及动画类型

mLayoutTransition.setAnimator(LayoutTransition.APPEARING, mAnimatorAppearing);

PropertyValuesHolder disappearingAlpha = PropertyValuesHolder.ofFloat("alpha", 1f, 0f);

PropertyValuesHolder disappearingRotationY = PropertyValuesHolder.ofFloat("rotationY", 0.0f, 90.0f);

ObjectAnimator mAnimatorDisappearing = ObjectAnimator.ofPropertyValuesHolder(this, disappearingAlpha, disappearingRotationY);

//为LayoutTransition设置动画及动画类型

mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, mAnimatorDisappearing);

ObjectAnimator mAnimatorChangeDisappearing = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);

//为LayoutTransition设置动画及动画类型

mLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, mAnimatorChangeDisappearing);

ObjectAnimator mAnimatorChangeAppearing = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);

//为LayoutTransition设置动画及动画类型

mLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, mAnimatorChangeAppearing);

//为mImageViewGroup设置mLayoutTransition对象

mImageViewGroup.setLayoutTransition(mLayoutTransition);

上面通过自定义LayoutTransition 修改系统提高的默认动画效果,如果不需要自定义的动画效果的话,不调用mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, mAnimatorDisappearing);就行了。

LayoutTransition 提供了以下几种过渡类型:

•APPEARING —— 元素在容器中显现时需要动画显示。

•CHANGE_APPEARING —— 由于容器中要显现一个新的元素,其它元素的变化需要动画显示。

•DISAPPEARING —— 元素在容器中消失时需要动画显示。

•CHANGE_DISAPPEARING —— 由于容器中某个元素要消失,其它元素的变化需要动画显示。

看下修改过的动画效果:

06eaa4986024cc47b1682a630e13a513.png

第三种方式:通过设置LayoutAnimation来实现布局动画

AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f);

alphaAnimation.setDuration(200);

LayoutAnimationController animationController = new LayoutAnimationController(alphaAnimation, 0.5f);

animationController.setOrder(LayoutAnimationController.ORDER_NORMAL);

mImageViewGroup.setLayoutAnimation(animationController);

显示顺序有以下几种:

• ORDER_NORMAL;//顺序显示

• ORDER_REVERSE;//反显示

• ORDER_RANDOM//随机显示

也可以通过xml实现

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

android:delay="0.5"

android:animationOrder="normal"

android:animation="@anim/alpha"

/>

ViewGroup xml添加android:layoutAnimation属性

android:id="@+id/image_layout"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="10dp"

android:layoutAnimation="@anim/layoutanimation"

lee:childHorizontalSpace="10dp"

lee:childVerticalSpace="10dp"

lee:columnNum="3"/>

由于这种方式采用的是补间动画,个人不再推荐使用这种方式,原因很简单实现的动画效果相对单一。

总结:

本篇学习了布局动画,自此Android的动画学习也将告一段落了,接下来准备总结一下学习动画的过程中遇见的编程知识,比如链式编程,TreadLocal等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值