iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >android怎么实现可以滑动的平滑曲线图
  • 832
分享到

android怎么实现可以滑动的平滑曲线图

2023-07-02 13:07:35 832人浏览 薄情痞子
摘要

本文小编为大家详细介绍“Android怎么实现可以滑动的平滑曲线图”,内容详细,步骤清晰,细节处理妥当,希望这篇“android怎么实现可以滑动的平滑曲线图”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1 att

本文小编为大家详细介绍“Android怎么实现可以滑动的平滑曲线图”,内容详细,步骤清晰,细节处理妥当,希望这篇“android怎么实现可以滑动的平滑曲线图”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

1 attr 属性编写   

<!-- xy坐标轴颜色 --><attr name="xy_line_color" fORMat="color" />    <!-- xy坐标轴宽度 -->    <attr name="xy_line_width" format="dimension" />    <!-- xy坐标轴文字颜色 -->    <attr name="xy_text_color" format="color" />    <!-- xy坐标轴文字大小 -->    <attr name="xy_text_size" format="dimension" />    <!-- 折线图中折线的颜色 -->    <attr name="line_color" format="color" />    <!-- x轴各个坐标点水平间距 -->    <attr name="interval" format="dimension" />    <!-- 背景颜色 -->    <attr name="bg_color" format="color" />    <!-- 曲线选中外部颜色 -->    <attr name="select_circle_color" format="color" />    <!-- 曲线选中内部颜色 -->    <attr name="select_reminder_color" format="color" />    <!--是否抬手滚动-->    <attr name="isScroll" format="boolean" />    <declare-styleable name="ChartView">        <attr name="xy_line_color" />        <attr name="xy_line_width" />        <attr name="xy_text_color" />        <attr name="xy_text_size" />        <attr name="line_color" />        <attr name="interval" />        <attr name="bg_color" />        <attr name="select_circle_color" />        <attr name="select_reminder_color" />        <attr name="isScroll" />        <!--提示框跟滑动显示的位置-->        <attr name="show_position">            <enum name="first" value="1" />            <enum name="middle" value="2" />            <enum name="end" value="3" />        </attr></declare-styleable>

2 ChartView

package com.laisontech.commonuilibrary.customviews;import android.animation.Animator;import android.animation.ValueAnimator;import android.content.Context;import android.content.res.TypedArray;import android.graphics.canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.PorterDuff;import android.graphics.PorterDuffXfermode;import android.graphics.Rect;import android.graphics.RectF;import android.util.AttributeSet;import android.util.Log;import android.util.TypedValue;import android.view.MotionEvent;import android.view.VelocityTracker;import android.view.View;import android.view.animation.DecelerateInterpolator;import com.laisontech.commonuilibrary.R;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class ChartView extends View {    private static final int FIRST = 1;    private static final int MIDDLE = 2;    private static final int END = 3;    //xy坐标轴颜色    private int xyLineColor = 0xffCFE2CF;    //折线选中的圆形颜色    private int selectCircleColor = 0xff00A8FF;    //选中数据提示框颜色    private int selectReminderColor = 0xff00A8FF;    //折线中圆形内部部颜色    private int xyTextColor = 0xff0014FF;    //折线图中折线的颜色    private int lineColor = 0xffFD00FF;    //xy坐标轴宽度    private int xyLineWidth = dpToPx(1);    //xy坐标轴文字大小    private int xyTextSize = spToPx(12);    //x轴各个坐标点水平间距    private int interval = dpToPx(40);    //背景颜色    private int bGColor = 0xffffffff;    //是否有起手时的滑动感    private boolean isScroll = false;    //提示框显示位置    private int mShowPositionType = 3;    //绘制XY轴坐标对应的画笔    private Paint mXYPaint;    //绘制XY轴的文本对应的画笔    private Paint mXYTextPaint;    //画折线对应的画笔    private Paint mSpinnerLinePaint;    private int width;    private int height;    //x轴的原点坐标    private int mXOri;    //y轴的原点坐标    private int mYOri;    //第一个点X的坐标    private float mXInit;    //第一个点对应的最大X坐标    private float maxXInit;    //第一个点对应的最小X坐标    private float minXInit;    //x轴坐标对应的数据    private List<String> mXData = new ArrayList<>();    //y轴坐标对应的数据    private List<Integer> mYData = new ArrayList<>();    //折线对应的数据    private Map<String, Integer> mSpinnerValue = new HashMap<>();    //点击的点对应的X轴的第几个点,默认1    private int selectIndex = 1;    //X轴刻度文本对应的最大矩形,为了选中时,在x轴文本画的框框大小一致,获取从数据中得到的x轴数据,获得最长数据    private Rect xValueRect;    //速度检测器    private VelocityTracker mTracker;    //是否为短距离滑动    private boolean isshortSlide = false;    //获取尺寸的的中间    private int mSelectMiddle = 0;    //曲线切率    private float mLineSmoothness = 0.18f;    public ChartView(Context context) {        this(context, null);    }    public ChartView(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public ChartView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context, attrs, defStyleAttr);        initPaint();    }    //设置切率    public void setLineSmoothness(float lineSmoothness) {        if (lineSmoothness != this.mLineSmoothness) {            this.mLineSmoothness = lineSmoothness;        }    }        private void initPaint() {        mXYPaint = new Paint();        mXYPaint.setAntiAlias(true);        mXYPaint.setStrokeWidth(xyLineWidth);        mXYPaint.setStrokeJoin(Paint.Join.ROUND);        mXYPaint.setColor(xyLineColor);        mXYTextPaint = new Paint();        mXYTextPaint.setAntiAlias(true);        mXYTextPaint.setTextSize(xyTextSize);        mXYTextPaint.setStrokeJoin(Paint.Join.ROUND);        mXYTextPaint.setColor(xyTextColor);        mXYTextPaint.setStyle(Paint.Style.STROKE);        mSpinnerLinePaint = new Paint();        mSpinnerLinePaint.setAntiAlias(true);        mSpinnerLinePaint.setStrokeWidth(xyLineWidth);        mSpinnerLinePaint.setColor(lineColor);        mSpinnerLinePaint.setStyle(Paint.Style.STROKE);        mSpinnerLinePaint.setStrokeJoin(Paint.Join.ROUND);    }        private void init(Context context, AttributeSet attrs, int defStyleAttr) {        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ChartView, defStyleAttr, 0);        int count = array.getIndexCount();        for (int i = 0; i < count; i++) {            int attr = array.getIndex(i);            if (attr == R.styleable.ChartView_xy_line_color) {                xyLineColor = array.getColor(attr, xyLineColor);            } else if (attr == R.styleable.ChartView_xy_line_width) {                xyLineWidth = (int) array.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, xyLineWidth, getResources().getDisplayMetrics()));            } else if (attr == R.styleable.ChartView_xy_text_color) {                xyTextColor = array.getColor(attr, xyTextColor);            } else if (attr == R.styleable.ChartView_xy_text_size) {                xyTextSize = (int) array.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, xyTextSize, getResources().getDisplayMetrics()));            } else if (attr == R.styleable.ChartView_line_color) {                lineColor = array.getColor(attr, lineColor);            } else if (attr == R.styleable.ChartView_interval) {                interval = (int) array.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, interval, getResources().getDisplayMetrics()));            } else if (attr == R.styleable.ChartView_bg_color) {                bgColor = array.getColor(attr, bgColor);            } else if (attr == R.styleable.ChartView_select_circle_color) {                selectCircleColor = array.getColor(attr, selectCircleColor);            } else if (attr == R.styleable.ChartView_select_reminder_color) {                selectReminderColor = array.getColor(attr, selectReminderColor);            } else if (attr == R.styleable.ChartView_isScroll) {                isScroll = array.getBoolean(attr, isScroll);            } else if (attr == R.styleable.ChartView_show_position) {                mShowPositionType = array.getInt(attr, mShowPositionType);            }        }        array.recycle();    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        if (changed) {            width = getWidth();            height = getHeight();            //Y轴文本的最大宽度            float textYWdith = getTextBounds(mYData.get(getListItemMaxIndex(mYData)) + "", mXYTextPaint).width();            for (int i = 0; i < mYData.size(); i++) {//求取y轴文本最大的宽度                float temp = getTextBounds(mYData.get(i) + "", mXYTextPaint).width();                if (temp > textYWdith)                    textYWdith = temp;            }            int dp2 = dpToPx(2);            int dp3 = dpToPx(3);            mXOri = (int) (dp2 + textYWdith + dp2 + xyLineWidth);            //获取x轴的最长文本的宽度所占的矩形            xValueRect = getTextBounds(mXData.get(getListItemMaxIndex(mXData)), mXYTextPaint);            //X轴文本高度            float textXHeight = xValueRect.height();            for (int i = 0; i < mXData.size(); i++) {                Rect rect = getTextBounds(mXData.get(i) + "", mXYTextPaint);                if (rect.height() > textXHeight)                    textXHeight = rect.height();                if (rect.width() > xValueRect.width())                    xValueRect = rect;            }            mYOri = (int) (height - dp2 - textXHeight - dp3 - xyLineWidth);            mXInit = mXOri + xValueRect.width() / 2 + dpToPx(5);            minXInit = width - (width - mXOri) * 0.1f - interval * (mXData.size() - 1);            maxXInit = mXInit;        }        selectIndex = getSelectIndexFromShowType(mShowPositionType);        super.onLayout(changed, left, top, right, bottom);    }    @Override    protected void onDraw(Canvas canvas) {        canvas.drawColor(bgColor);        drawXY(canvas);        drawBrokenLineAndPoint(canvas);    }        private void drawBrokenLineAndPoint(Canvas canvas) {        if (mXData.size() <= 0)            return;        int layerId = canvas.saveLayer(0, 0, width, height, null, Canvas.ALL_SAVE_FLAG);        drawBrokenLine(canvas);        drawBrokenPoint(canvas);        // 将超出x轴坐标的部分截掉        mSpinnerLinePaint.setStyle(Paint.Style.FILL);        mSpinnerLinePaint.setColor(bgColor);        mSpinnerLinePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));        RectF rectF = new RectF(0, 0, mXOri, height);        canvas.drawRect(rectF, mSpinnerLinePaint);        mSpinnerLinePaint.setXfermode(null);        canvas.restoreToCount(layerId);    }        private void drawBrokenPoint(Canvas canvas) {        float dp2 = dpToPx(2);        float dp4 = dpToPx(4);        float dp7 = dpToPx(7);        Log.e("selectIndex", "index:" + selectIndex);        //绘制节点        for (int i = 0; i < mXData.size(); i++) {            float x = mXInit + interval * i;            float y = mYOri - mYOri * (1 - 0.1f) * mSpinnerValue.get(mXData.get(i)) / mYData.get(mYData.size() - 1);            //绘制选中点            if (i == selectIndex - 1) {                mSpinnerLinePaint.setStyle(Paint.Style.FILL);                //设置选中颜色                mSpinnerLinePaint.setColor(selectCircleColor);                canvas.drawCircle(x, y, dp7, mSpinnerLinePaint);                mSpinnerLinePaint.setColor(selectReminderColor);                canvas.drawCircle(x, y, dp4, mSpinnerLinePaint);                drawFloatTextBox(canvas, x, y - dp7, mSpinnerValue.get(mXData.get(i)));            }            //绘制普通节点            mSpinnerLinePaint.setStyle(Paint.Style.FILL);            mSpinnerLinePaint.setColor(Color.WHITE);            canvas.drawCircle(x, y, dp2, mSpinnerLinePaint);            mSpinnerLinePaint.setStyle(Paint.Style.STROKE);            mSpinnerLinePaint.setColor(lineColor);            canvas.drawCircle(x, y, dp2, mSpinnerLinePaint);        }    }        private void drawFloatTextBox(Canvas canvas, float x, float y, int text) {        int dp6 = dpToPx(6);        int dp18 = dpToPx(18);        //p1        Path path = new Path();        path.moveTo(x, y);        //p2        path.lineTo(x - dp6, y - dp6);        //p3        path.lineTo(x - dp18, y - dp6);        //p4        path.lineTo(x - dp18, y - dp6 - dp18);        //p5        path.lineTo(x + dp18, y - dp6 - dp18);        //p6        path.lineTo(x + dp18, y - dp6);        //p7        path.lineTo(x + dp6, y - dp6);        //p1        path.lineTo(x, y);        canvas.drawPath(path, mSpinnerLinePaint);        mSpinnerLinePaint.setColor(Color.WHITE);        mSpinnerLinePaint.setTextSize(spToPx(14));        Rect rect = getTextBounds(text + "", mSpinnerLinePaint);        canvas.drawText(text + "", x - rect.width() / 2, y - dp6 - (dp18 - rect.height()) / 2, mSpinnerLinePaint);    }        private void drawBrokenLine(Canvas canvas) {        mSpinnerLinePaint.setStyle(Paint.Style.STROKE);        mSpinnerLinePaint.setColor(lineColor);        //绘制折线        Path path = new Path();        float prePreviousPointX = Float.NaN;        float prePreviousPointY = Float.NaN;        float previousPointX = Float.NaN;        float previousPointY = Float.NaN;        float currentPointX = Float.NaN;        float currentPointY = Float.NaN;        float nextPointX;        float nextPointY;        int lineSize = mXData.size();        for (int i = 0; i < lineSize; i++) {            float x;            float y;            if (Float.isNaN(currentPointX)) {                currentPointX = getSpinnerPoint(i).x;                currentPointY = getSpinnerPoint(i).y;            }            if (Float.isNaN(previousPointX)) {                //是第一个点?                if (i > 0) {                    previousPointX = getSpinnerPoint(i - 1).x;                    previousPointY = getSpinnerPoint(i - 1).y;                } else {                    //用当前点表示上一个点                    previousPointX = currentPointX;                    previousPointY = currentPointY;                }            }            if (Float.isNaN(prePreviousPointX)) {                //是前两个点?                if (i > 1) {                    prePreviousPointX = getSpinnerPoint(i - 2).x;                    prePreviousPointY = getSpinnerPoint(i - 2).y;                } else {                    //当前点表示上上个点                    prePreviousPointX = previousPointX;                    prePreviousPointY = previousPointY;                }            }            // 判断是不是最后一个点了            if (i < lineSize - 1) {                nextPointX = getSpinnerPoint(i + 1).x;                nextPointY = getSpinnerPoint(i + 1).y;            } else {                //用当前点表示下一个点                nextPointX = currentPointX;                nextPointY = currentPointY;            }            if (i == 0) {                // 将Path移动到开始点                path.moveTo(currentPointX, currentPointY);            } else {                // 求出控制点坐标                final float firstDiffX = (currentPointX - prePreviousPointX);                final float firstDiffY = (currentPointY - prePreviousPointY);                final float secondDiffX = (nextPointX - previousPointX);                final float secondDiffY = (nextPointY - previousPointY);                final float firstControlPointX = previousPointX + (mLineSmoothness * firstDiffX);                final float firstControlPointY = previousPointY + (mLineSmoothness * firstDiffY);                final float secondControlPointX = currentPointX - (mLineSmoothness * secondDiffX);                final float secondControlPointY = currentPointY - (mLineSmoothness * secondDiffY);                //画出曲线                path.cubicTo(firstControlPointX, firstControlPointY, secondControlPointX, secondControlPointY,                        currentPointX, currentPointY);            }            // 更新            prePreviousPointX = previousPointX;            prePreviousPointY = previousPointY;            previousPointX = currentPointX;            previousPointY = currentPointY;            currentPointX = nextPointX;            currentPointY = nextPointY;        }        canvas.drawPath(path, mSpinnerLinePaint);    }        private void drawXY(Canvas canvas) {        int length = dpToPx(5);//刻度的长度        //绘制Y坐标        canvas.drawLine(mXOri - xyLineWidth / 2, 0, mXOri - xyLineWidth / 2, mYOri, mXYPaint);        //绘制箭头        mXYPaint.setStyle(Paint.Style.STROKE);        Path path = new Path();        path.moveTo(mXOri - xyLineWidth / 2 - dpToPx(5), dpToPx(12));        path.lineTo(mXOri - xyLineWidth / 2, xyLineWidth / 2);        path.lineTo(mXOri - xyLineWidth / 2 + dpToPx(5), dpToPx(12));        canvas.drawPath(path, mXYPaint);        //绘制刻度        int yLength = (int) (mYOri * (1 - 0.1f) / (mYData.size() - 1));//y轴上面空出10%,计算出y轴刻度间距        for (int i = 0; i < mYData.size(); i++) {            //绘制刻度            canvas.drawLine(mXOri, mYOri - yLength * i + xyLineWidth / 2, mXOri + length, mYOri - yLength * i + xyLineWidth / 2, mXYPaint);            mXYTextPaint.setColor(xyTextColor);            //绘制文本            String text = mYData.get(i) + "";            Rect rect = getTextBounds(text, mXYTextPaint);            canvas.drawText(text, 0, text.length(), mXOri - xyLineWidth - dpToPx(2) - rect.width(), mYOri - yLength * i + rect.height() / 2, mXYTextPaint);        }        //绘制坐标        canvas.drawLine(mXOri, mYOri + xyLineWidth / 2, width, mYOri + xyLineWidth / 2, mXYPaint);        //绘制箭头        mXYPaint.setStyle(Paint.Style.STROKE);        path = new Path();        //整个长度        float xLength = mXInit + interval * (mXData.size() - 1) + (width - mXOri) * 0.1f;        if (xLength < width)            xLength = width;        path.moveTo(xLength - dpToPx(12), mYOri + xyLineWidth / 2 - dpToPx(5));        path.lineTo(xLength - xyLineWidth / 2, mYOri + xyLineWidth / 2);        path.lineTo(xLength - dpToPx(12), mYOri + xyLineWidth / 2 + dpToPx(5));        canvas.drawPath(path, mXYPaint);        //绘制x轴刻度        for (int i = 0; i < mXData.size(); i++) {            float x = mXInit + interval * i;            if (x >= mXOri) {//只绘制从原点开始的区域                mXYTextPaint.setColor(xyTextColor);                canvas.drawLine(x, mYOri, x, mYOri - length, mXYPaint);                //绘制X轴文本                String text = mXData.get(i);                Rect rect = getTextBounds(text, mXYTextPaint);                if (i == selectIndex - 1) {                    mXYTextPaint.setColor(lineColor);                    canvas.drawText(text, 0, text.length(), x - rect.width() / 2, mYOri + xyLineWidth + dpToPx(2) + rect.height(), mXYTextPaint);                    canvas.drawRoundRect(x - xValueRect.width() / 2 - dpToPx(3), mYOri + xyLineWidth + dpToPx(1), x + xValueRect.width() / 2 + dpToPx(3), mYOri + xyLineWidth + dpToPx(2) + xValueRect.height() + dpToPx(2), dpToPx(2), dpToPx(2), mXYTextPaint);                } else {                    canvas.drawText(text, 0, text.length(), x - rect.width() / 2, mYOri + xyLineWidth + dpToPx(2) + rect.height(), mXYTextPaint);                }            }        }    }    private float startX;    private float startx;    @Override    public boolean onTouchEvent(MotionEvent event) {        if (isScrolling)            return super.onTouchEvent(event);            //当该view获得点击事件,就请求父控件不拦截事件        this.getParent().requestDisallowInterceptTouchEvent(true);        obtainVelocityTracker(event);        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                startX = event.getX();                startx = event.getX();                Log.e("XXXX", "down:" + startX + "");                break;            case MotionEvent.ACTION_MOVE:                //滑动距离小于等于8的时候任务为短距离滑动                //当前x轴的尺寸与设置的x轴间隔的距离之乘积大于 屏幕中的显示布局宽度与x轴七点之差时,开始移动                if (interval * mXData.size() > width - mXOri) {                    //获取滑动的距离                    float dis = event.getX() - startX;                    //重新赋值给startX                    startX = event.getX();                    //当前x原点距离与左右滑动的距离之和没有最小值大,则将当前x距离赋值为最小,以下相似                    if (mXInit + dis < minXInit) {                        mXInit = minXInit;                    } else if (mXInit + dis > maxXInit) {                        mXInit = maxXInit;                    } else {                        mXInit = mXInit + dis;                    }                    invalidate();                }                break;            case MotionEvent.ACTION_UP:                isShortSlide = Math.abs(event.getX() - startx) <= dpToPx(8);                clickAction(event);                scrollAfterActionUp();                this.getParent().requestDisallowInterceptTouchEvent(false);                recycleVelocityTracker();                break;            case MotionEvent.ACTION_CANCEL:                //增加这行代码防止与父类的滑动事件冲突                this.getParent().requestDisallowInterceptTouchEvent(false);                recycleVelocityTracker();                break;        }        return true;    }    //是否正在滑动    private boolean isScrolling = false;        private void scrollAfterActionUp() {        if (!isScroll)            return;        final float velocity = getVelocity();        float scrollLength = maxXInit - minXInit;        if (Math.abs(velocity) < 10000)            scrollLength = (maxXInit - minXInit) * Math.abs(velocity) / 10000;        ValueAnimator animator = ValueAnimator.ofFloat(0, scrollLength);        animator.setDuration((long) (scrollLength / (maxXInit - minXInit) * 1000));//时间最大为1000毫秒,此处使用比例进行换算        animator.setInterpolator(new DecelerateInterpolator());        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator valueAnimator) {                float value = (float) valueAnimator.getAnimatedValue();                if (velocity < 0 && mXInit > minXInit) {//向左滑动                    if (mXInit - value <= minXInit)                        mXInit = minXInit;                    else                        mXInit = mXInit - value;                } else if (velocity > 0 && mXInit < maxXInit) {//向右滑动                    if (mXInit + value >= maxXInit)                        mXInit = maxXInit;                    else                        mXInit = mXInit + value;                }                invalidate();            }        });        animator.addListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animator) {                isScrolling = true;            }            @Override            public void onAnimationEnd(Animator animator) {                isScrolling = false;            }            @Override            public void onAnimationCancel(Animator animator) {                isScrolling = false;            }            @Override            public void onAnimationRepeat(Animator animator) {            }        });        animator.start();    }        private float getVelocity() {        if (mTracker != null) {            mTracker.computeCurrentVelocity(1000);            return mTracker.getXVelocity();        }        return 0;    }        // 44  142  139    private void clickAction(MotionEvent event) {        int dp8 = dpToPx(8);        float eventX = event.getX();        float eventY = event.getY();        if (!isShortSlide) {            for (int i = 0; i < mXData.size(); i++) {                float x = mXInit + interval * i;                float start = mXOri;                if (x >= start + (mSelectMiddle - 1) * interval && x < start + mSelectMiddle * interval) {                    selectIndex = i + 1;                    invalidate();                }            }            return;        }        for (int i = 0; i < mXData.size(); i++) {            //节点            float x = mXInit + interval * i;            float y = mYOri - mYOri * (1 - 0.1f) * mSpinnerValue.get(mXData.get(i)) / mYData.get(mYData.size() - 1);            if (eventX >= x - dp8 && eventX <= x + dp8 &&                    eventY >= y - dp8 && eventY <= y + dp8 && selectIndex != i + 1) {//每个节点周围范围内都是可点击区域                selectIndex = i + 1;                invalidate();                return;            }            //X轴刻度            String text = mXData.get(i);            Rect rect = getTextBounds(text, mXYTextPaint);            x = mXInit + interval * i;            y = mYOri + xyLineWidth + dpToPx(2);            if (eventX >= x - rect.width() / 2 - dp8 && eventX <= x + rect.width() + dp8 / 2 &&                    eventY >= y - dp8 && eventY <= y + rect.height() + dp8 && selectIndex != i + 1) {                selectIndex = i + 1;                invalidate();                return;            }        }    }        private void obtainVelocityTracker(MotionEvent event) {        if (!isScroll)            return;        if (mTracker == null) {            mTracker = VelocityTracker.obtain();        }        mTracker.addMovement(event);    }        private void recycleVelocityTracker() {        if (mTracker != null) {            mTracker.recycle();            mTracker = null;        }    }        private int getSelectIndexFromShowType(int showPositionType) {        int visibleScale = (width - mXOri) / interval;        switch (showPositionType) {            case FIRST:                mSelectMiddle = 1;                return mSelectMiddle;            case MIDDLE:                if (mXData.size() <= visibleScale) {                    mSelectMiddle = middleIndex(mXData.size());                } else {                    mSelectMiddle = middleIndex(visibleScale);                }                return mSelectMiddle;  //屏幕可显示的刻度            case END:                if (mXData.size() <= visibleScale) {                    mSelectMiddle = mXData.size();                } else {                    mSelectMiddle = visibleScale;                }                return visibleScale;            default:                mSelectMiddle = 0;                return mSelectMiddle;        }    }    public void setValue(Map<String, Integer> value) {        this.mSpinnerValue = value;        invalidate();    }    public void setValue(Map<String, Integer> value, List<String> xValue, List<Integer> yValue) {        this.mSpinnerValue = value;        this.mXData = xValue;        this.mYData = yValue;        invalidate();    }    public Map<String, Integer> getValue() {        return mSpinnerValue;    }        private Rect getTextBounds(String text, Paint paint) {        Rect rect = new Rect();        paint.getTextBounds(text, 0, text.length(), rect);        return rect;    }        private int dpToPx(int dp) {        float density = getContext().getResources().getDisplayMetrics().density;        return (int) (dp * density + 0.5f * (dp >= 0 ? 1 : -1));    }        private int spToPx(int sp) {        float scaledDensity = getContext().getResources().getDisplayMetrics().scaledDensity;        return (int) (scaledDensity * sp + 0.5f * (sp >= 0 ? 1 : -1));    }        private static final int NULL_INDEX = -1;    public int getListItemMaxIndex(List<?> data) {        if (data == null || data.size() < 1) {            return NULL_INDEX;        }        int max = (data.get(0) + "").length();        for (int i = 0; i < data.size(); i++) {            String s = data.get(i) + "";            if (s.length() > max) {                return i;            }        }        return NULL_INDEX;    }    //获得在滑动结束的时候在屏幕内的点    private int middleIndex(int size) {        if (size % 2 == 0) {            return size / 2;        } else {            return size / 2 + 1;        }    }        //获取已知点的斜率 y = kx+b    private float getSlope(Point from, Point to) {        float k = (to.y - from.y) / (to.x - from.x);        Log.e("Point", "参数b:" + k);        return k;    }    //获取参数 b    private float getParams(Point from, Point to) {        float b = from.y - (getSlope(from, to) * from.x);        Log.e("Point", "参数b:" + b);        return b;    }    //根据两点间的坐标获取x轴的任意一个坐标x值,    private float getArbitrarilyX(Point from, Point to, int grade, int needGrade) {        //获得输入的新坐标        float x = ((to.x - from.x) * needGrade) / grade + from.x;        Log.e("Point", "x坐标值:" + x);        return x;    }    //获取坐标值    private Point getPoint(Point from, Point to, int grade, int needGrade) {        Point point = new Point();        point.setX(getArbitrarilyX(from, to, grade, needGrade));        float slope = getSlope(from, to);        point.setY(slope * point.x + getParams(from, to));        return point;    }    //获取绘制折线的点    private Point getSpinnerPoint(int valueIndex) {        float x = mXInit + interval * (valueIndex);        float y = mYOri - mYOri * (1 - 0.1f) * mSpinnerValue.get(mXData.get(valueIndex)) / mYData.get(mYData.size() - 1);        return new Point(x, y);    }    private class Point {        float x;        float y;        public Point() {        }        public float getX() {            return x;        }        public void setX(float x) {            this.x = x;        }        public float getY() {            return y;        }        public void setY(float y) {            this.y = y;        }        public Point(float x, float y) {            this.x = x;            this.y = y;        }        @Override        public String toString() {            return "Point{" +                    "x=" + x +                    ", y=" + y +                    '}';        }    }}

读到这里,这篇“android怎么实现可以滑动的平滑曲线图”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: android怎么实现可以滑动的平滑曲线图

本文链接: https://www.lsjlt.com/news/342305.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • android实现可以滑动的平滑曲线图
    本文实例为大家分享了android实现可以滑动的平滑曲线图的具体代码,供大家参考,具体内容如下 直接上代码,里面有详细注解 1 attr 属性编写    <...
    99+
    2024-04-02
  • android怎么实现可以滑动的平滑曲线图
    本文小编为大家详细介绍“android怎么实现可以滑动的平滑曲线图”,内容详细,步骤清晰,细节处理妥当,希望这篇“android怎么实现可以滑动的平滑曲线图”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1 att...
    99+
    2023-07-02
  • Python Matplotlib绘制动图平滑曲线
    目录绘制动图FuncAnimationArtistAnimation使用 scipy.ndimage.gaussian_filter1d() 高斯核类绘制平滑曲线使用 scipy.i...
    99+
    2024-04-02
  • Python曲线平滑的实现示例
    在编写测试程序的时候,由于数据帧数多的原因,导致生成的曲线图比较难看,如下图: 由于高频某些点的波动导致高频曲线非常难看,因此需要对曲线做平滑处理,让曲线过渡更平滑。对曲线进行平滑...
    99+
    2024-04-02
  • canvas怎么画出平滑的曲线
    这篇文章将为大家详细讲解有关canvas怎么画出平滑的曲线,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。背景概要相信大家平时在学习canvas 或 项目开发中使用canvas的时候应该都遇到过这样的需求:...
    99+
    2023-06-09
  • python 数据、曲线平滑处理——基于Numpy.convolve实现滑动平均滤波——详解
    文章目录 1 基于Numpy.convolve实现滑动平均滤波1.1 滑动平均概念1.2 滑动平均的数学原理1.3 语法1.4 滑动平均滤波示例 2 曲线平滑处理——Savitzky-Go...
    99+
    2023-09-18
    Numpy.convolve convolve滑动平均滤波 曲线平滑滤波 numpy python
  • Javascript中怎么生成平滑曲线
    这篇文章给大家介绍Javascript中怎么生成平滑曲线,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。前言平滑曲线生成是一个很实用的技术很多时候,我们都需要通过绘制一些折线,然后让计算机平滑的连接起来,先来看下最终效果...
    99+
    2023-06-20
  • Android SeekBar实现平滑滚动
    本文实例为大家分享了Android SeekBar实现平滑滚动的具体代码,供大家参考,具体内容如下 由于项目需要,SeekBar只需要三个档,但是如果只设置三个档会很难滑,看着也不好...
    99+
    2024-04-02
  • Android实现平滑翻动效果
    本文实例为大家分享了Android实现平滑翻动效果的具体代码,供大家参考,具体内容如下 效果 1.activity加implements implements GestureD...
    99+
    2024-04-02
  • canvas小画板之平滑曲线的实现案例
    小编给大家分享一下canvas小画板之平滑曲线的实现案例,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!功能需求项目需求:需要实现一个可以自由书写的小画板简单实现对...
    99+
    2023-06-09
  • android ScrollView怎么实现水平滑动回弹
    这篇文章主要介绍“android ScrollView怎么实现水平滑动回弹”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“android ScrollView怎么实现水平滑动回弹”...
    99+
    2023-06-30
  • 怎么使用Android原生WebView+Highcharts实现可左右滑动的折线图
    这篇文章主要介绍“怎么使用Android原生WebView+Highcharts实现可左右滑动的折线图”,在日常操作中,相信很多人在怎么使用Android原生WebView+Highcharts实现可左右滑动的折线图问题上存在疑惑,小编查阅...
    99+
    2023-06-30
  • 使用Android原生WebView+Highcharts实现可左右滑动的折线图
    目录前言开发的思路如下:(一)设计Android端的View层(二)设计与JS交互的方法(三)开发html以及js逻辑总结前言 今天的内容是使用Android原生webview配合H...
    99+
    2024-04-02
  • Android实现ViewFlipper图片动画滑动
    今天给大家实现的功能是类似于ViewFlipper的图片滑动的效果,供大家参考,具体内容如下 现在就直接上代码吧! 代码实例: 1、xml布局文件 <xml version="...
    99+
    2024-04-02
  • Android如何实现平滑翻动效果
    这篇文章给大家分享的是有关Android如何实现平滑翻动效果的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。具体内容如下效果activity加implementsimplements GestureDet...
    99+
    2023-06-14
  • android怎么实现界面滑动
    在Android中,可以使用ScrollView、RecyclerView、ViewPager等控件来实现界面滑动。下面分别介绍这些...
    99+
    2023-08-18
    android
  • Android怎么实现左右滑动切换图片
    这篇文章主要介绍“Android怎么实现左右滑动切换图片”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android怎么实现左右滑动切换图片”文章能帮助大家解决问题。简要说明本文采用ImageSwi...
    99+
    2023-06-30
  • matlab怎么画出光滑的曲线
    要画出光滑的曲线,可以使用MATLAB中的插值函数。下面是一种常用的方法:1. 首先,创建一个包含X和Y数据的向量,其中X是自变量,...
    99+
    2023-10-08
    matlab
  • SpringCloud服务的平滑上下线怎么实现
    这篇文章主要介绍“SpringCloud服务的平滑上下线怎么实现”,在日常操作中,相信很多人在SpringCloud服务的平滑上下线怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”SpringCloud...
    99+
    2023-06-02
  • 在WPF中怎么实现平滑滚动
    本篇内容介绍了“在WPF中怎么实现平滑滚动”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!WPF实现滚动条还是比较方便的,只要在控件外围加上S...
    99+
    2023-07-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作