一个工具类就搞定:

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
 * 模拟竖直平面内小球以一定初速度在重力作用下绕圆环做变速圆周运动 (从最低点减速到0上升到最高点再加速到初始值回到最低点)。
 *
 * @author jren
 *
 */
public class AccelerateCircularView extends View {/**
    * 圆环的颜色
    */
   private int mRingColor;
   /**
    * 小球的颜色
    */
   private int mGlobuleColor;
   /**
    * 圆环半径、小球的旋转半径
    */
   private float mRingRadius;
   /**
    * 圆环宽度
    */
   private float mRingWidth;
   /**
    * 小球的半径
    */
   private float mGlobuleRadius;
   protected double currentAngle = -1;
   /**
    * 小球运动的周期
    */
   private float mCycleTime;
   private Paint mPaint;

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

   }@Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int mWidth = 0, mHeight = 0;
      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);

   }@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);
      drawGlobule(canvas, central);// 绘制小球
   }/**
    * 绘制小球,起始位置为圆环最低点
    *
    * @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);

   }private ValueAnimator animator;
   /**
    * 旋转小球
    */
   public void startCirMotion() {Log.e("TAG", "currentAngle:" + currentAngle);
      if (currentAngle == -1) {animator = ValueAnimator.ofFloat(90f, 450f);
         animator.setDuration((long) mCycleTime).setRepeatCount(ValueAnimator.INFINITE);
         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Override
            public void onAnimationUpdate(ValueAnimator animation) {Float angle = (Float) animation.getAnimatedValue();
               currentAngle = angle * Math.PI / 180;
               invalidate();
            }});
         // animator.setInterpolator(new LinearInterpolator());// 匀速旋转
         // 自定义开始减速到0后加速到初始值的Interpolator
         LinearInterpolator lir = new LinearInterpolator();
         animator.setInterpolator(lir);
         animator.start();
      }}public void stopAnimation(){if(animator!=null){animator.end();
           currentAngle =-1;
        }}

res/values/attrs.xml :

<?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>

The end !

Android -- 小球周期旋转相关推荐

  1. android生命周期_Android活动生命周期– 7个阶段和功能

    android生命周期 Activity is one of the primary components of an Android application. In this tutorial, w ...

  2. android 生命周期_Android生命周期组件 Lifecycle 源码详解(一)

    在上篇文章: warmcheng:Android生命周期组件 Lifecycle 使用详解​zhuanlan.zhihu.com 中,我们讲了 Lifecycle 的简单使用,本篇我们来研究下它的源码 ...

  3. android上传图片被旋转,input上传照片旋转解决办法

    需求很简单:h5拍照上传照片,然后显示出来 问题在:上传之后的图片在PC,IOS端均能正常显示,Android端显示的则是被旋转90度的. 直接上代码 下面这个方法传入file对象,然后会去除掉照片中 ...

  4. Android 禁止屏幕旋转 旋转屏幕时保持Activity内容

    Android 禁止屏幕旋转 & 旋转屏幕时保持Activity内容 1.在应用中固定屏幕方向. 在AndroidManifest.xml的activity中加入:            an ...

  5. android 屏幕旋转流程,android自动屏幕旋转流程分析.doc

    android自动屏幕旋转流程分析.doc android自动屏幕旋转流程分析 在android设置(Settings)中我们可以看到显示(display)下有一个自动屏幕旋转的checkbox, 如 ...

  6. android生命周期_Android片段生命周期

    android生命周期 Today we will learn about Android Fragment Lifecycle and implement a single activity cla ...

  7. Android手机模拟器旋转快捷键

    Android手机模拟器旋转快捷键:CTRL+F11 转载于:https://blog.51cto.com/568464209/1308983

  8. Android生命周期详解

    最近在看任玉刚老师的开发艺术探索,记录一下. Android生命周期分为两部分: 一.典型情况下的生命周期. 二.异常情况下的生命周期. 一.典型情况下的生命周期 典型情况下的生命周期指在有用户参与的 ...

  9. 实验三 Android生命周期

    实验三 Android生命周期 一.实验目的 巩固使用 Eclipse 开发 Android 应用程序方法和步骤. 加深了解和体验 Activity 的生命周期中各状态的变化关系. 掌握 Androi ...

最新文章

  1. Win7/Win2008下IIS配置Asp站点启用父路径的设置方法
  2. 2线程原语:pthread_create(),pthread_self(),pthread_exit(),pthread_join(),pthread_cancel(),pthread_detach(
  3. 解决element-ui table show-summary合计行不显示问题
  4. linux中asm数据库卸载教程,删除Linux非rac环境下的ASM实例
  5. Android 服务(Service)
  6. 第九十五节,移动流体布局和响应式布局总结
  7. ASP.NET Core 反向代理部署知多少
  8. 什么叫内部银团_MOS管和IGBT管有什么区别?
  9. UVALive 3942 Trie加速dp
  10. 你真的会php,你真的会PHP吗?
  11. STC8G七彩数字时钟、GPIO设置、DS1302使用、热敏电阻测温、SM5166P和MBI5024控制数码管显示
  12. Kingbase8开发版,启动提示FATAL: XX000: max_connections should be less than orequal than 10
  13. 网线水晶头制作及标准接法教程,运维必备硬技能
  14. 在matlab上利用fft进行信号频谱分析_使用示波器进行信号频谱分析(FFT)的设置教学...
  15. 用C#编写一个图片浏览器,实现鼠标控制图片的平移缩放与图片的灰度化
  16. 华为机试:DNA序列
  17. 机器指令与微指令之间的关系
  18. 《最强大脑第九季》C#手撸傅立叶残影题目
  19. java计算机毕业设计旅游景点展示平台的设计与实现源程序+mysql+系统+lw文档+远程调试
  20. 软件算法一些学习总结

热门文章

  1. flume1.9自定义hbaseSink(实际是自定义序列化类)
  2. 解决/var/lib/docker/overlay2占用很大、容器无法启动问题
  3. ROS机器人驱动板(含原理图以及PCB)已经打板测试且正在使用
  4. STM32 NEC红外遥控器解码
  5. 34【源码】数据可视化:基于 Echarts + Python 动态实时大屏 - 视频平台
  6. 互联网+时代的企业应用集成平台
  7. python 图像识别游戏_基于Python的浏览器图像识别
  8. 【vivado学习六】 Vivado综合
  9. 【Unity2D入门教程】简单制作一个弹珠游戏之制作场景③(设置砖块,添加碰撞)
  10. 列表推导式-list comprehension