package com.diandou.demo41_cycle;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.Rect;
import android.graphics.RectF;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by baiya on 2018/2/26.
*/
public class CycleView extends View {
/** 当前控件的宽 */
private int mWidthSize = 1000;
/** 当前控件的高 */
private int mHeightSize = 1000;
int zhouqi = 28;
private static final String TAG = "CycleView";
private Path mCyclePath;
private Paint mCyclePaint;
private TextPaint mTextPaint;
private PathMeasure mPathMeasure;
private int ox;
private int oy;
private int radius;
private float mWheelCurX;
private float mWheelCurY;
private float mAngle;
private int mCurrentProcess;
public CycleView(Context context) {
this(context, null);
}
public CycleView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
/**
* 初始化
* @param context
* @param attrs
*/
private void init(Context context, AttributeSet attrs) {
mCyclePaint = new Paint();
mCyclePaint.setColor(Color.WHITE);
mCyclePaint.setStrokeWidth(10);
mCyclePaint.setStyle(Paint.Style.STROKE);
/** 文字画笔 */
mTextPaint = new TextPaint();
mTextPaint.setColor(Color.BLACK);
mTextPaint.setStrokeWidth(2);
mTextPaint.setStyle(Paint.Style.FILL);/** 这个也有问题 */
mTextPaint.setTextSize(30);/** 文字大小, 文字的大小是按像素的 */
/**
* 设置文字的偏移量
* 文字的偏移量默认是left 就是 文本 左下角 的坐标点....
* */
mTextPaint.setTextAlign(Paint.Align.LEFT);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
// Log.d(TAG, "onMeasure" + " widthSize--" + widthSize + " heightSize--" + heightSize);
int measuredHeight, measuredWidth;
if (widthMode == MeasureSpec.EXACTLY){
measuredWidth = widthSize;
} else {
//如果能用到这种情况, 那就是不确定大小咯
measuredWidth = mHeightSize;
}
if (heightMode == MeasureSpec.EXACTLY) {
measuredHeight = heightSize;
} else {
measuredHeight = mHeightSize;
}
setMeasuredDimension(measuredWidth, measuredHeight);
mHeightSize = getMeasuredHeight();
mWidthSize = getMeasuredWidth();
ox = mWidthSize/2;
oy = mHeightSize/2;
radius = (mWidthSize -200)/2;
mCyclePath = new Path();
RectF rectF = new RectF(100, 100, mWidthSize-100, mHeightSize-100);
mCyclePath.addArc(rectF, 270, 359);
mPathMeasure = new PathMeasure(mCyclePath, false);
}
@Override
protected void onDraw(Canvas canvas) {
// 画中心圆..
// 画圆周边的小圆
// 写中间的文字
// 还有可滑动覆盖的圆
canvas.drawPath(mCyclePath, mCyclePaint);
for (int i = 0; i < zhouqi; i++) {
float[] coords = {0f, 0f};
String s = i+"";
mPathMeasure.getPosTan(i * mPathMeasure.getLength() / zhouqi, coords, null);
canvas.drawCircle(coords[0], coords[1], 30, mCyclePaint);
// canvas.drawText(i+"", coords[0]-15, coords[1]+15, mTextPaint);
Rect bounds = new Rect();
mTextPaint.getTextBounds(s, 0, s.length(), bounds);
Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
int baseline = (int) (coords[1] - fontMetrics.bottom/2 - fontMetrics.top/2);
canvas.drawText(s,coords[0] - bounds.width() / 2, baseline, mTextPaint);
}
if (mWheelCurX != 0 && mWheelCurY != 0) {
canvas.drawCircle(mWheelCurX, mWheelCurY, 100, mCyclePaint);
} else {
refershPosition();
invalidate();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
// Log.d(TAG, "x---" + x);
// Log.d(TAG, "y---" + y);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
/** 拿到x, y的值后, 计算 */
break;
case MotionEvent.ACTION_MOVE:
float cos = getCos(x, y, ox, oy);
if (x < getWidth() / 2) { // 滑动超过180度
mAngle = (float) (180 + Math.acos(cos) * 180 / Math.PI);
} else { // 没有超过180度
mAngle = (float) (180 - Math.acos(cos) * 180 / Math.PI);
}
refershSmallCyclePosition(cos);
mCurrentProcess = (int) (mAngle / 360 * 28 + 0.5);
Log.d(TAG, "mCurrentProcess---" + mCurrentProcess);
invalidate();
break;
case MotionEvent.ACTION_UP:
//当手指up的时候
//需要定位到那一点上
int angle = mCurrentProcess * 360/28;
Log.d(TAG, "y---" + y);
refershSmallCyclePosition(-Math.cos(Math.toRadians(angle)));
invalidate();
break;
case MotionEvent.ACTION_CANCEL:
int angle1 = mCurrentProcess * 360 /28;
refershSmallCyclePosition(-Math.cos(Math.toRadians(angle1)));
invalidate();
break;
}
/** 拿到点击事件后, 不再向上传递了 */
return true;
}
/**
* 更具选的position来刷新小圆的位置
*/
private void refershPosition() {
mAngle = (float) (1 / 28 * 360.0);
double cos = -Math.cos(Math.toRadians(mAngle));
refershSmallCyclePosition(cos);
}
/**
* 重置小圆点的位置
* @param cos
*/
private void refershSmallCyclePosition(double cos) {
/** 小圆点坐标 */
if (mAngle < 180) {
mWheelCurX = (float) (ox + Math.sqrt(1 - cos * cos) * radius);
} else {
mWheelCurX = (float) (ox - Math.sqrt(1 - cos * cos) * radius);
}
mWheelCurY = (int) (getMeasuredHeight() / 2 + radius * (float) cos);
}
/**
* 获取倾斜的cos的值
* @param x 手指按下点的x坐标
* @param y 手指按下点的y坐标
* @param ox 圆点x坐标
* @param oy 圆点y坐标
* @return 返回手指按下的点, 相对于圆心的度数
*/
public float getCos(float x, float y, int ox, int oy) {
float width = x - ox;
float height = y - oy;
float slope = (float) Math.sqrt(width * width + height * height);
float cos = height / slope;
return cos;
}
}
一个可跟随手指移动的view
最新推荐文章于 2024-05-11 08:30:00 发布