Android屬性動畫
private void objectAnimatorText1() {
setContentView(R.layout.activity_main);
final Button button = (Button) findViewById(R.id.bt);
LinearLayout linearLayout = findViewById(R.id.ll);
final TextView textViewFirst = linearLayout.findViewById(R.id.tv_first);
button.setOnClickListener(new View.OnClickListener() {
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
@Override
public void onClick(View v) {
/**
* 操作的屬性必須要有set、get方法,不然無法起效
*/
ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(button, "translationX", 300);
objectAnimator1.start();
/**
* 通過插值器,可以定義動畫變化速率,類似於物理中的加速度
*
* 線性插值器:在持續時間內,單位時間所移動的距離都是一樣的
* 加速度插值器:單位時間內所移動的距離越來越快
*/
objectAnimator1.setInterpolator();
objectAnimator1.addListener(new AnimatorListenerAdapter() {
/**
* 大部分我們只關心動畫結束事件
*/
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
/**
* 操作的屬性沒有set、get方法,通過自定義一個屬性類或者包裝類,來間接給這個屬性增加set、get方法
*/
WrapperView wrapperView = new WrapperView(button);
ObjectAnimator objectAnimator2 = ObjectAnimator.ofInt(wrapperView, "width", 300);
objectAnimator2.start();
/**
* 類似視圖動畫中的AnimationSet
*/
PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("translationX", 300f);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(button, holder1, holder2, holder3).setDuration(1000).start();
/**
* ValueAnimator本身不提供任何動畫效果,更像是一個數值發生器,
*/
ValueAnimator animator = ValueAnimator.ofInt(0, 400);
animator.setTarget(button);
animator.setDuration(1000).start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
/**
* 可以使用該數值做想做的事
*/
int animatedValue = (int) animation.getAnimatedValue();
Log.i(TAG, "onAnimationUpdate: "+animatedValue);
/**
* 計時器動畫
*/
textViewFirst.setText(String.valueOf(animatedValue));
}
});
/**
* Android3.0之後,Geogle給View增加了這樣一種簡易的方式驅動屬性動畫
*/
button.animate().alpha(0).y(300).setDuration(3000)
.withStartAction(new Runnable() {
@Override
public void run() {
}
}).withEndAction(new Runnable() {
@Override
public void run() {
}
}).start();
/**
* 自定義動畫
*/
MyAnimation myAnimation = new MyAnimation();
myAnimation.setDuration(1000);
button.startAnimation(myAnimation);
}
});
/**
* 佈局動畫
*/
LinearLayout linearLayout = findViewById(R.id.ll);
ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1);
scaleAnimation.setDuration(2000);
/**
* 第一個參數是需要作用的動畫,第二個參數是每個子view顯示的delay時間
* 當viewGroup添加view的時候,通過LayoutAnimationController定義一個子view的過渡效果
*/
LayoutAnimationController controller = new LayoutAnimationController(scaleAnimation, 0.5f);
/**
* delay時間不爲0的時候可以設置這個
*
* 子view出現的順序:
* ORDER_NORMAL: 順序
* ORDER_RANDOM: 隨機
* ORDER_REVERSE: 反序
*/
controller.setOrder(LayoutAnimationController.ORDER_REVERSE);
linearLayout.setLayoutAnimation(controller);
}
private static class WrapperView{
private View mTarget;
public WrapperView(View target){
mTarget = target;
}
public void setWidth(int width){
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
public int getWidth(){
return mTarget.getLayoutParams().width;
}
}
自定義動畫
/**
* 自定義動畫
*/
public class MyAnimation extends Animation {
private Camera mCamera;
private int mCenterWidth;
private int mCenterHeight;
private int mRotateY = 45;
public MyAnimation(){
mCamera = new Camera();
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
setDuration(2000);
/**
* 動畫結束後保留狀態
*/
setFillAfter(true);
setInterpolator(new BounceInterpolator());
mCenterWidth = width/2;
mCenterHeight = height/2;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
/**
* 獲得當前的矩陣對象
*/
Matrix matrix = t.getMatrix();
mCamera.save();
mCamera.rotateY(mRotateY*interpolatedTime);
/**
* 將旋轉變換作用到Matrix
*/
mCamera.getMatrix(matrix);
mCamera.restore();
/**
* 通過pre方法設置矩陣作用前的偏移量來改變旋轉中心
*/
matrix.preTranslate(mCenterWidth, mCenterHeight);
matrix.postTranslate(-mCenterWidth, mCenterHeight);
}
}
下拉展開動畫
實現類似商城購物車裏的刪除、收藏按鈕。
private void dropAnimatorText() {
setContentView(R.layout.drop);
LinearLayout ll_click = findViewById(R.id.ll_click);
final LinearLayout hidden_view = findViewById(R.id.hidden_view);
// 獲取像素密度
mDensity = getResources().getDisplayMetrics().density;
/**
* 獲取佈局的高度,40dp是佈局的高度,這裏轉化爲了像素值
*
* 因爲view還沒有測量完畢,所以獲取不到高
*/
Log.i(TAG, "dropAnimatorText: "+hidden_view.getMeasuredHeight());
mViewHeight = (int) (mDensity * 40 + 0.5);
ll_click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (hidden_view.getVisibility() == View.GONE){
animataOpen(hidden_view);
}else {
animataClose(hidden_view);
}
}
});
}
private void animataClose(final LinearLayout hidden_view) {
int height = hidden_view.getHeight();
ValueAnimator animator = createDropAnimator(hidden_view, height, 0);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
hidden_view.setVisibility(View.GONE);
}
});
animator.start();
}
private void animataOpen(View hidden_view) {
hidden_view.setVisibility(View.VISIBLE);
ValueAnimator animator = createDropAnimator(hidden_view, 0, mViewHeight);
animator.start();
}
private ValueAnimator createDropAnimator(final View hidden_view, int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int animatedValue = (int) animation.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = hidden_view.getLayoutParams();
layoutParams.height = animatedValue;
hidden_view.setLayoutParams(layoutParams);
}
});
return animator;
}