package com.cheng.animationstudy.activity;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.Keyframe;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import com.cheng.animationstudy.R;
import com.cheng.animationstudy.customview.layoutanim.FixedGridLayout;
/**
* 当Layout改变时应用动画
*/
public class LayoutAnimActivity extends AppCompatActivity {
private int mNumButtons = 1;
private ViewGroup mContainerVG = null;
private ViewGroup mParentVG;
private Button mAddNewBtn;
private CheckBox mCustomAnimCB;
private CheckBox mAppearingCB;
private CheckBox mDisappearingCB;
private CheckBox mChangingAppearingCB;
private CheckBox mChangingDisappearingCB;
// 默认的动画
private Animator mDefaultAppearingAnim, mDefaultDisappearingAnim;
private Animator mDefaultChangingAppearingAnim, mDefaultChangingDisappearingAnim;
// 自定义动画
private Animator mCustomAppearingAnim, mCustomDisappearingAnim;
private Animator mCustomChangingAppearingAnim, mCustomChangingDisappearingAnim;
// 当前动画
private Animator mCurrentAppearingAnim, mCurrentDisappearingAnim;
private Animator mCurrentChangingAppearingAnim, mCurrentChangingDisappearingAnim;
private CompoundButton.OnCheckedChangeListener mCheckboxListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layoutanim);
initView();
initListener();
}
private void initView() {
this.mContainerVG = new FixedGridLayout(this);
this.mContainerVG.setClipChildren(false);
((FixedGridLayout) mContainerVG).setCellHeight(90);
((FixedGridLayout) mContainerVG).setCellWidth(100);
this.mParentVG = (ViewGroup) findViewById(R.id.vg_parent);
this.mAddNewBtn = (Button) findViewById(R.id.btn_addnew);
// 几个多选按钮的事件都一样
this.mCustomAnimCB = (CheckBox) findViewById(R.id.cb_customanim);
// Check for disabled animations
this.mAppearingCB = (CheckBox) findViewById(R.id.cb_appearing);
this.mDisappearingCB = (CheckBox) findViewById(R.id.cb_disappearing);
this.mChangingAppearingCB = (CheckBox) findViewById(R.id.cb_changingAppearing);
this.mChangingDisappearingCB = (CheckBox) findViewById(R.id.cb_changingDisappearing);
}
private void initListener() {
// ViewGroup布局变换动画
final LayoutTransition transitioner = new LayoutTransition();
// 把LayoutTransition对象transitioner设置给这个外层容器
this.mContainerVG.setLayoutTransition(transitioner);
// 默认系列
this.mDefaultAppearingAnim = transitioner
.getAnimator(LayoutTransition.APPEARING);
this.mDefaultDisappearingAnim = transitioner
.getAnimator(LayoutTransition.DISAPPEARING);
this.mDefaultChangingAppearingAnim = transitioner
.getAnimator(LayoutTransition.CHANGE_APPEARING);
this.mDefaultChangingDisappearingAnim = transitioner
.getAnimator(LayoutTransition.CHANGE_DISAPPEARING);
// 创建自定义动画
createCustomAnimations(transitioner);
// 先将默认的作为当前的
this.mCurrentAppearingAnim = mDefaultAppearingAnim;
this.mCurrentDisappearingAnim = mDefaultDisappearingAnim;
this.mCurrentChangingAppearingAnim = mDefaultChangingAppearingAnim;
this.mCurrentChangingDisappearingAnim = mDefaultChangingDisappearingAnim;
// 加入自定义的FixedGridLayout
this.mParentVG.addView(mContainerVG);
this.mParentVG.setClipChildren(false);
this.mCheckboxListener = new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
setupTransition(transitioner);
}
};
this.mAddNewBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Add Button按钮点击事件:新增按钮,按钮的点击事件是移除自身
Button newButton = new Button(LayoutAnimActivity.this);
newButton.setText(String.valueOf(mNumButtons++));
newButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
mContainerVG.removeView(v);
}
});
// Math.min(1, mContainerVG.getChildCount()的使用:
// addView的index:最开始是0,后来都是1
// 即第一个按钮是加在index为0位置,后续添加的按钮都是插入地加在index为1,即第二的位置
mContainerVG.addView(newButton,
Math.min(1, mContainerVG.getChildCount()));
}
});
this.mCustomAnimCB.setOnCheckedChangeListener(mCheckboxListener);
this.mAppearingCB.setOnCheckedChangeListener(mCheckboxListener);
this.mDisappearingCB.setOnCheckedChangeListener(mCheckboxListener);
this.mChangingAppearingCB.setOnCheckedChangeListener(mCheckboxListener);
this.mChangingDisappearingCB.setOnCheckedChangeListener(mCheckboxListener);
}
// 多选按钮的选择变换后执行的事件方法
// 根据多选按钮的状态来设置LayoutTransition transition的四个Animator
private void setupTransition(LayoutTransition transition) {
// 首先,把多选按钮全都获取一遍
CheckBox customAnimCB = (CheckBox) findViewById(R.id.cb_customanim);
CheckBox appearingCB = (CheckBox) findViewById(R.id.cb_appearing);
CheckBox disappearingCB = (CheckBox) findViewById(R.id.cb_disappearing);
CheckBox changingAppearingCB = (CheckBox) findViewById(R.id.cb_changingAppearing);
CheckBox changingDisappearingCB = (CheckBox) findViewById(R.id.cb_changingDisappearing);
// 然后,根据多选按钮的选择状态来setAnimator
// 解释一下第一个:
// mAppearingCB.isChecked()?
// / \
// true false -> transition.setAnimator(LayoutTransition.APPEARING,null)
// |
// mCustomAnimCB.isChecked() ?
// / \
// true false ->
// transition.setAnimator(LayoutTransition.APPEARING,mDefaultAppearingAnim)
// |-->transition.setAnimator(LayoutTransition.APPEARING,mCustomAppearingAnim)
transition.setAnimator(LayoutTransition.APPEARING, appearingCB
.isChecked() ? (customAnimCB.isChecked() ? mCustomAppearingAnim
: mDefaultAppearingAnim) : null);
// 后面三个依次类推
transition
.setAnimator(
LayoutTransition.DISAPPEARING,
disappearingCB.isChecked() ? (customAnimCB.isChecked() ? mCustomDisappearingAnim
: mDefaultDisappearingAnim)
: null);
transition
.setAnimator(
LayoutTransition.CHANGE_APPEARING,
changingAppearingCB.isChecked() ? (customAnimCB
.isChecked() ? mCustomChangingAppearingAnim
: mDefaultChangingAppearingAnim) : null);
transition
.setAnimator(
LayoutTransition.CHANGE_DISAPPEARING,
changingDisappearingCB.isChecked() ? (customAnimCB
.isChecked() ? mCustomChangingDisappearingAnim
: mDefaultChangingDisappearingAnim) : null);
}
// 创建自定义动画
private void createCustomAnimations(LayoutTransition transition) {
// Changing while Adding
// 多个属性同时动画
PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1);
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1);
PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0,
1);
PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom",
0, 1);
PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX",
1f, 0f, 1f);
PropertyValuesHolder pvhScaleY = PropertyValuesHolder.ofFloat("scaleY",
1f, 0f, 1f);
// 自定义的ChangingAppearing动画
// 感觉就是从无到有地缩放了一遍
mCustomChangingAppearingAnim = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScaleX,
pvhScaleY).setDuration(
transition.getDuration(LayoutTransition.CHANGE_APPEARING));
mCustomChangingAppearingAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setScaleX(1f);
view.setScaleY(1f);
}
});
// 自定义的ChangingDisappearing动画
// 有一个平面旋转
// Changing while Removing
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe(
"rotation", kf0, kf1, kf2);
mCustomChangingDisappearingAnim = ObjectAnimator
.ofPropertyValuesHolder(this, pvhLeft, pvhTop, pvhRight,
pvhBottom, pvhRotation)
.setDuration(
transition
.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
mCustomChangingDisappearingAnim
.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotation(0f);
}
});
// 自定义的Appearing动画:纵向旋转(以Y为轴翻转)出现
// Adding
mCustomAppearingAnim = ObjectAnimator
.ofFloat(null, "rotationY", 90f, 0f).setDuration(
transition.getDuration(LayoutTransition.APPEARING));
mCustomAppearingAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotationY(0f);
}
});
// 自定义的Disappearing动画:横向旋转(以X为轴翻转)消失
// Removing
mCustomDisappearingAnim = ObjectAnimator.ofFloat(null, "rotationX", 0f,
90f).setDuration(
transition.getDuration(LayoutTransition.DISAPPEARING));
mCustomDisappearingAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotationX(0f);
}
});
}
/*
ViewGroup中的子元素可以通过setVisibility使其Visible、Invisible或Gone,当有子元素可见性改变时(VISIBLE、GONE),可以向其应用动画,通过LayoutTransition类应用此类动画:
transition.setAnimator(LayoutTransition.DISAPPEARING, mCustomDisappearingAnim);
通过setAnimator应用动画,第一个参数表示应用的情境,可以以下4种类型:
APPEARING 当一个元素在其父元素中变为Visible时对这个元素应用动画
CHANGE_APPEARING 当一个元素在其父元素中变为Visible时,因系统要重新布局有一些元素需要移动,对这些要移动的元素应用动画
DISAPPEARING 当一个元素在其父元素中变为GONE时对其应用动画
CHANGE_DISAPPEARING 当一个元素在其父元素中变为GONE时,因系统要重新布局有一些元素需要移动,这些要移动的元素应用动画.
第二个参数为一Animator
mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
此函数设置动画延迟时间,参数分别为类型与时间
*/
}