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

本文实例为大家分享了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);     } }

推荐阅读