zoukankan      html  css  js  c++  java
  • 自定义ViewGroup添加布局动画

    声明几个属性值:

    <declare-styleable name="GridImageViewGroup">
         <attr name="childVerticalSpace" format="dimension"/>
         <attr name="childHorizontalSpace" format="dimension"/>
         <attr name="columnNum" format="integer"/>
    </declare-styleable>

    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     @Override
    21     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     @Override
    44     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 <com.whoislcj.animation.GridImageViewGroup
    2             android:id="@+id/image_layout"
    3             android:layout_width="match_parent"
    4             android:layout_height="wrap_content"
    5             android:layout_margin="10dp"
    6             android:animateLayoutChanges="true"
    7             lee:childHorizontalSpace="10dp"
    8             lee:childVerticalSpace="10dp"
    9             lee:columnNum="3"/>

    在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             @Override
    19             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 <com.whoislcj.animation.GridImageViewGroup
    2             android:id="@+id/image_layout"
    3             android:layout_width="match_parent"
    4             android:layout_height="wrap_content"
    5             android:layout_margin="10dp"
    6             android:animateLayoutChanges="true"
    7             lee:childHorizontalSpace="10dp"
    8             lee:childVerticalSpace="10dp"
    9             lee:columnNum="3"/>

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

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

    第二种方式: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实现

    <?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="3"/>

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

    总结:

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

  • 相关阅读:
    Java 嵌套循环之九九乘法表
    Java switch语句第二种用法
    Java switch语句
    Java if-else if-else多选择结构代码
    Java if else双选择结构之计算圆的面积和周长
    Java if单选择结构---掷色子游戏
    在webstorm11中使用nodejs库的智能提示功能
    Node.JS 学习路线图
    Nodejs系列课程,从入门到进阶帮你打通全栈
    使用supervisor提高nodejs调试效率
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/8985002.html
Copyright © 2011-2022 走看看