汽车雷达距离指示

RadarView.java复制代码
package android.car.app.canbus;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class RadarView extends View {
    static final String TAG = RadarView.class.getSimpleName();
    static final boolean DEBUG = false;
    public static final int DIRECTION_UP = 1;
    public static final int DIRECTION_DOWN = 2;
    public static final int DIRECTION_LEFT = 3;
    public static final int DIRECTION_RIGHT = 4;
    // 显示风格
    public enum RadarStyle {
        InsideToOutside, // 内到外显示
        OutsideToInside, // 外到内显示
    }
    boolean mDebug = DEBUG;
    // 是否是纵向
    boolean mVertical = true;
    int mCellXCount;
    int mCellYCount;
    float mCenterXPercent;
    float mCenterYPercent;
    float mDrawBeginPercent;
    float mDrawSizePercent;
    float mBeginDegree;
    float mXSpacePercent;
    float mYSpacePercent;
    float mDegree;
    float mCellDegree;
    float mWidth;
    float mHeight;
    float mCellWidth;
    float mCellDrawWidth;
    float mCellHeight;
    float mCellDrawHeight;
    float mCellXSpace;
    float mCellYSpace;
    float mCenterX;
    float mCenterY;
    float mDrawBegin;
    float mDrawSize;
    int[] mLevels = null;
    int[][] mLevelColors = null;
    RadarStyle mStyle = RadarStyle.InsideToOutside;
    Paint mPaint = new Paint();
    public RadarView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }
    public RadarView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }
    public RadarView(Context context) {
        super(context);
        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }
    /**
     * 简易设置参数
     *
     * @param direction  方向, 决定了角度参照和圆心位置 @DIRECTION_
     * @param cellXCount X方向的格数
     * @param cellYCount Y方向的格数
     * @param degree     显示的角度
     */
    public void initRadar(int direction, int cellXCount, int cellYCount, float xSpace, float ySpace, float degree) {
        float centerX, centerY, drawBegin, drawSize, beginDegree;
        boolean vertical = false;
        drawBegin = 0.1f;
        drawSize = 0.8f;
        switch (direction) {
            default:
            case DIRECTION_UP:
                beginDegree = 180 + (180 - degree) / 2;
                centerX = 0.5f;
                centerY = 2.0f;
                vertical = true;
                break;
            case DIRECTION_DOWN:
                beginDegree = (180 - degree) / 2;
                centerX = 0.5f;
                centerY = -1.0f;
                vertical = true;
                break;
            case DIRECTION_LEFT:
                beginDegree = 90 + (180 - degree) / 2;
                centerX = 2.0f;
                centerY = 0.5f;
                vertical = false;
                break;
            case DIRECTION_RIGHT:
                beginDegree = 270 + (180 - degree) / 2;
                centerX = -1.0f;
                centerY = 0.5f;
                vertical = false;
                break;
        }
        initRadar(vertical, cellXCount, cellYCount, centerX, centerY, drawBegin, drawSize, xSpace, ySpace, beginDegree,
                degree);
    }
    /**
     * 初始化雷达显示参数, 除XCount/YCount/degree外, 都为百分比参数
     *
     * @param vertical    是否是纵向的
     * @param cellXCount  X方向的最大格数
     * @param cellYCount  Y方向的最大格数
     * @param centerX     圆心X (百分比)
     * @param centerY     圆心Y (百分比)
     * @param drawBegin   绘制开始位置 (百分比) 相对于控件本身
     * @param drawSize    绘制大小 (百分比) 相对于控件本身
     * @param xSpace      X方向的间隔 (百分比)
     * @param ySpace      Y方向的间隔 (百分比)
     * @param beginDegree 开始的角度(决定了方向)
     * @param degree      总角度(决定了大小)
     */
    public void initRadar(boolean vertical, int cellXCount, int cellYCount, float centerX, float centerY,
                          float drawBegin, float drawSize, float xSpace, float ySpace, float beginDegree, float degree) {
        if (cellXCount <= 0 || cellYCount <= 0)
            throw new IllegalArgumentException("cellXCount and cellYCount must > 0");
        mVertical = vertical;
        mCellXCount = cellXCount;
        mCellYCount = cellYCount;
        mCenterXPercent = centerX;
        mCenterYPercent = centerY;
        mDrawBeginPercent = drawBegin;
        mDrawSizePercent = drawSize;
        mXSpacePercent = xSpace;
        mYSpacePercent = ySpace;
        mDegree = degree;
        if (isInit()) {
            mBeginDegree = beginDegree;
            mCellDegree = degree / mCellXCount;
        }
        mLevels = new int[mCellXCount];
        mLevelColors = new int[mCellXCount][mCellYCount];
        initRadarParams(getWidth(), getHeight());
    }
    /**
     * 设置指定cell列的颜色
     *
     * @param cellX  X索引, =-1时代表设置所有颜色
     * @param colors
     */
    public void setRadarLevelColor(int cellX, int[] colors) {
        if (colors == null)
            throw new IllegalAccessError("colors is null");
        boolean changed = false;
        if (cellX == -1) {
            for (int i = 0; i < mCellXCount; ++i) {
                if (setRadarLevelColorInternal(i, colors))
                    changed = true;
            }
        } else {
            changed = setRadarLevelColorInternal(cellX, colors);
        }
        if (changed)
            postInvalidate();
    }
    /**
     * 设置指定cell列的颜色
     *
     * @param cellX
     * @param colors
     * @return 返回是否发生改变
     */
    private boolean setRadarLevelColorInternal(int cellX, int[] colors) {
        boolean changed = false;
        if (cellX >= 0 && cellX < mCellXCount) {
            for (int i = 0; i < mLevelColors[cellX].length && i < colors.length; ++i) {
                if (mLevelColors[cellX][i] != colors[i]) {
                    mLevelColors[cellX][i] = colors[i];
                    changed = true;
                }
            }
        }
        return changed;
    }
    public boolean isInit() {
        return mCellXCount > 0 && mCellYCount > 0;
    }
    /**
     * 获取CellX个数
     */
    public int getCellXCount() {
        return mCellXCount;
    }
    /**
     * 获取CellY个数
     */
    public int getCellYCount() {
        return mCellYCount;
    }
    /**
     * 获取指定cell的颜色
     *
     * @param cellX
     * @param cellY
     * @return
     */
    public int getRadarLevelColor(int cellX, int cellY) {
        if (isInit()) {
            if (cellX >= 0 && cellX < mCellXCount && cellY >= 0 && cellY < mCellYCount) {
                return mLevelColors[cellX][cellY];
            }
        }
        return 0;
    }
    /**
     * 设置指定cell的颜色
     *
     * @param cellX
     * @param cellY
     * @return
     */
    public int setRadarLevelColor(int cellX, int cellY, int color) {
        if (isInit()) {
            if (cellX >= 0 && cellX < mCellXCount && cellY >= 0 && cellY < mCellYCount) {
                if (mLevelColors[cellX][cellY] != color) {
                    mLevelColors[cellX][cellY] = color;
                    postInvalidate();
                }
            }
        }
        return 0;
    }
    /**
     * 获取指定cell的当前level
     *
     * @param cellX
     * @return
     */
    public int getRadarLevel(int cellX) {
        if (cellX >= 0 && cellX < mCellXCount) {
            return mLevels[cellX];
        }
        return -1;
    }
    /**
     * 设置指定cellX的level
     *
     * @param cellX
     * @param level
     */
    public void setRadarLevel(int cellX, int level) {
        if (cellX >= 0 && cellX < mCellXCount) {
            if (level < 0)
                level = 0;
            if (level > mCellYCount)
                level = mCellYCount - 1;
            if (mLevels[cellX] != level) {
                mLevels[cellX] = level;
                postInvalidate();
            }
        }
    }
    /**
     * 设置雷达的风格
     *
     * @param style RadarStyle
     */
    public void setRadarStyle(RadarStyle style) {
        if (style == null)
            style = RadarStyle.InsideToOutside;
        if (mStyle != style) {
            mStyle = style;
            postInvalidate();
        }
    }
    public RadarStyle getRadarStyle() {
        return mStyle;
    }
    /**
     * 将雷达信息重置, 全都设置为0
     */
    public void resetRadarLevel() {
        for (int i = 0; i < mCellXCount; ++i) {
            setRadarLevel(i, 0);
        }
    }
    public void setDebug(boolean debug) {
        mDebug = debug;
    }
    protected void initRadarParams(int width, int height) {
        if (mWidth != width || mHeight != height) {
            mWidth = width;
            mHeight = height;
            if (isInit()) {
                mCenterX = mWidth * mCenterXPercent;
                mCenterY = mHeight * mCenterYPercent;
                if (mVertical) {
                    mCellWidth = mWidth / mCellXCount;
                    mCellXSpace = mCellWidth * mXSpacePercent;
                    mCellDrawWidth = mCellWidth - mCellXSpace;
                    mDrawBegin = mHeight * mDrawBeginPercent;
                    mDrawSize = mHeight * mDrawSizePercent;
                    mCellHeight = mDrawSize / mCellYCount;
                    mCellYSpace = mCellHeight * mYSpacePercent;
                    mCellDrawHeight = mCellHeight - mCellYSpace;
                } else {
                    mCellWidth = mHeight / mCellXCount;
                    mCellXSpace = mCellWidth * mXSpacePercent;
                    mCellDrawWidth = mCellWidth - mCellXSpace;
                    mDrawBegin = mWidth * mDrawBeginPercent;
                    mDrawSize = mWidth * mDrawSizePercent;
                    mCellHeight = mDrawSize / mCellYCount;
                    mCellYSpace = mCellHeight * mYSpacePercent;
                    mCellDrawHeight = mCellHeight - mCellYSpace;
                }
                mPaint.setAntiAlias(true);
                mPaint.setStyle(Style.FILL);
                mPaint.setColor(Color.RED);
            }
            if (mDebug) {
                Log.d(TAG,
                        String.format(
                                "initRadarParams mWidth=%.1f,  mHeight=%.1f, mCellWidth=%.1f, mCellDrawWidth=%.1f, mCellHeight=%.1f, mCellDrawHeight=%.1f, mCenterX=%.1f, mCenterY=%.1f, mBegin=%.1f, mEnd=%.1f",
                                mWidth, mHeight, mCellWidth, mCellDrawWidth, mCellHeight, mCellDrawHeight, mCenterX,
                                mCenterY, mDrawBegin, mDrawSize));
            }
        }
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = getMeasuredWidth();
        int height = getMeasuredHeight();
        if (mDebug) {
            Log.d(TAG, "onMeasure width=" + width + ", height=" + height);
        }
        initRadarParams(width, height);
    }
    /**
     * @param canvas
     * @param paint
     * @param centerX   中心点x
     * @param centerY   中心点y
     * @param begPos    矩形内框
     * @param height    矩形高度
     * @param begDegree 开始角度
     * @param degree    角度
     */
    static void drawRadarBox(Canvas canvas, Paint paint, float centerX, float centerY, float begPos, float height,
                             float begDegree, float degree) {
        RectF outer = new RectF(centerX - begPos, centerY - begPos, centerX + begPos, centerY + begPos);
        RectF inner = new RectF(outer);
        inner.inset(-height, -height);
        if (DEBUG) {
            Log.d(TAG,
                    String.format(
                            "drawRadarBox centerX=%.1f,  centerY=%.1f, begPos=%.1f, height=%.1f, begDegree=%.1f, degree=%.1f, inner=%s, outer=%s",
                            centerX, centerY, begPos, height, begDegree, degree, inner.toShortString(),
                            outer.toShortString()));
        }
        if (DEBUG) {
            paint.setStyle(Style.STROKE);
            int color = paint.getColor();
            paint.setARGB(128, 255, 0, 128);
            canvas.drawRect(outer, paint);
            canvas.drawRect(inner, paint);
            paint.setColor(color);
            paint.setStyle(Style.FILL);
        }
        Path path = new Path();
        path.arcTo(outer, begDegree, degree);
        path.arcTo(inner, begDegree + degree, -degree);
        path.close();
        canvas.drawPath(path, paint);
    }
    /**
     * 绘制纵向的雷达块
     */
    private void drawRadarCellV(Canvas canvas, int cellX, int cellY) {
        int color = getRadarLevelColor(cellX, cellY);
        final Paint p = mPaint;
        p.setColor(color);
        if (mDebug)
            Log.d(TAG, String.format("x=%d, y=%d, color=%08x", cellX, cellY, color));
        float x = mCenterX;
        float y = mCenterY;
        float yOffset = mCenterY < 0 ? -mCenterY : mCenterY > mHeight ? mCenterY - mHeight : 0;
        float begPos = mDrawBegin + cellY * mCellHeight + yOffset;
        float cellDraw = mCellDrawHeight;
        float cellDeg = mCellDegree;
        float degDraw = cellDeg * (1.0f - mXSpacePercent);
        float begDeg = mBeginDegree + cellX * cellDeg;
        drawRadarBox(canvas, p, x, y, begPos, cellDraw, begDeg, degDraw);
    }
    /**
     * 绘制横向的雷达块
     */
    private void drawRadarCellH(Canvas canvas, int cellX, int cellY) {
        int color = getRadarLevelColor(cellX, cellY);
        final Paint p = mPaint;
        p.setColor(color);
        if (mDebug)
            Log.d(TAG, String.format("x=%d, y=%d, color=%08x", cellX, cellY, color));
        float x = mCenterX;
        float y = mCenterY;
        float offset = mCenterX < 0 ? -mCenterX : mCenterX > mWidth ? mCenterX - mWidth : 0;
        float begPos = mDrawBegin + cellY * mCellHeight + offset;
        float cellDraw = mCellDrawHeight;
        float cellDeg = mCellDegree;
        float degDraw = cellDeg * (1.0f - mXSpacePercent);
        float begDeg = mBeginDegree + cellX * cellDeg;
        drawRadarBox(canvas, p, x, y, begPos, cellDraw, begDeg, degDraw);
    }
    Paint mBgPaint = new Paint();
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (!isInit())
            return;
        if (mDebug) {
            mBgPaint.setColor(Color.BLACK);
            mBgPaint.setStyle(Style.STROKE);
            mBgPaint.setStrokeWidth(2);
            canvas.drawRect(0, 0, mWidth, mHeight, mBgPaint);
        }
        for (int i = 0; i < mCellXCount; ++i) {
            drawOneLineRadar(canvas, i);
        }
    }
    protected void drawOneLineRadar(Canvas canvas, int x) {
        if (x >= 0 && x < mCellXCount) {
            switch (mStyle) {
                case InsideToOutside:
                    for (int j = 0; j < mLevels[x]; ++j) {
                        if (mVertical) {
                            drawRadarCellV(canvas, x, j);
                        } else {
                            drawRadarCellH(canvas, x, j);
                        }
                    }
                    break;
                case OutsideToInside:
                    if(mLevels[x] == 0) {//0为没有障碍物
                        return;
                    }
                    for (int j = mCellYCount - 1; j >= mLevels[x] - 1; --j) {
                        if (mVertical) {
                            drawRadarCellV(canvas, x, j);
                        } else {
                            drawRadarCellH(canvas, x, j);
                        }
                    }
                    break;
            }
        }
    }
}复制代码
使用:
private void initRadarView() {
    mRadarViewFront = (RadarView) mRadarFloatView.findViewById(R.id.radar_front_view);

    float d = 40;
    float xSpace = 0.03f;
    float ySpace = 0.10f;

    mRadarViewFront.initRadar(RadarView.DIRECTION_UP, 4, RADAR_SIDE_MAX, xSpace, ySpace, d);
    mRadarViewFront.setRadarLevelColor(-1, mFrontRadarColors);
}复制代码




你可能感兴趣的:(汽车雷达距离指示)