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 屏幕适配方案

转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/45460089; 本文出自:【张鸿洋的博客】 1、概述大家在Andr...

Android 自定义控件之圆形扩散View(DiffuseView)

> 转载请标明出处: [http://blog.csdn.net/airsaid/article/details/52683193](http://blog.csdn.net/airsaid/arti...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

关于自定义view的适配问题

自定义view的时候往往,有一些适配不同的屏幕的手机,     android:layout_centerInParent="true">              ...
  • xyg165
  • xyg165
  • 2013-01-20 23:15
  • 1911

自定义View之ImageView做屏幕适配

自定义ImageView

开源,原创,实用Android 屏幕适配方案分享

(说来惭愧,这段时间忙项目,有时间也拿来调侃人生,好久没有写过技术文章了) 真正可用,并且简单易行,可以在多个屏幕大小和屏幕密度上有良好表现的Android 屏幕适配方案。   已经用在一款成...
  • zmobs
  • zmobs
  • 2015-04-08 10:28
  • 11802

Android多屏幕适配学习笔记

我所在公司的产品以硬件为主,软件跟着特定的硬件平台走,所以,虽然从事着Android开发,却从来没有处理过多屏幕适配的问题。意识到这个可能成为自己的一个短板,所以在缺乏实践的情况下,先准备点理论知识,...

Android 画三角形shape

android自定义圆环控件 滑动选择百分比

之前做了一个类微信的聊天应用,
  • nlgshw
  • nlgshw
  • 2014-11-21 14:19
  • 1536

Android 打造形形色色的进度条 实现可以如此简单

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43371299 ,本文出自:【张鸿洋的博客】1、概述 最近需要用进度条,秉着不重复...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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