美文网首页
android 遥控器布局

android 遥控器布局

作者: proud2008 | 来源:发表于2020-03-29 15:03 被阅读0次
效果如上

文本的内容 区域数 起始角度(x轴正向0度 逆时针)可自定

package com.hrg.gys.rebot.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.hrg.hefei.R;
import com.xin.common.utils.LogUtils;

/**
 * https://www.jianshu.com/p/207ea78f1634
 * Created by zxd on 2016/6/27.
 */
public class DiskMenuView extends View {


    ChangeStateListener mChangeStateListener = null;
    //按下时的X,Y坐标
    private int mArea = -1;
    //内圆边框的宽度
    private float innerCircleWidth = 10;
    //外围圆的边框的宽度
    private float outerCircleWidth = 15;
    //画笔对象
    private Paint paintLine;
    private Paint paintText;
    private Paint paintClick;
    int itemAngle;/*每个格的角度*/
    /*共分多少格*/
    private int cellNum = 4;
    /*开始的角度*/
    private int startAngle = 0;
    /*显示在中间的文本*/
    private String[] strArr;
    //圆心的X坐标
    private float centerX;
    //圆心的Y坐标
    private float centerY;
    //内圆半径的颜色
    private int outerCircleColor = 0xFFD8D9D9;
    //外围半径的颜色 、点击的颜色
    private int innerCircleColor = 0xFF000000;
    private float outerCircleRadius, innerCircleRadius;

    public DiskMenuView(Context context) {
        this(context, null);
    }

    public DiskMenuView(Context context, AttributeSet attributeSet) {
        this(context, attributeSet, 0);
    }

    public DiskMenuView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttr(context, attrs);
        init();
    }

    private void initAttr(Context context, AttributeSet attrs) {
        TypedArray t = context.obtainStyledAttributes(attrs, R.styleable.DiskMenuView);
        cellNum = t.getInt(R.styleable.DiskMenuView_DiskMenuView_CellNum, 4);
        startAngle = t.getInt(R.styleable.DiskMenuView_DiskMenuView_StartAngle, 0);
        String _strArr = t.getString(R.styleable.DiskMenuView_DiskMenuView_StrArr);
        if (_strArr != null && _strArr.split(",").length >= cellNum) {
            strArr = _strArr.split(",");
        }
        t.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int w = getMeasuredWidth();
        int h = getMeasuredHeight();
        centerX = w / 2;
        centerY = h / 2;
        outerCircleRadius = Math.min(centerX, centerY) - outerCircleWidth;
        innerCircleRadius = outerCircleRadius / 3;

    }

    private void init() {
        paintLine = new Paint();
        itemAngle = 360 / cellNum;
        paintText = new Paint();
        paintText.setAntiAlias(true);
        paintText.setTextSize(30);
        paintText.setStrokeWidth(20);
        paintText.setColor(innerCircleColor);
        paintText.setTextAlign(Paint.Align.CENTER);
        paintClick = new Paint();
    }

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

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

        paintLine.setAntiAlias(true);
        //画圆
        drawCircle(canvas);
        //花直线
        drawLine(canvas);
        //画背景选择器
        drawOnclikColor(canvas);
        //画文字
        drawText(canvas);
    }

    //写文字
    private void drawText(Canvas canvas) {

        Paint.FontMetricsInt fontMetrics = paintText.getFontMetricsInt();
        float centerRadius = (outerCircleRadius + innerCircleRadius) / 2;
//        canvas.drawPoints(new float[]{centerX,centerY},paintText);
        for (int i = 0; i < cellNum; i++) {
//            paintText.setColor(i == 0 ? Color.RED : Color.GREEN);
            int _itemStartAngle = itemAngle * i + startAngle;
            int _itemEndAngle = _itemStartAngle + itemAngle;
            int _averageAngle = (_itemEndAngle + _itemStartAngle) / 2;
            float textX = (float) (centerX + Math.cos(_averageAngle * Math.PI / 180) * centerRadius);
            float texty = (float) (centerY + Math.sin(_averageAngle * Math.PI / 180) * centerRadius);
//            canvas.drawPoints(new float[]{textX,texty},paintText);
            /*基线的位置*/
            int baseline = (int) (texty - (fontMetrics.bottom + fontMetrics.top) / 2);
            String text = strArr != null ? strArr[i + 1] : String.valueOf(i + 1);
            canvas.drawText(text, textX, baseline, paintText);
        }
        int baseline = (int) (centerY - (fontMetrics.bottom + fontMetrics.top) / 2);
        String text = strArr != null ? strArr[0] : String.valueOf(0);
        canvas.drawText(text, centerX, baseline, paintText);

    }


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

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

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

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


    }

    //画直线
    private void drawLine(Canvas canvas) {
        paintLine.setColor(outerCircleColor);
        paintLine.setStrokeWidth(5);

        for (int i = 0; i < cellNum; i++) {
//            paintLine.setColor(i == 0 ? Color.RED : Color.GREEN);
            double v = (itemAngle * i + startAngle) * Math.PI / 180;
            double sinItem = Math.sin(v);
            double cosItem = Math.cos(v);
            canvas.drawLine((int) (centerX + (cosItem * outerCircleRadius)),
                    (int) (centerY + (sinItem * outerCircleRadius)),
                    (int) (centerX + (cosItem * innerCircleRadius)),
                    (int) (centerY + (sinItem * innerCircleRadius)),
                    paintLine);
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mArea = judgeArea(event.getX(), event.getY());
                if (mArea >= 0) {
                    invalidate();
                    log("mChangeStateListener->" + mArea);
                    if (mChangeStateListener != null && mArea >= 0) {
                        mChangeStateListener.onChangeState(mArea);
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (mArea >= 0) {
                    mArea = -1;
                    invalidate();
                }
                break;
            default:
                break;
        }

        return true;
    }

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

    //判断区域
    public int 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 = centerY - y;
                float tan = y / x;
                double angle = 0;
                double mathAngle = Math.atan(Math.abs(tan)) * 180 / Math.PI;
                if (x >= 0 && y >= 0) { //一象限
                    angle = mathAngle;
                } else if (x <= 0 && y >= 0) { //二角限
                    angle = 180 - mathAngle;
                } else if (x <= 0 && y <= 0) {//三
                    angle = 180 + mathAngle;
                } else if (x >= 0 && y <= 0) { //四
                    angle = 360 - mathAngle;
                }
                log("judgeArea->" + angle);
                int area = (int) Math.ceil((360 - (angle + startAngle)) / itemAngle);
                if (area > cellNum) {
                    area = area - cellNum;
                }
                return area;
            } else {
                return 0;
            }
        } else {
            return -1;
        }
    }

    private void log(String t) {
        LogUtils.log("DiskMenuView", t);
    }

    /**
     * 点击的时候绘制深色的扇形
     *
     * @param canvas
     */
    private void drawOnclikColor(Canvas canvas) {
        if (mArea == -1) { //未选中
            return;
        } else if (mArea == 0) { //中心区域
            paintClick.setStrokeWidth(0);
            paintClick.setStyle(Paint.Style.FILL);
            canvas.drawCircle(centerX, centerY, innerCircleRadius, paintClick);
            return;
        } else {
            paintClick.setColor(outerCircleColor);
            paintClick.setStyle(Paint.Style.STROKE);
            paintClick.setStrokeWidth(outerCircleRadius - innerCircleRadius);

            RectF oval = new RectF(centerX - (outerCircleRadius - innerCircleRadius) - innerCircleWidth, centerY - (outerCircleRadius - innerCircleRadius) - innerCircleWidth,
                    centerX + (outerCircleRadius - innerCircleRadius) + innerCircleWidth, centerY
                    + (outerCircleRadius - innerCircleRadius) + innerCircleWidth);

            canvas.drawArc(oval, (mArea - 1) * itemAngle + startAngle, itemAngle, false, paintClick);
        }

    }


    //定义接口
    public interface ChangeStateListener {
        /**
         * @param area 0 中心点 1是 1号位置 2号位置
         */
        void onChangeState(int area);
    }
}
//attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
 
   <declare-styleable name="DiskMenuView">
        <attr name="DiskMenuView_CellNum" format="integer" />
        <attr name="DiskMenuView_StartAngle" format="integer" />
        <attr name="DiskMenuView_StrArr" format="reference|string" />
    </declare-styleable>
</resources>
//layout.xml
 <com.hrg.gys.rebot.view.DiskMenuView
        android:id="@+id/dmve2"
        android:layout_width="match_parent"
        app:DiskMenuView_CellNum="4"
        app:DiskMenuView_StartAngle="-135"
        app:DiskMenuView_StrArr="暂停,前,右,后,左"
        android:layout_height="match_parent"
        android:layout_margin="@dimen/view_size_20"/>

相关文章

网友评论

      本文标题:android 遥控器布局

      本文链接:https://www.haomeiwen.com/subject/dzlhjhtx.html