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();
}
}
效果图如下: