您的位置:首页 > 移动开发 > Android开发

第七章 Android动画机制与技巧

2018-03-12 21:26 288 查看

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);

b576
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;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  第七章