自定義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等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM