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

原创 2016年04月25日 20:51:50

好久没写博客了,最近在写一个项目时需要一个可以调节档位的圆盘, 首先实现这个圆盘自定义View,首先在构造方法中定义画笔,重写onDraw(Canvas canvas)方法,进行绘制,首先绘制一个大圆,然后我这个大圆周围的表盘显示一共有9个档位,为了美观,每个档位里面有8个小指针,这样一个分为72份,也就是没5°画一次,由于我这个还需要有一个设定档位的按钮,所以添加档位的档位设置。
下面说一下滑动手势的处理
我们可以在oNMeasure()方法得到该控件的大小,除以2就是圆心,我们设定的大圆的半径为200,用圆心y坐标减去200就是0档位的y坐标,通过获取当前手势位置,就可以通过这三个点构建三角形,通过初中学的余弦定理可以求得滑动角度,当滑动到左半部分,角度注意要用360-当前角度。
屏幕适配看了hongyang大神Orz的适配方案,http://blog.csdn.net/lmj623565791/article/details/45460089

————————–分割线————————————-
上代码

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

}

效果图
这里写图片描述

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Android基础

Android基础 View的绘制流程;自定义View如何考虑机型适配;自定义View的事件分发机制;View和ViewGroup分别有哪些事件分发相关的回调方法;自定义Vi...

android自定义View(2):实现百分比自适应布局

android界面适配的难是历史原因,我们只能想办法解决。github上面已有一些布局自适应的解决方案,今天我分享的是自定义控件:RelativieLayout自适应百分比宽高。实现的原理其实很简单,...

Android圆盘刻度,类似体重测试仪,效果不错哦

拒绝懒惰,支持原创,我是hailong,大家可以一起交流,我的QQ:623144766

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Android SurfaceView实战 打造抽奖转盘

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41722441 ,本文出自:【张鸿洋的博客】1、概述今天给大家带来SurfaceV...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Android自定义控件——仿优酷圆盘菜单

最近学习的时候,看见一份资料上教怎么写自定义控件,上面的示例用的是优酷早期版本的客户端,该客户端的菜单就是一个自定义的组件(现在的版本就不清楚有没有了,没下载过了),好吧,废话不多说,先上优酷的原型图...

Android开发学习笔记:TextView的属性详解

博客源址:Android开发学习笔记:TextView的属性详解 博客时间:2011-07-30 12:34:22 android:autoLink :设置是否当文本为URL链接/...

RotateAnimation 实现表盘指针转动

RotateAnimation 实现表盘指针转动 最近在做车助手这个项目,遇到这样的一个功能需求:获取车子启动的实时数据让指针转动: 我这里做了一个Demo:demo的原理在于使用onTouchE...

Android自定义控件:图片比例适配,解决图片白边(详解View中onMeasure方法)

当App中涉及到布局需要展示大量图片时,你就应该考虑到“图片比例适配“的问题。当图片的宽高规格不同时,你设置展示的ImageView是否可以完好地展示,填充满?也就是说ImagView的比例和图片的比...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android自定义View圆盘滑动控件(已适配多种分辨率)
举报原因:
原因补充:

(最多只允许输入30个字)