Android 的一個簡單的遙控器自定義控件

做一個智能風扇時 客戶有一個智能遙控器的需求往产,就寫了個比較簡單的自定義控件呵萨。代碼注釋很詳細了,就不多說了伶丐。自己看下啦悼做,有問題的問題一起交流下。

效果如下圖:

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

    //內(nèi)圓邊框的寬度
    private float innerCircleWidth = 10;

    //外圍圓的邊框的寬度
    private float outerCircleWidth = 15;

    //畫筆對象
    private Paint mPaint;

    //圓心的X坐標
    private float centerX;

    //圓心的Y坐標
    private float centerY;

    //內(nèi)圓半徑的顏色
    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;
    }


    //判斷區(qū)域
    public AREA judgeArea(float x, float y) {
        //判斷是是否在大圓內(nèi)
        if ((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY) <= outerCircleRadius * outerCircleRadius) {
            //判斷是否在小圓內(nèi)
            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;
        }
        //設(shè)置點擊之后的顏色
        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;
        }

    }

    /**
     * 關(guān)于不同區(qū)域的枚舉,逆時針方向
     */
    public enum AREA {
        //第一區(qū)域
        NUMBER_ONE,
        //第二區(qū)域
        NUMBER_TWO,
        //第三區(qū)域
        NUMBER_THREE,
        //第四區(qū)域
        NUMBER_FOUR,
        //第五區(qū)域
        NUMBER_FIVE,
        //第六區(qū)域
        NUMBER_SIX,
        //第七區(qū)域
        NUMBER_SEVEN,
        //第八區(qū)域
        NUMBER_EIGHT,
        //中心區(qū)域
        CENTER,
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末啡彬,一起剝皮案震驚了整個濱河市羹与,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌庶灿,老刑警劉巖纵搁,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異往踢,居然都是意外死亡腾誉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門峻呕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來利职,“玉大人,你說我怎么就攤上這事瘦癌≈硖埃” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵讯私,是天一觀的道長热押。 經(jīng)常有香客問我西傀,道長,這世上最難降的妖魔是什么桶癣? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任拥褂,我火速辦了婚禮,結(jié)果婚禮上牙寞,老公的妹妹穿的比我還像新娘饺鹃。我一直安慰自己,他們只是感情好间雀,可當我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布悔详。 她就那樣靜靜地躺著,像睡著了一般雷蹂。 火紅的嫁衣襯著肌膚如雪伟端。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天匪煌,我揣著相機與錄音责蝠,去河邊找鬼。 笑死萎庭,一個胖子當著我的面吹牛霜医,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播驳规,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼肴敛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吗购?” 一聲冷哼從身側(cè)響起医男,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捻勉,沒想到半個月后镀梭,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡踱启,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年报账,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片埠偿。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡透罢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冠蒋,到底是詐尸還是另有隱情羽圃,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布抖剿,位于F島的核電站朽寞,受9級特大地震影響胚吁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜愁憔,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望孽拷。 院中可真熱鬧吨掌,春花似錦、人聲如沸脓恕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炼幔。三九已至秋茫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乃秀,已是汗流浹背肛著。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留跺讯,地道東北人枢贿。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像刀脏,于是被迫代替她去往敵國和親局荚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容