自定义ViewGroup添加布局动画
声明几个属性值:
<declare-styleable name="GridImageViewGroup">
<attr name="childVerticalSpace" format="dimension"/>
<attr name="childHorizontalSpace" format="dimension"/>
<attr name="columnNum" format="integer"/>
</declare-styleable>
GridImageViewGroup.java 代码:
public class GridImageViewGroup extends ViewGroup {
private int childVerticalSpace = ;
private int childHorizontalSpace = ;
private int columnNum = ;
private int childWidth = ;
private int childHeight = ;
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, );
childHorizontalSpace = attributes.getDimensionPixelSize(R.styleable.GridImageViewGroup_childHorizontalSpace, );
columnNum = attributes.getInt(R.styleable.GridImageViewGroup_columnNum, );
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 > ) {
childWidth = (rw - (columnNum - ) * childHorizontalSpace) / columnNum;
childHeight = childWidth;
int vw = rw;
if (childCount < columnNum) {
vw = childCount * (childHeight + childVerticalSpace);
}
int rowCount = childCount / columnNum + (childCount % columnNum != ? : );
int vh = rowCount * childHeight + (rowCount > ? rowCount - : ) * childVerticalSpace;
setMeasuredDimension(vw, vh);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left = ;
int top = ;
int count = getChildCount();
for (int i = ; 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中引用:
<com.whoislcj.animation.GridImageViewGroup
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=""/>
在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, );
}
实现效果如下:

布局动画产生的背景:
凡事总要问个明白,为何要引入布局动画呢?其实通过上面的实现效果可以看出,在添加和删除图片时都显得很突兀,不知道该用什么语言形容了,总之就是感觉不舒服。其实我平时在开发中调用View.setVisibility()方法时也会有这种感受,这也是布局动画产生的一个背景吧。
布局动画:
布局动画是指ViewGroup在布局时产生的动画效果 。实现布局动画有如下几种方式
第一种方式:在xml中,对ViewGrope设置android:animateLayoutChanges="true"属性:
<com.whoislcj.animation.GridImageViewGroup
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=""/>
就这么简单的一句话实现的效果就可以实现了,看看效果如何

这种方式虽然简单但是实现的布局动画比较单一,下面看第二种方式。
第二种方式:LayoutTransition实现
LayoutTransition mLayoutTransition = new LayoutTransition();
//设置每个动画持续的时间
mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, );
mLayoutTransition.setStagger(LayoutTransition.CHANGE_DISAPPEARING, );
mLayoutTransition.setStagger(LayoutTransition.APPEARING, );
mLayoutTransition.setStagger(LayoutTransition.DISAPPEARING, );
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 —— 由于容器中某个元素要消失,其它元素的变化需要动画显示。
看下修改过的动画效果:

第三种方式:通过设置LayoutAnimation来实现布局动画
AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f);
alphaAnimation.setDuration();
LayoutAnimationController animationController = new LayoutAnimationController(alphaAnimation, 0.5f);
animationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
mImageViewGroup.setLayoutAnimation(animationController);
显示顺序有以下几种:
- ORDER_NORMAL;//顺序显示
- ORDER_REVERSE;//反显示
- ORDER_RANDOM//随机显示
也可以通过xml实现
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/alpha"
/>
ViewGroup xml添加android:layoutAnimation属性
<com.whoislcj.animation.GridImageViewGroup
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=""/>
由于这种方式采用的是补间动画,个人不再推荐使用这种方式,原因很简单实现的动画效果相对单一。
总结:
本篇学习了布局动画,自此Android的动画学习也将告一段落了,接下来准备总结一下学习动画的过程中遇见的编程知识,比如链式编程,TreadLocal等。
自定义ViewGroup添加布局动画的更多相关文章
- Android动画效果之自定义ViewGroup添加布局动画
前言: 前面几篇文章介绍了补间动画.逐帧动画.属性动画,大部分都是针对View来实现的动画,那么该如何为了一个ViewGroup添加动画呢?今天结合自定义ViewGroup来学习一下布局动画.本文将通 ...
- Android笔记之为自定义对话框添加移动动画效果
给底部的对话框添加移动动画效果 可通过Window.setWindowAnimations(int resId)设置 SharingDialog.java package com.bu_ish.sha ...
- Android -- 自定义ViewGroup+贝塞尔+属性动画实现仿QQ点赞效果
1,昨天我们写了篇简单的贝塞尔曲线的应用,今天和大家一起写一个QQ名片上常用的给别人点赞的效果,实现效果图如下: 红心的图片比较丑,见谅见谅(哈哈哈哈哈哈).... 2,实现的思路和原理 从上面的效果 ...
- AndroidUI 布局动画-为列表添加布局动画效果
新建一个Android project ,使MainActivity 继承自 ListActivity: public class MainActivity extends ListActivity ...
- Android Animation动画实战(一): 从布局动画引入ListView滑动时,每一Item项的显示动画
前言: 之前,我已经写了两篇博文,给大家介绍了Android的基础动画是如何实现的,如果还不清楚的,可以点击查看:Android Animation动画详解(一): 补间动画 及 Android An ...
- Android中的布局动画
简介 布局动画是给布局的动画,会影响到布局中子对象 使用方法 给布局添加动画效果: 先找到要设置的layout的id,然后创建布局动画,创建一个LayoutAnimationController,并把 ...
- android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu
示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这里我简单说明一下用自定义ViewGroup来实现. 实现方法:我们自定义一个ViewGroup实现左右滑动, ...
- android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu[转]
http://blog.csdn.net/jj120522/article/details/8095852 示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这 ...
- Android 进阶自定义 ViewGroup 自定义布局
前言 在我们的实际应用中, 经常需要用到自定义控件,比如自定义圆形头像,自定义计步器等等.但有时我们不仅需要自定义控件,举个例子,FloatingActionButton 大家都很常用,所以大家也很经 ...
随机推荐
- Day 21:Docker 入门教程
几个月以前,红帽(Red Hat)宣布了在 Docker 技术上和 dotCloud 建立合作关系.在那时候,我并没有时间去学习关于 Docker 的知识,所以在今天,趁着这个 30 天的挑战,我决定 ...
- Linux上程序调试的基石(2)--GDB
3. GDB的实现 GDB是GNU发布的一个强大的程序调试工具,用以调试C/C++程序.可以使程序员在程序运行的时候观察程序在内存/寄存器中的使用情况.它的实现也是基于ptrace系统调用来完成的. ...
- Java-IO之CharArrayWriter(字符数组输出流)
CharArrayWriter用于写数据,数据单位是字符. (1) 通过CharArrayWriter()创建的CharArrayWriter对应的字符数组大小是32. (2) 通过CharArray ...
- Ubuntu 15.10下的WebStorm-11.0.3完美破解
由于最新的JetBrains 发布了最新版本的IntelliJ IDEA的各个版本,而且更换了注册机的使用方式,这就导致了之前对WebStorm的破解方法不能在使用了.所以我们就必须另寻他法咯.如题, ...
- Ubuntu文件中文乱码
如图,该文件在gedit打开中文显示正常 在命令行中用vim打开,显示内容如下: 使用命令进行编码转换 iconv -f gbk -t utf8 ./SogouQ.mini > ./sougou ...
- TOMCAT数据源连接配置
/* *本文档简单介绍系统使用TOMCAT6.0数据源方式连接数据库的配置方法: *1,系统环境: gdczsam4.0 + Tomcat6.0 + JDK1.5 + SQL Server2008 ...
- Cocos2D:塔防游戏制作之旅(四)
让我们看一下项目的结构.在TowerDefense文件夹,你将找到: 含有Cocos2D文件的libs文件夹 含有所有图片和声音的资源文件夹 现在,你已经准备就绪准备开始建造炮台之旅了 ;) 放置炮塔 ...
- 网站开发进阶(三十四)编码中的setCharacterEncoding 理解
编码中的setCharacterEncoding 理解 1.pageEncoding="UTF-8"的作用是设置JSP编译成Servlet时使用的编码. 2.contentType ...
- 11、Libgdx的音频
(官网:www.libgdx.cn) Libgdx提供了简单的方法对较小的音效和磁盘中的音乐进行回放.它同样也提供了方便的针对音频硬件的读写权限. 所有的音频操作都通过audio模块来完成: Audi ...
- 【IOS 开发】Object - C 语法 之 类型转换
作者 : 万境绝尘 (octopus_truth@163.com) 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/3913507 ...