Android自定义View实现遥控器按钮

2022-08-17 11:45:51

本文实例为大家分享了Android自定义View实现遥控器按钮的具体代码,供大家参考,具体内容如下

效果图:

原理:

    onSizeChanged拿到控件宽高,进行path和region的计算(此处,path和region的坐标值都是以viewWidth/2,viewHeight/2为坐标原点进行计算的)画布平移,绘制5个path点击事件,判断是否处于相应的region区域内,进行控件的重绘点击事件motionEvent的原始坐标(getX和getY),是以viewParent的左上角为坐标原点的,需要经过matrix转换成以控件中心点为原点的坐标体系。

    Region区域,paint的style设置为stroke模式,遍历绘制

    mPaint.setColor(Color.RED);
    RegionIterator iterator = new RegionIterator(topRegion);
     Rect r = new Rect();
     while (iterator.next(r)) {
          canvas.drawRect(r, mPaint);
     }

    源码:

    public class RemoteControlMenu extends View {
    
        private int mWidth;
        private int mHeight;
    
        private RectF bigRectF;
        private int bigRadius;
        private RectF smallRectF;
        private int smallRadius;
        private int padding = 20;
        private int sweepAngel = 80;
        private int offsetAngel;
    
        @TouchArea
        private int mTouchArea = TouchArea.INVALID;
    
        private Paint mPaint;
        private Region topRegion, bottomRegion, leftRegion, rightRegion, centerRegion, globalRegion;
        private Path topPath, bottomPath, leftPath, rightPath, centerPath, selectedPath;
    
        Matrix mMapMatrix;
    
        private int unselectedColor = 0xff4c5165;
        private int selectedColor = 0xffdd9181;
    
        private boolean isSelected = false;
    
    
        public RemoteControlMenu(Context context) {
            this(context, null);
        }
    
        public RemoteControlMenu(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public RemoteControlMenu(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mPaint = new Paint();
            mPaint.setAntiAlias(true);
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setStrokeWidth(4);
            mPaint.setColor(unselectedColor);
    
            offsetAngel = (360 - sweepAngel * 4) / 4;
            bigRectF = new RectF();
            smallRectF = new RectF();
    
            topRegion = new Region();
            bottomRegion = new Region();
            leftRegion = new Region();
            rightRegion = new Region();
            centerRegion = new Region();
            globalRegion = new Region();
            topPath = new Path();
            bottomPath = new Path();
            leftPath = new Path();
            rightPath = new Path();
            centerPath = new Path();
            mMapMatrix = new Matrix();
        }
    
        @Retention(RetentionPolicy.SOURCE)
        @IntDef({TouchArea.LEFT, TouchArea.TOP, TouchArea.RIGHT, TouchArea.BOTTOM,
                TouchArea.CENTER, TouchArea.INVALID})
        private @interface TouchArea {
            int LEFT = 1;
            int TOP = 2;
            int RIGHT = 3;
            int BOTTOM = 4;
            int CENTER = 5;
            int INVALID = 0;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            float[] pts = new float[2];
            pts[0] = event.getX();
            pts[1] = event.getY();
            Log.d("zhen", "原始触摸位置:" + Arrays.toString(pts) + " mMapMatrix: " + mMapMatrix);
            mMapMatrix.mapPoints(pts);
    
            int x = (int) pts[0];
            int y = (int) pts[1];
            Log.w("zhen", "转换后的触摸位置:" + Arrays.toString(pts) + " mMapMatrix: " + mMapMatrix);
            int touchArea = TouchArea.INVALID;
            switch (event.getAction()) {
                case MotionEvent.ACTION_UP:
                    if (leftRegion.contains(x, y)) {
                        touchArea = TouchArea.LEFT;
                    }
                    if (topRegion.contains(x, y)) {
                        touchArea = TouchArea.TOP;
                    }
                    if (rightRegion.contains(x, y)) {
                        touchArea = TouchArea.RIGHT;
                    }
                    if (bottomRegion.contains(x, y)) {
                        touchArea = TouchArea.BOTTOM;
                    }
                    if (centerRegion.contains(x, y)) {
                        touchArea = TouchArea.CENTER;
                    }
                    if (touchArea == TouchArea.INVALID) {
                        mTouchArea = touchArea;
                        Log.w("zhen", "点击outside");
                    } else {
                        if (mTouchArea == touchArea) {
                            //取消选中
                            isSelected = false;
                            mTouchArea = TouchArea.INVALID;
                        } else {
                            //选中
                            isSelected = true;
                            mTouchArea = touchArea;
                        }
                        Log.w("zhen", "按钮状态 mTouchArea " + mTouchArea + " isSelected: " + isSelected);
                        if (mListener != null) {
                            mListener.onMenuClicked(mTouchArea, isSelected);
                        }
                        invalidate();
                    }
                    break;
            }
    
            return true;
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mWidth = w;
            mHeight = h;
            //大圆
            bigRadius = (Math.min(mWidth, mHeight) - 250) / 2;
            bigRectF.set(-bigRadius, -bigRadius, bigRadius, bigRadius);
            //小圆
            smallRadius = (bigRadius - padding) / 2;
            smallRectF.set(-smallRadius - padding, -smallRadius - padding,
                    smallRadius + padding, smallRadius + padding);
    
            mMapMatrix.reset();
            globalRegion.set(-mWidth / 2, -mHeight / 2, mWidth / 2, mHeight / 2);
    
            centerPath.addCircle(0, 0, smallRadius, Path.Direction.CW);
            centerRegion.setPath(centerPath, globalRegion);
    
            float startAngel = -sweepAngel / 2f;
            rightPath.addArc(bigRectF, startAngel, sweepAngel + 4);
            startAngel += sweepAngel;
            rightPath.arcTo(smallRectF, startAngel, -sweepAngel);
            rightPath.close();
            rightRegion.setPath(rightPath, globalRegion);
    
            startAngel += offsetAngel;
            bottomPath.addArc(bigRectF, startAngel, sweepAngel + 4);
            startAngel += sweepAngel;
            bottomPath.arcTo(smallRectF, startAngel, -sweepAngel);
            bottomPath.close();
            bottomRegion.setPath(bottomPath, globalRegion);
    
            startAngel += offsetAngel;
            leftPath.addArc(bigRectF, startAngel, sweepAngel + 4);
            startAngel += sweepAngel;
            leftPath.arcTo(smallRectF, startAngel, -sweepAngel);
            leftPath.close();
            leftRegion.setPath(leftPath, globalRegion);
    
            startAngel += offsetAngel;
            topPath.addArc(bigRectF, startAngel, sweepAngel + 4);
            startAngel += sweepAngel;
            topPath.arcTo(smallRectF, startAngel, -sweepAngel);
            topPath.close();
            topRegion.setPath(topPath, globalRegion);
            Log.d("zhen", "globalRegion: " + globalRegion);
            Log.d("zhen", "globalRegion: " + globalRegion);
            Log.d("zhen", "leftRegion: " + leftRegion);
            Log.d("zhen", "topRegion: " + topRegion);
            Log.d("zhen", "rightRegion: " + rightRegion);
            Log.d("zhen", "bottomRegion: " + bottomRegion);
            Log.d("zhen", "centerRegion: " + centerRegion);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.translate(mWidth / 2, mHeight / 2);
            // 获取测量矩阵(逆矩阵)
            if (mMapMatrix.isIdentity()) {
                canvas.getMatrix().invert(mMapMatrix);
            }
    
            mPaint.setColor(unselectedColor);
            canvas.drawPath(centerPath, mPaint);
            canvas.drawPath(rightPath, mPaint);
            canvas.drawPath(bottomPath, mPaint);
            canvas.drawPath(leftPath, mPaint);
            canvas.drawPath(topPath, mPaint);
    
            if (!isSelected) return;
            mPaint.setColor(selectedColor);
            switch (mTouchArea) {
                case TouchArea.LEFT:
                    canvas.drawPath(leftPath, mPaint);
                    break;
                case TouchArea.TOP:
                    canvas.drawPath(topPath, mPaint);
                    break;
                case TouchArea.RIGHT:
                    canvas.drawPath(rightPath, mPaint);
                    break;
                case TouchArea.BOTTOM:
                    canvas.drawPath(bottomPath, mPaint);
                    break;
                case TouchArea.CENTER:
                    canvas.drawPath(centerPath, mPaint);
                    break;
            }
            Log.e("zhen", " touchArea: " + mTouchArea);
    
            //Android还提供了一个RegionIterator来对Region中的所有矩阵进行迭代,
            // 可以使用该类,获得某个Region的所有矩阵
            //通过遍历region中的矩阵,并绘制出来,来绘制region
    //        mPaint.setColor(Color.RED);
    //        RegionIterator iterator = new RegionIterator(topRegion);
    //        Rect r = new Rect();
    //        while (iterator.next(r)) {
    //            canvas.drawRect(r, mPaint);
    //        }
    //
    //        mPaint.setColor(Color.BLUE);
    //        RegionIterator iterator1 = new RegionIterator(leftRegion);
    //        Rect r1 = new Rect();
    //        while (iterator1.next(r1)) {
    //            canvas.drawRect(r1, mPaint);
    //        }
    //
    //        mPaint.setColor(Color.BLACK);
    //        RegionIterator iterator2 = new RegionIterator(rightRegion);
    //        Rect r2 = new Rect();
    //        while (iterator2.next(r2)) {
    //            canvas.drawRect(r2, mPaint);
    //        }
    //
    //        mPaint.setColor(Color.YELLOW);
    //        RegionIterator iterator3 = new RegionIterator(bottomRegion);
    //        Rect r3 = new Rect();
    //        while (iterator3.next(r3)) {
    //            canvas.drawRect(r3, mPaint);
    //        }
    //
    //        mPaint.setColor(Color.GREEN);
    //        RegionIterator iterator4 = new RegionIterator(centerRegion);
    //        Rect r4 = new Rect();
    //        while (iterator4.next(r4)) {
    //            canvas.drawRect(r4, mPaint);
    //        }
        }
    
        private MenuListener mListener;
    
        public void setListener(MenuListener listener) {
            mListener = listener;
        }
    
        // 点击事件监听器
        public interface MenuListener {
            void onMenuClicked(int type, boolean isSelected);
        }
    }
    

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持易采站长站。