# View animation ###### tags: `Android` `Java` `基礎` ###### 2018/10/16 - 要放在支援檔 - 支援檔統一放在 res/anim/ 裡面 - 只針對繪製的那一段做改動,屬性都不會被改動,包括它的位置 #### android:fillAfter - 預設是"false" ->動畫結束後會彈回去 - "true" ->動畫結束是畫面停留在最後一幀 alpha scale translate rotate set => 動畫集合 #### translation 用於控制view的位移 android:fromXDelta => 起始X坐標(偏移) android:toXDelta => 結束坐標(偏移) android:fromYDelta => 起始Y坐標(偏移) android:toYDelta => 結束Y坐標(偏移) 以上屬性有三種格式 - (50%) (50%p) (50)•% => 自身高/寬 - 100%~100%的位置•%p => 父元件高/寬 - 100%~100%的位置•數字 => px ``` xml <?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="0%" <--! 0 -> --> android:fromYDelta="0" android:toXDelta="30%p" android:toYDelta="30%p" android:duration="2000" android:fillAfter="true" > </translate> ``` 是LayoutInflater是用來找res/layout/下的xml佈局文件,並且實例化;作用類似於findViewById(), 而findViewById()是找xml佈局文件下的具體widget控件(如 Button、TextView等) ``` public class CLL extends LinearLayout { public CLL(Context context) { super(context); init(context); } public CLL(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context); } public CLL(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } public CLL(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context); } private int tmpHeight; private boolean isCollapse; private Context context; private void init(Context context){ tmpHeight = 0; isCollapse = false; this.context = context; } public void change(){ if(getMeasuredHeight() > tmpHeight) tmpHeight = getMeasuredHeight();// 這個LinearLayout最大的高度 if(isCollapse){ expand(); }else{ collapse(); } isCollapse = !isCollapse; } private void expand(){ ValueAnimator animator = (ValueAnimator)AnimatorInflater.loadAnimator(context, R.animator.anim1); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int currentValue = (int)animation.getAnimatedValue(); getLayoutParams().height = (int)(tmpHeight * ((120 - currentValue)/100f)); requestLayout(); if(currentValue == 20 && changedListener != null){ changedListener.expand(); } } }); animator.start(); } private void collapse(){ ValueAnimator animator = (ValueAnimator)AnimatorInflater.loadAnimator(context, R.animator.anim1); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int currentValue = (int)animation.getAnimatedValue(); getLayoutParams().height = (int)(tmpHeight * (currentValue/100f)); requestLayout(); if(currentValue == 20 && changedListener != null){ changedListener.collapse(); } } }); animator.start(); } ChangedListener changedListener; public void setChangedListener(ChangedListener changedListener){ this.changedListener = changedListener; } public interface ChangedListener{ void expand(); void collapse(); } } ``` test(1); test(1,2,3); test(1,2,3,4,5,6); public void test(int... values) { }