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);
    }
    /**
     * 初始化
     *
     * @param context
     * @param attrs
     * @param defstyleattr
     */
    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);
    }
    /**
     * 绘制xy坐标
     */
    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();
    }
    /**
     * 获取速度
     *
     * @return
     */
    private float getvelocity() {
        if (mtracker != null) {
            mtracker.computecurrentvelocity(1000);
            return mtracker.getxvelocity();
        }
        return 0;
    }
    /**
     * 点击x轴坐标或者折线节点
     *  */
    // 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;
            }
        }
    }
    /**
     * 获取速度跟踪器
     *
     * @param event
     */
    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;
    }
    /**
     * 获取丈量文本的矩形
     *
     * @param text
     * @param paint
     * @return
     */
    private rect gettextbounds(string text, paint paint) {
        rect rect = new rect();
        paint.gettextbounds(text, 0, text.length(), rect);
        return rect;
    }
    /**
     * dp转化成为px
     *
     * @param dp
     * @return
     */
    private int dptopx(int dp) {
        float density = getcontext().getresources().getdisplaymetrics().density;
        return (int) (dp * density + 0.5f * (dp >= 0 ? 1 : -1));
    }
    /**
     * sp转化为px
     *
     * @param sp
     * @return
     */
    private int sptopx(int sp) {
        float scaleddensity = getcontext().getresources().getdisplaymetrics().scaleddensity;
        return (int) (scaleddensity * sp + 0.5f * (sp >= 0 ? 1 : -1));
    }
    /**
     * 获取集合中最长的index
     */
    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;
        }
    }
    /**
     * 根据两点坐标获取中间某个点
     *
     * @param from 坐标1
     * @param to   坐标2
     */
    //获取已知点的斜率 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 +
                    '}';
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

(0)
上一篇 2022年7月1日
下一篇 2022年7月1日

相关推荐