android动画效果
Posted 小毛驴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android动画效果相关的知识,希望对你有一定的参考价值。
http://blog.csdn.net/L_wwbs/article/details/53408830
本篇通过自定义View模拟一个物理现象——竖直平面内小球在最低点以一定初速度在重力作用下绕圆环做变速圆周运动的效果(从最低点减速到0时上升到最高点再加速到初始速度时回到最低点)。可以用于加载等待等场景,下面按照自定义View的步骤具体说明一下。
1、定义属性
为了能在布局文件中使用我们的自定义控件,定制其属性,我们需要自定义一些控件的属性,以供更灵活的使用此控件。
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <attr name="ringColor" format="color"></attr>
- <attr name="ringWidth" format="dimension"></attr>
- <attr name="globuleColor" format="color"></attr>
- <attr name="globuleRadius" format="dimension"></attr>
- <attr name="cycleTime" format="float"></attr>
- <declare-styleable name="AccelerateCircularView">
- <attr name="ringColor" />
- <attr name="ringWidth" />
- <attr name="globuleColor" />
- <attr name="globuleRadius" />
- <attr name="cycleTime" />
- </declare-styleable>
- </resources>
-
2、获取属性
自定义属性完成后,我们需要在自定义View的构造方法中逐一获取这些属性。- public AccelerateCircularView(Context context) {
- this(context, null);
- }
- public AccelerateCircularView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
- public AccelerateCircularView(Context context, AttributeSet attrs,
- int defStyle) {
- super(context, attrs, defStyle);
- TypedArray attrsArray = context.getTheme().obtainStyledAttributes(
- attrs, R.styleable.AccelerateCircularView, defStyle, 0);
- mRingColor = attrsArray.getColor(
- R.styleable.AccelerateCircularView_ringColor, Color.GRAY);
- mGlobuleColor = attrsArray.getColor(
- R.styleable.AccelerateCircularView_globuleColor, Color.BLUE);
- mRingWidth = attrsArray.getDimension(
- R.styleable.AccelerateCircularView_ringWidth, TypedValue
- .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,
- getResources().getDisplayMetrics()));
- mGlobuleRadius = attrsArray.getDimension(
- R.styleable.AccelerateCircularView_globuleRadius, TypedValue
- .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6,
- getResources().getDisplayMetrics()));
- mCycleTime = attrsArray.getFloat(
- R.styleable.AccelerateCircularView_cycleTime, 3000);
- attrsArray.recycle();
- mPaint = new Paint();
- }
2、重写onMeasure
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int mWidth , mHeight ;
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- if (widthMode == MeasureSpec.EXACTLY) {
- mWidth = widthSize;
- } else {
- mWidth = 169;
- if (widthMode == MeasureSpec.AT_MOST) {
- mWidth = Math.min(mWidth, widthSize);
- }
- }
- if (heightMode == MeasureSpec.EXACTLY) {
- mHeight = heightSize;
- } else {
- mHeight = 169;
- if (heightMode == MeasureSpec.AT_MOST) {
- mHeight = Math.min(mWidth, heightSize);
- }
- }
- setMeasuredDimension(mWidth, mHeight);
- }
这里主要是处理当VIew设置为“wrap_content”时需要自己给出测量结果,否则系统默认给我们测量的结果将是"match_parent"的大小。3、重写onDraw
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- int central = Math.min(getWidth(), getHeight()) / 2;
- mRingRadius = central - mGlobuleRadius;
- if (mGlobuleRadius < mRingWidth / 2) {// 小球嵌在环里
- mRingRadius = central - mRingWidth / 2;
- }
- mPaint.setStrokeWidth(mRingWidth);
- mPaint.setStyle(Style.STROKE);
- mPaint.setAntiAlias(true);
- mPaint.setColor(mRingColor);
- canvas.drawCircle(central, central, mRingRadius, mPaint);// 绘制圆环
- mPaint.setStyle(Style.FILL);
- mPaint.setAntiAlias(true);
- mPaint.setColor(mGlobuleColor);
- if (currentAngle == -1) {
- startCirMotion();
- }
- drawGlobule(canvas, central);// 绘制小球
- }
- /**
- * 绘制小球,起始位置为圆环最低点
- *
- * @param canvas
- * @param central
- */
- private void drawGlobule(Canvas canvas, float central) {
- float cx = central + (float) (mRingRadius * Math.cos(currentAngle));
- float cy = (float) (central + mRingRadius * Math.sin(currentAngle));
- canvas.drawCircle(cx, cy, mGlobuleRadius, mPaint);
- }
4、定义动画
- /**
- * 旋转小球
- */
- private void startCirMotion() {
- ValueAnimator animator = ValueAnimator.ofFloat(90f, 450f);//起始位置在最低点
- animator.setDuration((long) mCycleTime).setRepeatCount(
- ValueAnimator.INFINITE);
- animator.addUpdateListener(new AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- Float angle = (Float) animation.getAnimatedValue();
- currentAngle = angle * Math.PI / 180;
- invalidate();
- }
- });
- // animator.setInterpolator(new LinearInterpolator());// 匀速旋转
- // 自定义开始减速到0后加速到初始值的Interpolator
- animator.setInterpolator(new TimeInterpolator() {
- @Override
- public float getInterpolation(float input) {
- float output;
- if (input < 0.5) {
- output = (float) Math.sin(input * Math.PI) / 2;// 先加速
- } else {
- output = 1 - (float) Math.sin(input * Math.PI) / 2;// 后减速,最高点(中间)速度为0
- }
- return output;
- }
- });
- animator.start();
- }
这里通过自定义Interpolator来实现对动画进度变化快慢的控制,动画设置的值为小球的当前角度。初值90°保证小球从最低点开始运动。http://blog.csdn.net/chjr1000/article/details/41823505
以上是关于android动画效果的主要内容,如果未能解决你的问题,请参考以下文章