Android動畫效果之自定義ViewGroup添加布局動畫(五)
前言:
前面幾篇文章介紹了補間動畫、逐幀動畫、屬性動畫,大部分都是針對View來實現(xiàn)的動畫,那么該如何為了一個ViewGroup添加動畫呢?今天結(jié)合自定義ViewGroup來學(xué)習(xí)一下布局動畫。本文將通過對自定義圖片選擇控件設(shè)置動畫為例來學(xué)習(xí)布局動畫。
自定義一個顯示多行圖片的ViewGroup:
這里不再對自定義控件做解說,想了解的可以看下以下幾篇文章
•Android自定義控件之基本原理(一)
•Android自定義控件之自定義屬性(二)
•Android自定義控件之自定義組合控件(三)
•Android自定義控件之自定義ViewGroup實現(xiàn)標(biāo)簽云(四)
聲明幾個屬性值:
<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 = 0;
private int childHorizontalSpace = 0;
private int columnNum = 3;
private int childWidth = 0;
private int childHeight = 0;
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, 0);
childHorizontalSpace = attributes.getDimensionPixelSize(R.styleable.GridImageViewGroup_childHorizontalSpace, 0);
columnNum = attributes.getInt(R.styleable.GridImageViewGroup_columnNum, 3);
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 > 0) {
childWidth = (rw - (columnNum - 1) * childHorizontalSpace) / columnNum;
childHeight = childWidth;
int vw = rw;
if (childCount < columnNum) {
vw = childCount * (childHeight + childVerticalSpace);
}
int rowCount = childCount / columnNum + (childCount % columnNum != 0 ? 1 : 0);
int vh = rowCount * childHeight + (rowCount > 0 ? rowCount - 1 : 0) * childVerticalSpace;
setMeasuredDimension(vw, vh);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int left = 0;
int top = 0;
int count = getChildCount();
for (int i = 0; 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="3"/>
在Activity中調(diào)用:
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, 0);
}
實現(xiàn)效果如下:

布局動畫產(chǎn)生的背景:
凡事總要問個明白,為何要引入布局動畫呢?其實通過上面的實現(xiàn)效果可以看出,在添加和刪除圖片時都顯得很突兀,不知道該用什么語言形容了,總之就是感覺不舒服。其實我平時在開發(fā)中調(diào)用View.setVisibility()方法時也會有這種感受,這也是布局動畫產(chǎn)生的一個背景吧。
布局動畫:
布局動畫是指ViewGroup在布局時產(chǎn)生的動畫效果 。實現(xiàn)布局動畫有如下幾種方式
第一種方式:在xml中,對ViewGrope設(shè)置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="3"/>
就這么簡單的一句話實現(xiàn)的效果就可以實現(xiàn)了,看看效果如何

這種方式雖然簡單但是實現(xiàn)的布局動畫比較單一,下面看第二種方式。
第二種方式:LayoutTransition實現(xiàn)
LayoutTransition mLayoutTransition = new LayoutTransition();
//設(shè)置每個動畫持續(xù)的時間
mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, 50);
mLayoutTransition.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 50);
mLayoutTransition.setStagger(LayoutTransition.APPEARING, 50);
mLayoutTransition.setStagger(LayoutTransition.DISAPPEARING, 50);
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設(shè)置動畫及動畫類型
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設(shè)置動畫及動畫類型
mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, mAnimatorDisappearing);
ObjectAnimator mAnimatorChangeDisappearing = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);
//為LayoutTransition設(shè)置動畫及動畫類型
mLayoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, mAnimatorChangeDisappearing);
ObjectAnimator mAnimatorChangeAppearing = ObjectAnimator.ofFloat(null, "alpha", 1f, 0f);
//為LayoutTransition設(shè)置動畫及動畫類型
mLayoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, mAnimatorChangeAppearing);
//為mImageViewGroup設(shè)置mLayoutTransition對象
mImageViewGroup.setLayoutTransition(mLayoutTransition);
上面通過自定義LayoutTransition 修改系統(tǒng)提高的默認動畫效果,如果不需要自定義的動畫效果的話,不調(diào)用mLayoutTransition.setAnimator(LayoutTransition.DISAPPEARING, mAnimatorDisappearing);就行了。
LayoutTransition 提供了以下幾種過渡類型:
•APPEARING —— 元素在容器中顯現(xiàn)時需要動畫顯示。
•CHANGE_APPEARING —— 由于容器中要顯現(xiàn)一個新的元素,其它元素的變化需要動畫顯示。
•DISAPPEARING —— 元素在容器中消失時需要動畫顯示。
•CHANGE_DISAPPEARING —— 由于容器中某個元素要消失,其它元素的變化需要動畫顯示。
看下修改過的動畫效果:

第三種方式:通過設(shè)置LayoutAnimation來實現(xiàn)布局動畫
AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f); alphaAnimation.setDuration(200); LayoutAnimationController animationController = new LayoutAnimationController(alphaAnimation, 0.5f); animationController.setOrder(LayoutAnimationController.ORDER_NORMAL); mImageViewGroup.setLayoutAnimation(animationController);
顯示順序有以下幾種:
• ORDER_NORMAL;//順序顯示
• ORDER_REVERSE;//反顯示
• ORDER_RANDOM//隨機顯示
也可以通過xml實現(xiàn)
<?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"/>
由于這種方式采用的是補間動畫,個人不再推薦使用這種方式,原因很簡單實現(xiàn)的動畫效果相對單一。
總結(jié):
本篇學(xué)習(xí)了布局動畫,自此Android的動畫學(xué)習(xí)也將告一段落了,接下來準(zhǔn)備總結(jié)一下學(xué)習(xí)動畫的過程中遇見的編程知識,比如鏈?zhǔn)骄幊?,TreadLocal等。
- Android自定義ViewGroup實現(xiàn)帶箭頭的圓角矩形菜單
- Android自定義ViewGroup實現(xiàn)堆疊頭像的點贊Layout
- Android自定義ViewGroup實現(xiàn)標(biāo)簽浮動效果
- Android自定義ViewGroup之實現(xiàn)FlowLayout流式布局
- Android App開發(fā)中自定義View和ViewGroup的實例教程
- 一篇文章弄懂Android自定義viewgroup的相關(guān)難點
- Android應(yīng)用開發(fā)中自定義ViewGroup的究極攻略
- Android自定義ViewGroup實現(xiàn)受邊界限制的滾動操作(3)
- Android自定義ViewGroup的實現(xiàn)方法
- Android自定義ViewGroup實現(xiàn)朋友圈九宮格控件
相關(guān)文章
Android開發(fā)注解排列組合出啟動任務(wù)ksp
這篇文章主要為大家介紹了Android開發(fā)注解排列組合出啟動任務(wù)ksp示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06
GridView基于pulltorefresh實現(xiàn)下拉刷新 上拉加載更多功能(推薦)
原理和listview一樣 ,都是重寫Android原生控件。下面小編通過實例代碼給大家分享GridView基于pulltorefresh實現(xiàn)下拉刷新 上拉加載更多功能,非常不錯,一起看看吧2016-11-11
Android 中FloatingActionButton(懸浮按鈕)實例詳解
這篇文章主要介紹了Android 中FloatingActionButton(懸浮按鈕)實例詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05
Android 自定義Switch開關(guān)按鈕的樣式實例詳解
本文主要講的是在Android原生Switch控件的基礎(chǔ)上進行樣式自定義,內(nèi)容很簡單,但是在實現(xiàn)的過程中還是遇到了一些問題,在此記錄下來,需要的朋友參考下吧2017-12-12
淺談Android Activity與Service的交互方式
下面小編就為大家?guī)硪黄獪\談Android Activity與Service的交互方式。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09
Android編程實現(xiàn)可滑動的開關(guān)效果(附demo源碼下載)
這篇文章主要介紹了Android編程實現(xiàn)可滑動的開關(guān)效果,涉及Android的布局與控件設(shè)置技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2016-04-04

