Android最近在自定义view,需要做一个圆周运动;
- 方案一:首先想到的是根据圆的方程,实时递增x值进行,然后实时计算y值,代码如下:
package com.example.demo.practice.ui; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.View; import com.example.demo.practice.dashboardview.PxUtils; import com.example.demo.practice.tool.TimeAction; /** * Created by hanbo on 2018-01-23. */ public class SatelliteView extends View { private int mWidth; private int mHeight; private Paint p; private float degree; private Context context; private TimeAction timeAction; //运动圆的轨迹 private int x; private int y; //圆心坐标 private int x1; private int y1; //最大半径 private int r1; //r平方 private int r_pow; //上下半圆 private boolean flag; private int left; private int right; private int speed=4; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (flag) { if (x + speed >= right) { flag = false; } x = x + speed; y = (int) (y1 - Math.sqrt(r_pow - (x - x1) * (x - x1))); } else { if (x - speed <= left) { flag = true; } x = x - speed; y = (int) (y1 + Math.sqrt(r_pow - (x - x1) * (x - x1))); } invalidate(); } }; public SatelliteView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; p = new Paint(); p.setAntiAlias(true); degree = 0; timeAction = new TimeAction(handler, 100); timeAction.start(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { mWidth = widthSize; } else { mWidth = PxUtils.dpToPx(200, context); } if (heightMode == MeasureSpec.EXACTLY) { mHeight = heightSize; } else { mHeight = PxUtils.dpToPx(200, context); } setMeasuredDimension(mWidth, mHeight); r1 = mWidth; if (mHeight < mWidth) { r1 = mHeight; } x = mWidth / 2; x1 = x; y1 = mHeight / 2; y = y1 - r1 / 4; left = x1 - r1 / 4; right = x1 + r1 / 4; r_pow = r1 * r1 / 16; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); p.setColor(Color.parseColor("#00a1e9")); p.setStrokeWidth(5); p.setStyle(Paint.Style.STROKE); canvas.drawCircle(x1, y1, r1 / 4, p); p.setColor(Color.parseColor("#194464")); canvas.drawCircle(x1, y1, r1 * 3 / 8, p); p.setStyle(Paint.Style.FILL); p.setColor(Color.parseColor("#00a1e9")); canvas.drawCircle(x, y, 10, p); } @Override protected void onDetachedFromWindow() { timeAction.stop(); super.onDetachedFromWindow(); } }效果图如下:
这种方式的缺点很明显,就是速度不均匀,y与x变化率不同。
方案二:以角度计算xy的值,这样的速度就比较均匀了,代码如下:
package com.example.demo.practice.ui; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.View; import com.example.demo.practice.dashboardview.PxUtils; import com.example.demo.practice.tool.TimeAction; /** * Created by hanbo on 2018-01-23. */ public class SatelliteView extends View { private static String TAG = "卫星图"; private int mWidth; private int mHeight; private Paint p; private Context context; //定时器 private TimeAction timeAction; //运动圆的轨迹 private int x; private int y; //圆心坐标 private int x1; private int y1; //最大半径 private int r1; //r平方 private int r_run; //速度 private double speed = 0.04; private double degree; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); degree=speed+degree; if (degree >= 360) { degree = degree - 360; } y = (int) (y1 - r_run * Math.cos(degree)); x = (int) (x1 + r_run * Math.sin(degree)); invalidate(); } }; public SatelliteView(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; p = new Paint(); p.setAntiAlias(true); degree = 0; timeAction = new TimeAction(handler, 100); timeAction.start(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { mWidth = widthSize; } else { mWidth = PxUtils.dpToPx(200, context); } if (heightMode == MeasureSpec.EXACTLY) { mHeight = heightSize; } else { mHeight = PxUtils.dpToPx(200, context); } setMeasuredDimension(mWidth, mHeight); r1 = mWidth; if (mHeight < mWidth) { r1 = mHeight; } r_run = r1 / 4; x = mWidth / 2; x1 = x; y1 = mHeight / 2; y = y1 - r_run; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); p.setColor(Color.parseColor("#00a1e9")); p.setStrokeWidth(5); p.setStyle(Paint.Style.STROKE); canvas.drawCircle(x1, y1, r1 / 4, p); p.setColor(Color.parseColor("#194464")); canvas.drawCircle(x1, y1, r1 * 3 / 8, p); p.setStyle(Paint.Style.FILL); p.setColor(Color.parseColor("#00a1e9")); canvas.drawCircle(x, y, 10, p); } @Override protected void onDetachedFromWindow() { timeAction.stop(); super.onDetachedFromWindow(); } }效果图如下: