您的位置:首页 > 移动开发 > Android开发

Android自定义View圆盘滑动控件(已适配多种分辨率)

2016-04-25 20:51 477 查看
好久没写博客了,最近在写一个项目时需要一个可以调节档位的圆盘, 首先实现这个圆盘自定义View,首先在构造方法中定义画笔,重写onDraw(Canvas canvas)方法,进行绘制,首先绘制一个大圆,然后我这个大圆周围的表盘显示一共有9个档位,为了美观,每个档位里面有8个小指针,这样一个分为72份,也就是没5°画一次,由于我这个还需要有一个设定档位的按钮,所以添加档位的档位设置。

下面说一下滑动手势的处理

我们可以在oNMeasure()方法得到该控件的大小,除以2就是圆心,我们设定的大圆的半径为200,用圆心y坐标减去200就是0档位的y坐标,通过获取当前手势位置,就可以通过这三个点构建三角形,通过初中学的余弦定理可以求得滑动角度,当滑动到左半部分,角度注意要用360-当前角度。

屏幕适配看了hongyang大神Orz的适配方案,/article/1580259.html

————————–分割线————————————-

上代码

package com.example.yasin.dianretan.utils;

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.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.example.yasin.dianretan.R;

import java.util.Calendar;

/**
* Created by Yasin on 2016/4/7.
*/
public class CirclerView extends View {

private int width;
private int height;
private Paint mPaintLine;
private Paint mPaintCircle;
private Paint mPaintSec;
private Paint mPaintText,mPaintText2;
private int dw;//当前档位
public static final int NEED_INVALIDATE = 0X23;
private double cx,cy;//手势坐标
private double yxx,yxy;//圆心
private String name;
private double jd;//滑动的角度

//每隔一秒,在handler中调用一次重新绘制方法
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {

switch (msg.what){
case NEED_INVALIDATE:
invalidate();//告诉UI主线程重新绘制
handler.sendEmptyMessageDelayed(NEED_INVALIDATE,1000);
break;
default:
break;
}
}
};

public CirclerView(Context context) {
super(context);
}

public CirclerView(Context context, AttributeSet attrs) {
super(context, attrs);

/*
* 定义多个画不同东西的画笔
* */
mPaintLine = new Paint();
mPaintLine.setColor(Color.WHITE);
mPaintLine.setStrokeWidth(6);

mPaintCircle = new Paint();
mPaintCircle.setColor(context.getResources().getColor(R.color.yellow));//设置颜色
mPaintCircle.setStrokeWidth(10);//设置线宽
mPaintCircle.setAntiAlias(true);//设置是否抗锯齿
mPaintCircle.setStyle(Paint.Style.STROKE);//设置绘制风格

mPaintText = new Paint();
mPaintText.setColor(Color.WHITE);
mPaintText.setStrokeWidth(10);
mPaintText.setTextAlign(Paint.Align.CENTER);
mPaintText.setTextSize(40);

mPaintText2 = new Paint();
mPaintText2.setColor(Color.WHITE);
mPaintText2.setStrokeWidth(10);
mPaintText2.setTextAlign(Paint.Align.CENTER);
mPaintText2.setTextSize(60);

//滑针
mPaintSec = new Paint();
mPaintSec.setStrokeWidth(10);
mPaintSec.setColor(Color.YELLOW);

}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
yxx = width/2;
yxy = height/2;
setMeasuredDimension(width, height);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

int circleRadius = 200;//大圆半径
//画出大圆
canvas.drawCircle(width / 2, height / 2, circleRadius, mPaintCircle);

//依次旋转画布,画出每个刻度和对应数字
if(dw==0){
mPaintText2.setColor(Color.RED);
canvas.drawText("关",width/2,height/2+60,mPaintText2);
}else{
mPaintText2.setColor(Color.WHITE);
canvas.drawText(dw+"档",width/2,height/2+60,mPaintText2);
}

mPaintText2.setColor(Color.YELLOW);
mPaintText2.setTextSize(40);
canvas.drawText(name, width / 2, height / 2 - 50, mPaintText2);

for (int i = 0; i <= 71; i++) {//一共有72个(刻度+档位文字)
canvas.save();//保存当前画布
canvas.rotate(360 / 72 * i, width / 2, height / 2);
// canvas.rotate((float)jd, width / 2, height / 2);
if(i%8!=0) {
if(i<dw*8||i<jd/5.0f){/*如果使用的档位调节,则该档位内的都有黄色;
如果滑动的,一个刻度是5°,s所以个当前度数除以5*/
mPaintLine.setColor(Color.YELLOW);
}else{
mPaintLine.setColor(Color.WHITE);
}
canvas.drawLine(width / 2, height / 2 - circleRadius-10, width / 2, height / 2 - circleRadius - 30, mPaintLine);
}else {
//左起:文本内容,起始位置x坐标,起始位置y坐标,画笔
if(i/8<=dw){
mPaintText.setColor(Color.YELLOW);
}else{
mPaintText.setColor(Color.WHITE);
}
canvas.drawText("" + i / 8, width / 2, height / 2 - circleRadius - 20, mPaintText);
}
canvas.restore();
}

float secDegree = (float) jd;//dw/9f*360;//得到指针旋转的角度
canvas.save();
canvas.rotate(secDegree, width / 2, height / 2);
canvas.drawLine(width / 2, height / 2 - circleRadius, width / 2, height / 2 - circleRadius - 30, mPaintSec);

canvas.restore();

}

public void setDw(int dw){
this.dw = dw;
//handler.sendEmptyMessage(NEED_INVALIDATE);//向handler发送一个消息,让它开启重绘
this.jd = dw*40;
invalidate();
}
public int getDw(){
return dw;
}

public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
cx=event.getX();
cy=event.getY();

jd = getJD(cx,cy);
if(cx<=yxx) {
jd=180+(180-jd);
}
dw = (int) (jd/40);
invalidate();
return true;
}

/*
* type 1表示得到距离,2表示得到的距离的平方
* */
private double getJL(double ax,double ay,double bx,double by,int type){
if(type==1){
return Math.sqrt(((ax-bx)*(ax-bx)+(ay-by)*(ay-by)));
}else{
return (((ax-bx)*(ax-bx)+(ay-by)*(ay-by)));
}
}
//计算角度
private double getJD(double ax,double ay){
return (Math.acos(((getJL(ax,ay,yxx,yxy,2)+200*200-getJL(ax,ay,yxx,(yxy-200),2))/(2*200*getJL(ax,ay,yxx,yxy,1))))*180/Math.PI);
}

}


效果图

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: