关闭

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

标签: 自定义控件及其屏幕适
1669人阅读 评论(0) 收藏 举报
分类:

好久没写博客了,最近在写一个项目时需要一个可以调节档位的圆盘, 首先实现这个圆盘自定义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);
    }

}

效果图
这里写图片描述

0
0
查看评论

[Android自定义控件]双圆圈内外旋转菜单

双圆圈菜单是之前做的一个项目的需求,写完以后boss决定不用了,提取以后把它贴出来,第一次发技术博客,希望各位前辈多多指教。 需求就是 * 外圈放置菜单选项,内圈为圆形大图; * 当内圈小白点对准外圈选项时,内圈切换对应的选项图案; * 移动内圈时,内圈图案随转动角度旋转; *...
  • u014204844
  • u014204844
  • 2016-03-13 00:10
  • 1655

android 一分钟掌握圆形布局原理--圆形菜单控件 so easy

前言:首先看看我们的两个demo效果,一个类似支付宝网格属性图,一个类似建行圆形菜单。 这两个效果,第一个涉及自定义view,第二个涉及ViewGroup。如果对于自定义view有一点了解实现起来都不难,但是很多时候自己对于自定义view是一种恐惧,因为写的很少。比如今天的圆形布局的view,...
  • lmj121212
  • lmj121212
  • 2016-11-19 11:49
  • 2608

Android自定义圆形菜单

炫酷,拉风的UI效果,对于我们每位开发人员来说都是相当具有吸引力的。上图是雏形,可以扩展成为表盘,转盘,圆形菜单,下图就是扩展的圆形菜单。由于录制工具很不清晰,UI特效效果真心不错。如有感兴趣的,请往后面看。当然灵感来源于上图。标题是自定义的圆形菜单,我主要讲解圆形菜单的开发流程,如有对上图感兴趣的...
  • u012551350
  • u012551350
  • 2016-03-11 10:56
  • 2092

Android 自定义View实现圆形环绕效果

之前项目中需要实现一个四周环绕中心圆形头像的效果,感觉还是自定义比较方便,于是就自己封装了一个控件去实现。先贴张图显示最终效果。
  • ZuoZuoShengHen
  • ZuoZuoShengHen
  • 2017-07-25 17:23
  • 417

android 自定义view实现类似圆盘抽奖的效果

android 自定义view实现类似圆盘抽奖的效果
  • coderinchina
  • coderinchina
  • 2016-11-02 17:23
  • 1158

Android基础

Android基础 View的绘制流程;自定义View如何考虑机型适配;自定义View的事件分发机制;View和ViewGroup分别有哪些事件分发相关的回调方法;自定义View如何提供获取View属性的接口; Art和Dalvik对比;虚拟机原理,如何自己设计一个虚...
  • w15195868673
  • w15195868673
  • 2017-03-15 19:46
  • 192

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

android界面适配的难是历史原因,我们只能想办法解决。github上面已有一些布局自适应的解决方案,今天我分享的是自定义控件:RelativieLayout自适应百分比宽高。实现的原理其实很简单,就是自定义两个属性:宽和高的百分比,让自定义的view继承 RelativeLayout。取出这两个...
  • dzsw0117
  • dzsw0117
  • 2016-05-09 12:03
  • 1716

自定义View中的适配

自定义View中的适配 自定义view中,使用的单位都是px,那如何去适配屏幕呢?获取屏幕宽度px等数据,然后根据这些去设置 view的宽度px,字体的大小 我们可以把想要显示的大小用dp、sp作为单位,然后在代码中通过工具类转换为px package com.zhy.utils;import ...
  • qianjfsjf
  • qianjfsjf
  • 2016-04-20 21:53
  • 276

关于自定义view的适配问题

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

Android--自定义View滑动的六种方法

概述由于移动平台屏幕尺寸大小的限制,为了给用户呈现更好的页面内容,我们需要通过滑动来实现一些页面内容的显示和隐藏操作。自定义View的方法 View.layout()方法 改变view的布局参数LayoutParams View.offsetLeftAndRight()和View.offsetTop...
  • hpk1994
  • hpk1994
  • 2016-04-21 22:45
  • 667
    个人资料
    • 访问:75176次
    • 积分:1327
    • 等级:
    • 排名:千里之外
    • 原创:59篇
    • 转载:1篇
    • 译文:0篇
    • 评论:31条