博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android动画效果
阅读量:5320 次
发布时间:2019-06-14

本文共 4880 字,大约阅读时间需要 16 分钟。

http://blog.csdn.net/L_wwbs/article/details/53408830

本篇通过自定义View模拟一个物理现象——竖直平面内小球在最低点以一定初速度在重力作用下绕圆环做变速圆周运动的效果(从最低点减速到0时上升到最高点再加速到初始速度时回到最低点)。可以用于加载等待等场景,下面按照自定义View的步骤具体说明一下。

1、定义属性

为了能在布局文件中使用我们的自定义控件,定制其属性,我们需要自定义一些控件的属性,以供更灵活的使用此控件。

 

[java] 
 
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <attr name="ringColor" format="color"></attr>  
  4.     <attr name="ringWidth" format="dimension"></attr>  
  5.     <attr name="globuleColor" format="color"></attr>  
  6.     <attr name="globuleRadius" format="dimension"></attr>  
  7.     <attr name="cycleTime" format="float"></attr>  
  8.     <declare-styleable name="AccelerateCircularView">  
  9.         <attr name="ringColor" />  
  10.         <attr name="ringWidth" />  
  11.         <attr name="globuleColor" />  
  12.         <attr name="globuleRadius" />  
  13.         <attr name="cycleTime" />  
  14.     </declare-styleable>  
  15. </resources>  
  16. 2、获取属性

    自定义属性完成后,我们需要在自定义View的构造方法中逐一获取这些属性。
    [java] 
     
     
    1. public AccelerateCircularView(Context context) {  
    2.        this(context, null);  
    3.    }  
    4.   
    5.    public AccelerateCircularView(Context context, AttributeSet attrs) {  
    6.        this(context, attrs, 0);  
    7.    }  
    8.   
    9.    public AccelerateCircularView(Context context, AttributeSet attrs,  
    10.                                  int defStyle) {  
    11.        super(context, attrs, defStyle);  
    12.        TypedArray attrsArray = context.getTheme().obtainStyledAttributes(  
    13.                attrs, R.styleable.AccelerateCircularView, defStyle, 0);  
    14.        mRingColor = attrsArray.getColor(  
    15.                R.styleable.AccelerateCircularView_ringColor, Color.GRAY);  
    16.        mGlobuleColor = attrsArray.getColor(  
    17.                R.styleable.AccelerateCircularView_globuleColor, Color.BLUE);  
    18.        mRingWidth = attrsArray.getDimension(  
    19.                R.styleable.AccelerateCircularView_ringWidth, TypedValue  
    20.                        .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,  
    21.                                getResources().getDisplayMetrics()));  
    22.        mGlobuleRadius = attrsArray.getDimension(  
    23.                R.styleable.AccelerateCircularView_globuleRadius, TypedValue  
    24.                        .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6,  
    25.                                getResources().getDisplayMetrics()));  
    26.        mCycleTime = attrsArray.getFloat(  
    27.                R.styleable.AccelerateCircularView_cycleTime, 3000);  
    28.        attrsArray.recycle();  
    29.        mPaint = new Paint();  
    30.   
    31.    }  
    这里要注意通过attrsArray.recycle()及时回收TypedArray ,避免浪费内存资源 。

    2、重写onMeasure

    [java] 
     
     
    1. @Override  
    2.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
    3.         int mWidth , mHeight ;  
    4.         int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
    5.         int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
    6.         int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
    7.         int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
    8.         if (widthMode == MeasureSpec.EXACTLY) {  
    9.             mWidth = widthSize;  
    10.         } else {  
    11.             mWidth = 169;  
    12.             if (widthMode == MeasureSpec.AT_MOST) {  
    13.                 mWidth = Math.min(mWidth, widthSize);  
    14.             }  
    15.   
    16.         }  
    17.         if (heightMode == MeasureSpec.EXACTLY) {  
    18.             mHeight = heightSize;  
    19.         } else {  
    20.             mHeight = 169;  
    21.             if (heightMode == MeasureSpec.AT_MOST) {  
    22.                 mHeight = Math.min(mWidth, heightSize);  
    23.             }  
    24.   
    25.         }  
    26.   
    27.         setMeasuredDimension(mWidth, mHeight);  
    28.   
    29.     }  
    这里主要是处理当VIew设置为“wrap_content”时需要自己给出测量结果,否则系统默认给我们测量的结果将是"match_parent"的大小。

    3、重写onDraw

    [java] 
     
     
    1. @Override  
    2.    protected void onDraw(Canvas canvas) {  
    3.        super.onDraw(canvas);  
    4.   
    5.        int central = Math.min(getWidth(), getHeight()) / 2;  
    6.   
    7.        mRingRadius = central - mGlobuleRadius;  
    8.   
    9.        if (mGlobuleRadius < mRingWidth / 2) {
      // 小球嵌在环里  
    10.            mRingRadius = central - mRingWidth / 2;  
    11.        }  
    12.        mPaint.setStrokeWidth(mRingWidth);  
    13.        mPaint.setStyle(Style.STROKE);  
    14.        mPaint.setAntiAlias(true);  
    15.        mPaint.setColor(mRingColor);  
    16.        canvas.drawCircle(central, central, mRingRadius, mPaint);// 绘制圆环  
    17.        mPaint.setStyle(Style.FILL);  
    18.        mPaint.setAntiAlias(true);  
    19.        mPaint.setColor(mGlobuleColor);  
    20.   
    21.        if (currentAngle == -1) {  
    22.            startCirMotion();  
    23.        }  
    24.        drawGlobule(canvas, central);// 绘制小球  
    25.    }  
    [java] 
     
     
    1. /** 
    2.    * 绘制小球,起始位置为圆环最低点 
    3.    * 
    4.    * @param canvas 
    5.    * @param central 
    6.    */  
    7.   private void drawGlobule(Canvas canvas, float central) {  
    8.   
    9.       float cx = central + (float) (mRingRadius * Math.cos(currentAngle));  
    10.       float cy = (float) (central + mRingRadius * Math.sin(currentAngle));  
    11.       canvas.drawCircle(cx, cy, mGlobuleRadius, mPaint);  
    12.   
    13.   }  
    这里完成对控件的绘制,这里根据圆环半径、当前旋转的角度结合三角函数关系来定位小球的当前坐标。其中对小球速度的控制是通过属性动画获取当前旋转角度实现。

    4、定义动画

    [java] 
     
     
    1. /** 
    2.     * 旋转小球 
    3.     */  
    4.    private void startCirMotion() {  
    5.        ValueAnimator animator = ValueAnimator.ofFloat(90f, 450f);//起始位置在最低点  
    6.        animator.setDuration((long) mCycleTime).setRepeatCount(  
    7.                ValueAnimator.INFINITE);  
    8.        animator.addUpdateListener(new AnimatorUpdateListener() {  
    9.            @Override  
    10.            public void onAnimationUpdate(ValueAnimator animation) {  
    11.                Float angle = (Float) animation.getAnimatedValue();  
    12.                currentAngle = angle * Math.PI / 180;  
    13.                invalidate();  
    14.            }  
    15.        });  
    16.        // animator.setInterpolator(new LinearInterpolator());// 匀速旋转  
    17.        // 自定义开始减速到0后加速到初始值的Interpolator  
    18.        animator.setInterpolator(new TimeInterpolator() {  
    19.   
    20.            @Override  
    21.            public float getInterpolation(float input) {  
    22.                float output;  
    23.                if (input < 0.5) {  
    24.                    output = (float) Math.sin(input * Math.PI) / 2;// 先加速  
    25.                } else {  
    26.                    output = 1 - (float) Math.sin(input * Math.PI) / 2;// 后减速,最高点(中间)速度为0  
    27.                }  
    28.                return output;  
    29.            }  
    30.        });  
    31.        animator.start();  
    32.    }  
    这里通过自定义Interpolator来实现对动画进度变化快慢的控制,动画设置的值为小球的当前角度。初值90°保证小球从最低点开始运动。
    http://blog.csdn.net/chjr1000/article/details/41823505
    http://blog.csdn.net/lmj623565791/article/details/45460089

转载于:https://www.cnblogs.com/wcLT/p/7894200.html

你可能感兴趣的文章
Leetcode 589. N-ary Tree Preorder Traversal
查看>>
机器学习/深度学习/其他开发环境搭建记录
查看>>
xml.exist() 实例演示
查看>>
判断是否为空然后赋值
查看>>
zabbix监控日志文件
查看>>
正则表达式
查看>>
pip install torch on windows, and the 'from torch._C import * ImportError: DLL load failed:' s...
查看>>
java基础(一):我对java的三个环境变量的简单理解和配置
查看>>
arcgis api 4.x for js 结合 Echarts4 实现散点图效果(附源码下载)
查看>>
YTU 2625: B 构造函数和析构函数
查看>>
apache自带压力测试工具ab的使用及解析
查看>>
C#使用Xamarin开发可移植移动应用(2.Xamarin.Forms布局,本篇很长,注意)附源码
查看>>
jenkins搭建
查看>>
C#中使用Split分隔字符串的技巧
查看>>
加固linux
查看>>
IPSP问题
查看>>
10.17动手动脑
查看>>
WPF中Image显示本地图片
查看>>
Windows Phone 7你不知道的8件事
查看>>
java的二叉树树一层层输出,Java构造二叉树、树形结构先序遍历、中序遍历、后序遍历...
查看>>