声明几个属性值:

<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添加布局动画的更多相关文章

  1. Android动画效果之自定义ViewGroup添加布局动画

    前言: 前面几篇文章介绍了补间动画.逐帧动画.属性动画,大部分都是针对View来实现的动画,那么该如何为了一个ViewGroup添加动画呢?今天结合自定义ViewGroup来学习一下布局动画.本文将通 ...

  2. Android笔记之为自定义对话框添加移动动画效果

    给底部的对话框添加移动动画效果 可通过Window.setWindowAnimations(int resId)设置 SharingDialog.java package com.bu_ish.sha ...

  3. Android -- 自定义ViewGroup+贝塞尔+属性动画实现仿QQ点赞效果

    1,昨天我们写了篇简单的贝塞尔曲线的应用,今天和大家一起写一个QQ名片上常用的给别人点赞的效果,实现效果图如下: 红心的图片比较丑,见谅见谅(哈哈哈哈哈哈).... 2,实现的思路和原理 从上面的效果 ...

  4. AndroidUI 布局动画-为列表添加布局动画效果

    新建一个Android project ,使MainActivity 继承自 ListActivity: public class MainActivity extends ListActivity ...

  5. Android Animation动画实战(一): 从布局动画引入ListView滑动时,每一Item项的显示动画

    前言: 之前,我已经写了两篇博文,给大家介绍了Android的基础动画是如何实现的,如果还不清楚的,可以点击查看:Android Animation动画详解(一): 补间动画 及 Android An ...

  6. Android中的布局动画

    简介 布局动画是给布局的动画,会影响到布局中子对象 使用方法 给布局添加动画效果: 先找到要设置的layout的id,然后创建布局动画,创建一个LayoutAnimationController,并把 ...

  7. android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu

    示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这里我简单说明一下用自定义ViewGroup来实现. 实现方法:我们自定义一个ViewGroup实现左右滑动, ...

  8. android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu[转]

    http://blog.csdn.net/jj120522/article/details/8095852 示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这 ...

  9. Android 进阶自定义 ViewGroup 自定义布局

    前言 在我们的实际应用中, 经常需要用到自定义控件,比如自定义圆形头像,自定义计步器等等.但有时我们不仅需要自定义控件,举个例子,FloatingActionButton 大家都很常用,所以大家也很经 ...

随机推荐

  1. C++对象模型的那些事儿之五:NRV优化和初始化列表

    前言 在C++对象模型的那些事儿之四:拷贝构造函数中提到如果将一个对象作为函数参数或者返回值的时候,会调用拷贝构造函数,编译器是如何处理这些步骤,又会对其做哪些优化呢?本篇博客就为他家介绍一个编译器的 ...

  2. 【java集合框架源码剖析系列】java源码剖析之java集合中的折半插入排序算法

    注:关于排序算法,博主写过[数据结构排序算法系列]数据结构八大排序算法,基本上把所有的排序算法都详细的讲解过,而之所以单独将java集合中的排序算法拿出来讲解,是因为在阿里巴巴内推面试的时候面试官问过 ...

  3. [java面试]javascript中dom取值问题radio名字一样归属于同一个组,求点击的是哪一个

    题目描述: 看如下的html文件,里面定义了一些radio类型的元素,请完成parse()函数的内容,要求能够弹出对话框提示当前选中的是第几个单选框. </pre><pre code ...

  4. python进行md5加密

    代码函数 import hashlib def md5(str): m = hashlib.md5() m.update(str) return m.hexdigest() f = open('idf ...

  5. 小文本——Cookies

    http协议的无状态性导致在需要会话的场景下寸步难行,例如一个网站为了方便用户,在一段时间内登录过改网站的浏览器客户端实现自动登录,为实现这种客户端与服务器之间的会话机制需要额外的一些标识,http头 ...

  6. java加载外部文件数据到代码中:外部数据文件放到jar包中,调用方法getResourceAsStream

    任务要将数据文件geo.txt加载进行.因为是别人写的总体项目,不能乱动位置.只能将geo.txt打包到jar中某目录.比如,放到.class文件下怎么加载:http://riddickbryant. ...

  7. 【Unity Shaders】Reflecting Your World —— 在Unity3D中创建一个简单的动态Cubemap系统

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  8. Java 8新特性探究(二)类型注解和重复注解

    本文将介绍java 8的第二个特性:类型注解. 注解大家都知道,从java5开始加入这一特性,发展到现在已然是遍地开花,在很多框架中得到了广泛的使用,用来简化程序中的配置.那充满争议的类型注解究竟是什 ...

  9. django练习——博客系统优化

    一直准备使用Django搭建一个个人网站,最近终于开始动手,上周已经完成了基本博客功能的搭建(http://blog.csdn.net/hcx25909/article/details/2460133 ...

  10. (四十二)tableView的滑动编辑和刷新 -局部刷新和删除刷新 -待解决问题

    tableView的局部刷新有两个方法: 注意这个方法只能用于模型数据的行数不变,否则会出错. [self.tableView reloadRowsAtIndexPaths:<#(NSArray ...