Android 的一个简单的遥控器自定义控件

做一个智能风扇时 客户有一个智能遥控器的需求,就写了个比较简单的自定义控件。代码注释很详细了,就不多说了。自己看下啦,有问题的问题一起交流下。

效果如下图:

遥控器截图.png
/**
 * Created by zxd on 2016/6/27.
 */
public class DiskMenuViewEight extends View {

    //内圆边框的宽度
    private float innerCircleWidth = 10;

    //外围圆的边框的宽度
    private float outerCircleWidth = 15;

    //画笔对象
    private Paint mPaint;

    //圆心的X坐标
    private float centerX;

    //圆心的Y坐标
    private float centerY;

    //内圆半径的颜色
    private int outerCircleColor = 0xFFD8D9D9;

    //外围半径的颜色 、点击的颜色
    private int innerCircleColor = 0xFFF1F1F1;

    //37°正弦值
    private float mSin45 = (float) Math.sin(45 * Math.PI / 180);

    //37°的余弦值

    private float mCos45 = (float) Math.cos(45 * Math.PI / 180);


    private float outerCircleRadius, innerCircleRadius;


    private AREA mArea;

    public DiskMenuViewEight(Context context) {
        super(context);
        init();
    }

    //长度
    int mWidth;
    //高度
    int mHeight;

    public void setWidthAndHeight(int w, int h) {
        this.mWidth = w;
        this.mHeight = h;

    }

    public DiskMenuViewEight(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int w = mWidth;
        int h = mHeight;

        centerX = w / 2;

        centerY = h / 2;

        outerCircleRadius = centerX - outerCircleWidth;

        innerCircleRadius = centerX / 3;

    }

    private void init() {
        mPaint = new Paint();
    }

    //定义接口
    public interface ChangeStateListener {
        void onChangeState(AREA area);
    }

    ChangeStateListener mChangeStateListener = null;

    public void setChangeStateListener(ChangeStateListener changeStateListener) {
        mChangeStateListener = changeStateListener;
    }

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

        mPaint.setAntiAlias(true);
        //画圆
        drawCircle(canvas);
        //花直线
        drawLine(canvas);
        //画背景选择器
        drawOnclikColor(canvas, mArea);
        //画文字
        drawText(canvas);
        //画图
        drawImageView1(canvas);
        drawImageView2(canvas);
        //画灯泡
        drawImageViewCenter(canvas);
    }


    //画图
    private void drawImageView1(Canvas canvas) {
        Paint imgPaint = new Paint();
        imgPaint.setAntiAlias(true);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.reversal);

        Matrix matrix = new Matrix();
        matrix.postScale(0.3f, 0.3f);
        Bitmap dstbmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, true);

        RectF mRectF = new RectF((float) (centerX - (mSin45 * outerCircleRadius) / 3 - UiUtil.Dp2Px(20)), (float) (centerY + (0.55f * outerCircleRadius) - UiUtil.Dp2Px(10)),
                (float) ((centerX - (mSin45 * outerCircleRadius) / 3) + UiUtil.Dp2Px(20)), (float) (centerY + (0.55f * outerCircleRadius) + UiUtil.Dp2Px(30)));
        canvas.drawBitmap(dstbmp, null, mRectF, imgPaint);
    }

    //画图
    private void drawImageView2(Canvas canvas) {
        Paint imgPaint = new Paint();
        imgPaint.setAntiAlias(true);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.wind_speed);

        Matrix matrix = new Matrix();
        matrix.postScale(0.3f, 0.3f);
        Bitmap dstbmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, true);

        RectF mRectF = new RectF((float) (centerX + (mSin45 * outerCircleRadius) / 3 - UiUtil.Dp2Px(20)), (float) (centerY + (0.55f * outerCircleRadius) - UiUtil.Dp2Px(10)),
                (float) ((centerX + (mSin45 * outerCircleRadius) / 3) + UiUtil.Dp2Px(20)), (float) (centerY + (0.55f * outerCircleRadius) + UiUtil.Dp2Px(30)));
        canvas.drawBitmap(dstbmp, null, mRectF, imgPaint);
    }

    //画图
    private void drawImageViewCenter(Canvas canvas) {
        Paint imgPaint = new Paint();
        imgPaint.setAntiAlias(true);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.off_light);

        Matrix matrix = new Matrix();
        matrix.postScale(0.4f, 0.4f);
        Bitmap dstbmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), matrix, true);

        RectF mRectF = new RectF((float) (centerX - UiUtil.Dp2Px(30)), (float) (centerY - UiUtil.Dp2Px(30)),
                (float) (centerX + UiUtil.Dp2Px(30)), (float) (centerY + UiUtil.Dp2Px(30)));
        canvas.drawBitmap(dstbmp, null, mRectF, imgPaint);
    }

    //写文字
    private void drawText(Canvas canvas) {
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setTextSize(100);
        paint.setColor(innerCircleColor);
        paint.setTextAlign(Paint.Align.CENTER);


        //写1
        canvas.drawText("1", centerX - mSin45 * (outerCircleRadius / 2) - (outerCircleRadius - innerCircleRadius) * 2 / 5,
                centerY + mSin45 * (outerCircleRadius / 2) - (outerCircleRadius - innerCircleRadius) / 20, paint);

        //写2
        canvas.drawText("2", centerX - mSin45 * (outerCircleRadius / 2) - (outerCircleRadius - innerCircleRadius) * 2 / 5,
                centerY - mCos45 * (outerCircleRadius / 4), paint);
        //写3
        canvas.drawText("3", centerX - (mSin45 * outerCircleRadius) / 3, centerY - (0.55f * outerCircleRadius), paint);

        //写4
        canvas.drawText("4", centerX + mSin45 * (outerCircleRadius / 3),
                centerY - (0.55f * outerCircleRadius), paint);
        //写5
        canvas.drawText("5", centerX + mSin45 * (outerCircleRadius / 2) + (outerCircleRadius - innerCircleRadius) * 2 / 5,
                centerY - mCos45 * (outerCircleRadius / 4), paint);
        //写6
        canvas.drawText("6", centerX + mSin45 * (outerCircleRadius / 2) + (outerCircleRadius - innerCircleRadius) * 2 / 5,
                centerY + mSin45 * (outerCircleRadius / 2) - (outerCircleRadius - innerCircleRadius) / 20, paint);

    }

    //画圆
    private void drawCircle(Canvas canvas) {
        mPaint.setColor(Color.WHITE);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(centerX, centerY, outerCircleRadius, mPaint);

        mPaint.setColor(outerCircleColor);
        mPaint.setStrokeWidth(outerCircleWidth);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(centerX, centerY, outerCircleRadius, mPaint);

        mPaint.setColor(outerCircleColor);
        mPaint.setStrokeWidth(10);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(centerX, centerY, innerCircleRadius, mPaint);

        mPaint.setColor(Color.WHITE);
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(centerX, centerY, innerCircleRadius, mPaint);


    }

    //画直线
    private void drawLine(Canvas canvas) {
        mPaint.setColor(outerCircleColor);
        mPaint.setStrokeWidth(5);
        //第一条
        canvas.drawLine(centerX, centerY - innerCircleRadius, centerX, centerY - outerCircleRadius, mPaint);
        //第二条
        canvas.drawLine(centerX - (mSin45 * outerCircleRadius), centerY - (mSin45 * outerCircleRadius),
                centerX - (mSin45 * innerCircleRadius), centerY - (mSin45 * innerCircleRadius), mPaint);
        //第三条
        canvas.drawLine(centerX - innerCircleRadius, centerY, centerX - outerCircleRadius, centerY, mPaint);
        //第四条
        canvas.drawLine(centerX - (mSin45 * outerCircleRadius), centerY + (mSin45 * outerCircleRadius),
                centerX - (mSin45 * innerCircleRadius), centerY + (mSin45 * innerCircleRadius), mPaint);
        //第五条
        canvas.drawLine(centerX - (mSin45 * outerCircleRadius), centerY + (mSin45 * outerCircleRadius),
                centerX - (mSin45 * innerCircleRadius), centerY + (mSin45 * innerCircleRadius), mPaint);
        //第六条
        canvas.drawLine(centerX, centerY + innerCircleRadius, centerX, centerY + outerCircleRadius, mPaint);
        //第七条
        canvas.drawLine(centerX + (mSin45 * outerCircleRadius), centerY + (mSin45 * outerCircleRadius),
                centerX + (mSin45 * innerCircleRadius), centerY + (mSin45 * innerCircleRadius), mPaint);
        //第八条
        canvas.drawLine(centerX + innerCircleRadius, centerY, centerX + outerCircleRadius, centerY, mPaint);
        //第九条
        canvas.drawLine(centerX + (mSin45 * outerCircleRadius), centerY - (mSin45 * outerCircleRadius),
                centerX + (mSin45 * innerCircleRadius), centerY - (mSin45 * innerCircleRadius), mPaint);
    }


    /**
     * 清空画布
     *
     * @param canvas
     */
    private void clearCanvas(Canvas canvas) {
        canvas.drawColor(Color.WHITE);
    }

    //按下时的X,Y坐标
    float mDownX, mDownY;
    //松开时的X,Y坐标
    float mUpX, mUpY;

    //触摸事件 即点击事件的处理


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownX = event.getX();
                mDownY = event.getY();
                Log.i("custom", "mDown==" + mDownX);
                Log.i("custom", "mDown==" + judgeArea(mDownX, mDownY));
                mArea = judgeArea(mDownX, mDownY);
                invalidate();
                mChangeStateListener.onChangeState(mArea);
                break;
            case MotionEvent.ACTION_UP:
//                clearCanvas(mCanvas);
                mArea = null;
                invalidate();
                break;
            default:
                break;
        }

        return true;
    }


    //判断区域
    public AREA judgeArea(float x, float y) {
        //判断是是否在大圆内
        if ((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY) <= outerCircleRadius * outerCircleRadius) {
            //判断是否在小圆内
            if ((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY) > innerCircleRadius * innerCircleRadius) {
                x = x - centerX;
                y = y - centerY;
                float tan = y / x;
                if (tan > Math.tan(45 * Math.PI / 180) && tan < Integer.MAX_VALUE && x < 0 && y < 0) {
                    return AREA.NUMBER_ONE;
                } else if (tan > 0 && tan < Math.tan(45 * Math.PI / 180) && x < 0 && y < 0) {
                    return AREA.NUMBER_TWO;
                } else if (tan < 0 && tan > -Math.tan(45 * Math.PI / 180) && x < 0 && y > 0) {
                    return AREA.NUMBER_THREE;
                } else if (tan < -Math.tan(45 * Math.PI / 180) && tan > Integer.MIN_VALUE && x < 0 && y > 0) {
                    return AREA.NUMBER_FOUR;
                } else if (tan > Math.tan(45 * Math.PI / 180) && tan < Integer.MAX_VALUE && x > 0 && y > 0) {
                    return AREA.NUMBER_FIVE;
                } else if (tan > 0 && tan < Math.tan(45 * Math.PI / 180) && x > 0 && y > 0) {
                    return AREA.NUMBER_SIX;
                } else if (tan > -Math.tan(45 * Math.PI / 180) && tan < 0 && x > 0 && y < 0) {
                    return AREA.NUMBER_SEVEN;
                } else if (tan > Integer.MIN_VALUE && tan < -Math.tan(45 * Math.PI / 180) && x > 0 && y < 0) {
                    return AREA.NUMBER_EIGHT;
                }
            } else {
                return AREA.CENTER;
            }
        } else {
            return null;
        }
        return null;
    }


    /**
     * 点击的时候绘制深色的扇形
     *
     * @param canvas
     * @param area
     */
    private void drawOnclikColor(Canvas canvas, AREA area) {
        //先诀条件
        if (area == null) {
            return;
        }
        //设置点击之后的颜色
        mPaint.setColor(outerCircleColor);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeWidth(outerCircleRadius - innerCircleRadius);

        switch (area) {
            case NUMBER_ONE:
                canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
                        centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
                        + (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 225, 45, false, mPaint);
                break;
            case NUMBER_TWO:
                canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
                        centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
                        + (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 180, 45, false, mPaint);
                break;
            case NUMBER_THREE:
                canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
                        centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
                        + (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 135, 45, false, mPaint);
                break;
            case NUMBER_FOUR:
                canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
                        centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
                        + (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 90, 45, false, mPaint);
                break;
            case NUMBER_FIVE:
                canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
                        centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
                        + (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 45, 45, false, mPaint);
                break;
            case NUMBER_SIX:
                canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
                        centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
                        + (outerCircleRadius - innerCircleRadius) + innerCircleWidth), 0, 45, false, mPaint);
                break;
            case NUMBER_SEVEN:
                canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
                        centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
                        + (outerCircleRadius - innerCircleRadius) + innerCircleWidth), -45, 45, false, mPaint);
                break;
            case NUMBER_EIGHT:
                canvas.drawArc(new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
                        centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
                        + (outerCircleRadius - innerCircleRadius) + innerCircleWidth), -90, 45, false, mPaint);
                break;
            case CENTER:
                mPaint.setStrokeWidth(0);
                mPaint.setStyle(Paint.Style.FILL);
                canvas.drawCircle(centerX, centerY, innerCircleRadius, mPaint);
                break;
            default:
                break;
        }

    }

    /**
     * 关于不同区域的枚举,逆时针方向
     */
    public enum AREA {
        //第一区域
        NUMBER_ONE,
        //第二区域
        NUMBER_TWO,
        //第三区域
        NUMBER_THREE,
        //第四区域
        NUMBER_FOUR,
        //第五区域
        NUMBER_FIVE,
        //第六区域
        NUMBER_SIX,
        //第七区域
        NUMBER_SEVEN,
        //第八区域
        NUMBER_EIGHT,
        //中心区域
        CENTER,
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容