声明几个属性值:
GridImageViewGroup.java 代码:
1 public class GridImageViewGroup extends ViewGroup { 2 private int childVerticalSpace = 0; 3 private int childHorizontalSpace = 0; 4 private int columnNum = 3; 5 private int childWidth = 0; 6 private int childHeight = 0; 7 8 9 public GridImageViewGroup(Context context, AttributeSet attrs) {10 super(context, attrs);11 TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.GridImageViewGroup);12 if (attributes != null) {13 childVerticalSpace = attributes.getDimensionPixelSize(R.styleable.GridImageViewGroup_childVerticalSpace, 0);14 childHorizontalSpace = attributes.getDimensionPixelSize(R.styleable.GridImageViewGroup_childHorizontalSpace, 0);15 columnNum = attributes.getInt(R.styleable.GridImageViewGroup_columnNum, 3);16 attributes.recycle();17 }18 }19 20 @Override21 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {22 super.onMeasure(widthMeasureSpec, heightMeasureSpec);23 int rw = MeasureSpec.getSize(widthMeasureSpec);24 int rh = MeasureSpec.getSize(heightMeasureSpec);25 int childCount = getChildCount();26 if (childCount > 0) {27 childWidth = (rw - (columnNum - 1) * childHorizontalSpace) / columnNum;28 29 childHeight = childWidth;30 31 int vw = rw;32 if (childCount < columnNum) {33 vw = childCount * (childHeight + childVerticalSpace);34 }35 int rowCount = childCount / columnNum + (childCount % columnNum != 0 ? 1 : 0);36 37 int vh = rowCount * childHeight + (rowCount > 0 ? rowCount - 1 : 0) * childVerticalSpace;38 39 setMeasuredDimension(vw, vh);40 }41 }42 43 @Override44 protected void onLayout(boolean changed, int l, int t, int r, int b) {45 int left = 0;46 int top = 0;47 int count = getChildCount();48 for (int i = 0; i < count; i++) {49 View child = getChildAt(i);50 left = (i % columnNum) * (childWidth + childHorizontalSpace);51 top = (i / columnNum) * (childHeight + childVerticalSpace);52 child.layout(left, top, left + childWidth, top + childHeight);53 }54 }
在xml中引用:
1
在Activity中调用:
1 private void initViews() { 2 mImageViewGroup = (GridImageViewGroup) findViewById(R.id.image_layout); 3 ImageView imageView = new ImageView(this); 4 imageView.setImageResource(R.mipmap.add_image); 5 imageView.setOnClickListener(new View.OnClickListener() { 6 @Override 7 public void onClick(View v) { 8 addImageView(); 9 }10 });11 mImageViewGroup.addView(imageView);12 }13 14 public void addImageView() {15 final ImageView imageView = new ImageView(MainActivity4.this);16 imageView.setImageResource(R.mipmap.lottery);17 imageView.setOnClickListener(new View.OnClickListener() {18 @Override19 public void onClick(View v) {20 mImageViewGroup.removeView(imageView);21 }22 });23 mImageViewGroup.addView(imageView, 0);24 }
实现效果如下:
布局动画产生的背景:
凡事总要问个明白,为何要引入布局动画呢?其实通过上面的实现效果可以看出,在添加和删除图片时都显得很突兀,不知道该用什么语言形容了,总之就是感觉不舒服。其实我平时在开发中调用View.setVisibility()方法时也会有这种感受,这也是布局动画产生的一个背景吧。
布局动画:
布局动画是指ViewGroup在布局时产生的动画效果 。实现布局动画有如下几种方式
第一种方式:在xml中,对ViewGrope设置android:animateLayoutChanges="true"
属性:
1
就这么简单的一句话实现的效果就可以实现了,看看效果如何
这种方式虽然简单但是实现的布局动画比较单一,下面看第二种方式。
第二种方式:LayoutTransition实现
1 LayoutTransition mLayoutTransition = new LayoutTransition(); 2 3 //设置每个动画持续的时间 4 mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, 50); 5 mLayoutTransition.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 50); 6 mLayoutTransition.setStagger(LayoutTransition.APPEARING, 50); 7 mLayoutTransition.setStagger(LayoutTransition.DISAPPEARING, 50); 8 9 PropertyValuesHolder appearingScaleX = PropertyValuesHolder.ofFloat("scaleX", 0.5f, 1.0f);10 PropertyValuesHolder appearingScaleY = PropertyValuesHolder.ofFloat("scaleY", 0.5f, 1.0f);11 PropertyValuesHolder appearingAlpha = PropertyValuesHolder.ofFloat("alpha", 0f, 1f);12 ObjectAnimator mAnimatorAppearing = ObjectAnimator.ofPropertyValuesHolder(this, appearingAlpha, appearingScaleX, appearingScaleY);13 //为LayoutTransition设置动画及动画类型14 mLayoutTransition.setAnimator(LayoutTransition.APPEARING, mAnimatorAppearing);15 16 17 PropertyValuesHolder disappearingAlpha = PropertyValuesHolder.ofFloat("alpha", 1f, 0f);18 PropertyValuesHolder disappearingRotationY = PropertyValuesHolder.ofFloat("rotationY", 0.0f, 90.0f);19 ObjectAnimator mAnimatorDisappearing = ObjectAnimator.ofPropertyValuesHolder(this, disappearingAlpha, disappearingRotationY);20 //为LayoutTransition设置动画及动画类型21 mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, mAnimatorDisappearing);22 23 24 ObjectAnimator mAnimatorChangeDisappearing = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);25 //为LayoutTransition设置动画及动画类型26 mLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, mAnimatorChangeDisappearing);27 28 ObjectAnimator mAnimatorChangeAppearing = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);29 //为LayoutTransition设置动画及动画类型30 mLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, mAnimatorChangeAppearing);31 32 //为mImageViewGroup设置mLayoutTransition对象33 mImageViewGroup.setLayoutTransition(mLayoutTransition);
上面通过自定义LayoutTransition 修改系统提高的默认动画效果,如果不需要自定义的动画效果的话,不调用mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, mAnimatorDisappearing);就行了。
LayoutTransition 提供了以下几种过渡类型:
- APPEARING —— 元素在容器中显现时需要动画显示。
- CHANGE_APPEARING —— 由于容器中要显现一个新的元素,其它元素的变化需要动画显示。
- DISAPPEARING —— 元素在容器中消失时需要动画显示。
- CHANGE_DISAPPEARING —— 由于容器中某个元素要消失,其它元素的变化需要动画显示。
看下修改过的动画效果:
第三种方式:通过设置LayoutAnimation来实现布局动画
1 AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f);2 alphaAnimation.setDuration(200);3 LayoutAnimationController animationController = new LayoutAnimationController(alphaAnimation, 0.5f);4 animationController.setOrder(LayoutAnimationController.ORDER_NORMAL);5 mImageViewGroup.setLayoutAnimation(animationController);
显示顺序有以下几种:
- ORDER_NORMAL;//顺序显示
- ORDER_REVERSE;//反显示
- ORDER_RANDOM//随机显示
也可以通过xml实现
ViewGroup xml添加android:layoutAnimation属性
由于这种方式采用的是补间动画,个人不再推荐使用这种方式,原因很简单实现的动画效果相对单一。
总结:
本篇学习了布局动画,自此Android的动画学习也将告一段落了,接下来准备总结一下学习动画的过程中遇见的编程知识,比如链式编程,TreadLocal等。