Android 遥控器

遥控器源码
java 复制代码
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RadialGradient;
import android.graphics.Region;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import com.anbao.monitor.robot.schemas.Direction;

/**
 * 方向盘控制
 */
public class SteeringView extends View {

    private Paint paint;
    //第1个圆颜色
    private int circle1Color = Color.WHITE;
    //第2个圆颜色
    private int circle2Color = Color.parseColor("#4D5D6E");
    //第3个圆颜色
    private int circle3Color = Color.WHITE;
    //第4个圆颜色
    private int circle4Color = Color.GRAY;
    //线条颜色
    private int strokeColor = Color.WHITE;
    //左边三角形颜色
    private int leftTriangleColor = Color.WHITE;
    //右边三角形颜色
    private int rightTriangleColor = Color.WHITE;
    //上边三角形颜色
    private int topTriangleColor = Color.WHITE;
    //下边三角形颜色
    private int bottomTriangleColor = Color.WHITE;
    //第一个圆和第二个圆间距
    private float padding = 8;
    //线条宽度
    private float strokeWidth = 5;
    //第三个圆比例
    private float circle3RadiusFactor = 0.4f;
    //第4个圆比例
    private float circle4RadiusFactor = 0.3f;
    //三角形边长
    private float triangleLength = 100;
    //三角形和第二个圆间距
    private float trianglePadding = 90;
    //中心X
    private float cx;
    //中心Y
    private float cy;
    //半径
    private float radius;
    //高度
    protected float height;
    //左点击区域
    private Region leftRegion;
    //右点击区域
    private Region rightRegion;
    //上点击区域
    private Region topRegion;
    //下点击区域
    private Region bottomRegion;

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

    public SteeringView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SteeringView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(circle2Color);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        height = getMeasuredHeight();
        radius = Math.min(getMeasuredHeight(), getMeasuredWidth()) / 2f;
        cx = getMeasuredWidth() / 2f;
        cy = getMeasuredHeight() / 2f;
        trianglePadding = radius * 0.2f;
        triangleLength = radius * 0.22f;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (leftRegion.contains((int) x, (int) y)) {
                    leftTriangleColor = Color.RED;
                    onSteeringDirection(Direction.LEFT);
                } else if (rightRegion.contains((int) x, (int) y)) {
                    rightTriangleColor = Color.RED;
                    onSteeringDirection(Direction.RIGHT);
                } else if (topRegion.contains((int) x, (int) y)) {
                    topTriangleColor = Color.RED;
                    onSteeringDirection(Direction.FORWARD);
                } else if (bottomRegion.contains((int) x, (int) y)) {
                    bottomTriangleColor = Color.RED;
                    onSteeringDirection(Direction.BACKWARDS);
                }
                break;
            case MotionEvent.ACTION_UP:
                leftTriangleColor = Color.WHITE;
                rightTriangleColor = Color.WHITE;
                topTriangleColor = Color.WHITE;
                bottomTriangleColor = Color.WHITE;
                break;
        }
        invalidate();
        return true;
    }

    /**
     * 方向控制
     *
     * @param direction 方向
     */
    private void onSteeringDirection(Direction direction) {
        //左转
        if (direction == Direction.LEFT) {

        }
        //右转
        else if (direction == Direction.RIGHT) {

        }
        //前进
        else if (direction == Direction.FORWARD) {

        }
        //后退
        else if (direction == Direction.BACKWARDS) {

        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        paint.setShader(null);
        //外圆
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(circle1Color);
        canvas.drawCircle(cx, cy, radius, paint);
        //内圆
        paint.setColor(circle2Color);
        canvas.drawCircle(cx, cy, radius - padding, paint);
        //中心圆
        paint.setColor(circle3Color);
        canvas.drawCircle(cx, cy, radius * circle3RadiusFactor, paint);
        //左->右斜线
        paint.setColor(strokeColor);
        paint.setStrokeWidth(strokeWidth);
        float radians = (float) Math.toRadians(45);
        float lsx = cx - (float) ((radius - padding) * Math.cos(radians));
        float lsy = height / 2.0f - (float) ((radius - padding) * Math.sin(radians));
        float lex = cx + (float) ((radius - padding) * Math.cos(radians));
        float ley = height / 2.0f + (float) ((radius - padding) * Math.sin(radians));
        canvas.drawLine(lsx, lsy, lex, ley, paint);
        //右->左斜线
        float rsx = cx + (float) ((radius - padding) * Math.cos(radians));
        float rsy = height / 2.0f - (float) ((radius - padding) * Math.sin(radians));
        float rex = cx - (float) ((radius - padding) * Math.cos(radians));
        float rey = height / 2.0f + (float) ((radius - padding) * Math.sin(radians));
        canvas.drawLine(rsx, rsy, rex, rey, paint);
        //绘制左边箭头
        drawLeftTriangle(canvas);
        //绘制右边箭头
        drawRightTriangle(canvas);
        //绘制上方箭头
        drawTopTriangle(canvas);
        //绘制下方箭头
        drawBottomTriangle(canvas);
        //按下区域
        leftRegion = buildLeftRegion();
        rightRegion = buildRightRegion();
        topRegion = buildTopRegion();
        bottomRegion = buildBottomRegion();
        //外发光圆
        int[] colors = {Color.TRANSPARENT, circle4Color};
        float[] stops = {0.3f, 1.0f};
        RadialGradient gradient = new RadialGradient(cx, cy, radius * 0.3f, colors, stops, Shader.TileMode.CLAMP);
        paint.setShader(gradient);
        canvas.drawCircle(cx, cy, radius * circle4RadiusFactor, paint);
    }

    /**
     * 绘制左边三角形
     *
     * @param canvas
     */
    private void drawLeftTriangle(Canvas canvas) {
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(leftTriangleColor);
        Path path = new Path();
        path.moveTo(cx - radius + trianglePadding, cy);
        path.lineTo(cx - radius + trianglePadding + triangleLength, cy - triangleLength / 2f);
        path.lineTo(cx - radius + trianglePadding + triangleLength, cy + triangleLength / 2f);
        path.lineTo(cx - radius + trianglePadding, cy);
        canvas.drawPath(path, paint);
    }

    /**
     * 绘制右边三角形
     *
     * @param canvas
     */
    private void drawRightTriangle(Canvas canvas) {
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(rightTriangleColor);
        Path path = new Path();
        path.moveTo(cx + radius - trianglePadding, cy);
        path.lineTo(cx + radius - trianglePadding - triangleLength, cy - triangleLength / 2f);
        path.lineTo(cx + radius - trianglePadding - triangleLength, cy + triangleLength / 2f);
        path.lineTo(cx + radius - trianglePadding, cy);
        canvas.drawPath(path, paint);
    }

    /**
     * 绘制上方三角形
     *
     * @param canvas
     */
    private void drawTopTriangle(Canvas canvas) {
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(topTriangleColor);
        Path path = new Path();
        path.moveTo(cx, cy - radius + trianglePadding);
        path.lineTo(cx + triangleLength / 2f, cy - radius + trianglePadding + triangleLength);
        path.lineTo(cx - triangleLength / 2f, cy - radius + trianglePadding + triangleLength);
        path.lineTo(cx, cy - radius + trianglePadding);
        canvas.drawPath(path, paint);
    }

    /**
     * 绘制下方箭头
     *
     * @param canvas
     */
    private void drawBottomTriangle(Canvas canvas) {
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(bottomTriangleColor);
        Path path = new Path();
        path.moveTo(cx, cy + radius - trianglePadding);
        path.lineTo(cx + triangleLength / 2f, cy + radius - trianglePadding - triangleLength);
        path.lineTo(cx - triangleLength / 2f, cy + radius - trianglePadding - triangleLength);
        path.lineTo(cx, cy + radius - trianglePadding);
        canvas.drawPath(path, paint);
    }

    /**
     * 构建左边区域
     *
     * @return
     */
    private Region buildLeftRegion() {
        Region region = new Region();
        Path path = new Path();
        path.moveTo(cx, cy);
        path.addArc(cx - radius, cy - radius, cx + radius, cy + radius, -135, -90);
        path.lineTo(cx, cy);
        paint.setColor(Color.RED);
        Region clip = new Region((int) (cx - radius), (int) (cy - radius), (int) (cx - radius * circle3RadiusFactor), (int) (cy + radius));
        region.setPath(path, clip);
        return region;
    }

    /**
     * 构建右边区域
     *
     * @return
     */
    private Region buildRightRegion() {
        Region region = new Region();
        Path path = new Path();
        path.moveTo(cx, cy);
        path.addArc(cx - radius, cy - radius, cx + radius, cy + radius, -45, 90);
        path.lineTo(cx, cy);
        paint.setColor(Color.RED);
        Region clip = new Region((int) (cx + radius * circle3RadiusFactor), (int) (cy - radius), (int) (cx + radius), (int) (cy + radius));
        region.setPath(path, clip);
        return region;
    }

    /**
     * 构建上方区域
     *
     * @return
     */
    private Region buildTopRegion() {
        Region region = new Region();
        Path path = new Path();
        path.moveTo(cx, cy);
        path.addArc(cx - radius, cy - radius, cx + radius, cy + radius, -45, -90);
        path.lineTo(cx, cy);
        paint.setColor(Color.RED);
        Region clip = new Region((int) (cx - radius), (int) (cy - radius), (int) (cx + radius), (int) (cy - radius * circle3RadiusFactor));
        region.setPath(path, clip);
        return region;
    }

    /**
     * 构建下方区域
     *
     * @return
     */
    private Region buildBottomRegion() {
        Region region = new Region();
        Path path = new Path();
        path.moveTo(cx, cy);
        path.addArc(cx - radius, cy - radius, cx + radius, cy + radius, 45, 90);
        path.lineTo(cx, cy);
        paint.setColor(Color.RED);
        Region clip = new Region((int) (cx - radius), (int) (cy + radius * circle3RadiusFactor), (int) (cx + radius), (int) (cy + radius));
        region.setPath(path, clip);
        return region;
    }

}
相关推荐
拭心9 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王11 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡11 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道12 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库12 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道13 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe13 小时前
Android Hook - 动态加载so库
android
居居飒14 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He17 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗17 小时前
Android笔试面试题AI答之Android基础(1)
android