Android自定义View简单实现手绘折(曲)线滚动图效果

目录

一、简介

二、实现

三、代码

四、实现效果 


一、简介

        通过安卓自定义View实现根据手指点击或移动轨迹绘制出折(曲)线图并循环滚动。

二、实现

        获取手指点击和移动的y坐标存入数组,设定好x间隔,根据坐标数组和间隔绘制折线路径,并使用定时器Timer实现循环移动数组内容位置重新绘制折线来实现。(此方法实现会有肉眼可见的帧数问题)

三、代码

 attrs.xml:


    
        
        
        
        
        
        
    

自定义WaveView.java:

/**
 * author:created by mj
 * Date:2022/5/17 11:05
 * Description:自定义view用来实现手绘折线波动图的展示
 */
public class WaveView extends androidx.appcompat.widget.AppCompatImageView {
    //折线宽度、颜色、间隔宽度
    private float lineWidth;
    private int lineColor;
    private int lineSpaceWidth;
    private Paint linePaint;
    private Path path;

    //定时器用来数据循环显示
    private Timer timer;
    private TimerTask timerTask;

    //数组长度
    private int row;
    //绘制开始纵坐标位置
    private float startY;
    //折线坐标数组
    private float[] dataArray;
    private float[] tempData;

    private float mHeight = 0;

    @RequiresApi(api = Build.VERSION_CODES.M)
    public WaveView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    //初始化控件自定义属性和默认值以及画笔等方法
    @RequiresApi(api = Build.VERSION_CODES.M)
    private void init(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WaveView);
        lineWidth = typedArray.getInteger(R.styleable.WaveView_lineWidth, 5);
        lineSpaceWidth = typedArray.getInteger(R.styleable.WaveView_lineSpaceWidth, 20);
        lineColor = typedArray.getColor(R.styleable.WaveView_lineColor, context.getColor(R.color.hand_drawn_color));
        this.setWillNotDraw(false);
        //资源回收
        typedArray.recycle();

        //初始化画笔
        linePaint = new Paint();
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setStrokeWidth(lineWidth);
        linePaint.setColor(lineColor);
        linePaint.setStrokeCap(Paint.Cap.ROUND);
        linePaint.setAntiAlias(true);

        path = new Path();
        //初始化定时器
        timer = new Timer();

    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        //设置长度和宽度以及初始位置
        mHeight = getMeasuredHeight();
        //组件高度和宽度
        float mWidth = getMeasuredWidth();
        startY = mHeight / 1.25f;
        //根据间隔设置最多绘制多少个数据点
        row = (int) (mWidth / lineSpaceWidth) + 1;
        //初始化数据数组
        dataArray = new float[row];
        tempData = new float[row];
        for (int i = 0; i < row; i++) {
            dataArray[i] = startY;
        }
        //定时器循环执行数据改变实现滚动
        timerTask = new TimerTask() {
            @Override
            public void run() {
                //改变数组内容位置
                tempData = dataArray;
                //数组内容向前移动一位
                float temp = tempData[0];
                System.arraycopy(tempData, 1, tempData, 0, tempData.length - 1);
                tempData[tempData.length - 1] = temp;
                dataArray = tempData;
                postInvalidate();
            }
        };
        timer.schedule(timerTask, 0, 100);
    }

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

    }

    //绘制折线
    private void drawWaveLine(Canvas canvas) {
        path.reset();
        path.moveTo(0, dataArray[0]);
        for (int i = 0; i < dataArray.length - 1; i++) {
            path.lineTo(i * lineSpaceWidth, dataArray[i]);
        }
        canvas.drawPath(path, linePaint);
    }

    public float[] getTempData() {
        return tempData;
    }

    public void setTempData(float[] tempData) {
        this.tempData = tempData;
    }
}

布局中添加组件

    

界面中添加数据

private WaveView showView;

showView = findViewById(R.id.view_drawnShow);

private final View.OnTouchListener touchListener = new View.OnTouchListener() {
        //手指点击和移动事件
        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                    //添加坐标数据
                    tempData = showView.getTempData();
                    //控制最大高度
                    if (event.getY() < 0)
                        tempData[tempData.length - 1] = toolbar.getHeight()/4f;
                    else
                        tempData[tempData.length - 1] = event.getY();
                    showView.setTempData(tempData);
                    break;
                default:
                    break;
            }
            return true;
        }
    };

四、实现效果 

 Android自定义View简单实现手绘折(曲)线滚动图效果_第1张图片

你可能感兴趣的:(android,java,开发语言)