仿小米计步折线图

项目用到的技术点

  1. mvp简单应用
  2. 自定义控件使用

1. ScrollView的自定义
因为我们需要的是折线图可以左右滑动,但是我们需要实时计算滑动距离,所以需要自己定义,代码比较简单

/*
 * ScrollView并没有实现滚动监听,所以我们必须自行实现对ScrollView的监听,
 * 我们很自然的想到在onTouchEvent()方法中实现对滚动横轴进行监听
 */
public class MyScrollView extends HorizontalScrollView {

    private static final int SCROLL = 1;

    public MyScrollView(Context context) {
        super(context, null);
    }
    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
    }
    public MyScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    /**
     * 当前滚动状态
     */
    public enum ScrollType{
        IDLE,TOUCH_SCROLL,FLING    //IDLE 滚动停止  TOUCH_SCROLL 手指拖动滚动  FLING滚动
    }
    private ScrollType scrollType =  ScrollType.IDLE;

    private int lastScrollX;
    /** 
     * 用于用户手指离开MyScrollView的时候获取MyScrollView滚动的Y距离,然后回调给onScroll方法中 
     */  
    private Handler handler = new Handler(Looper.myLooper()) {

        public void handleMessage(android.os.Message msg) {
            if(msg.what == SCROLL) {
                int scrollX = MyScrollView.this.getScrollX();
                //此时的距离和记录下的距离不相等,在隔10毫秒给handler发送消息
                if (lastScrollX != scrollX) {   //还在滚动
                    lastScrollX = scrollX;
                    scrollType = ScrollType.FLING;
                    handler.sendEmptyMessageDelayed(SCROLL, 20);
                } else { //停止滚动
                    scrollType = ScrollType.IDLE;
                }
                if (onScrollListener != null) {
                    onScrollListener.onScrollChanged(scrollType);
                    onScrollListener.onScroll(scrollX);
                }
            }
        }
    };
    /** 
     * 重写onTouchEvent, 当用户的手在MyScrollView上面的时候, 
     * 直接将MyScrollView滑动的X方向距离回调给onScroll方法中,当用户抬起手的时候,MyScrollView可能还在滑动,所以当用户抬起手我们隔5毫秒给handler发送消息,在handler处理
     * MyScrollView滑动的距离 
     */ 
    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        switch(ev.getAction()){  
            case MotionEvent.ACTION_UP:
                if(onScrollListener != null){
                    onScrollListener.onScroll(lastScrollX = getScrollX());
                }
                handler.sendEmptyMessageDelayed(SCROLL, 20);
                break;
            case MotionEvent.ACTION_MOVE:
                scrollType = ScrollType.TOUCH_SCROLL;
                if(onScrollListener != null){
                    onScrollListener.onScrollChanged(scrollType);
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    /** 
     * 滚动的回调接口 
     */  
    public interface OnScrollListener{  
        //回调方法, 返回MyScrollView滑动的X方向距离
         void onScroll(int scrollX);
        //滑动监听
         void onScrollChanged(ScrollType scrollType);
    }

    private OnScrollListener onScrollListener;
    public void setOnScrollListener(OnScrollListener onScrollListener){
        this.onScrollListener = onScrollListener;
    }

    @Override
    protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
        return 0;
    }
}

2. 折线图控件的定义
从网上弄得一个改了改 还是挺复杂的赶脚,可以一起交流交流

package zlc.com.linechartdemo.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.graphics.drawable.NinePatchDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;

import zlc.com.linechartdemo.MyApplication;
import zlc.com.linechartdemo.R;
import zlc.com.linechartdemo.utils.DensityUtil;
import zlc.com.linechartdemo.utils.LogUtil;


/**
 * Created by zlc on 17/4/13.
 */
public class LineView extends View {

    private int mViewHeight;
    private boolean autoSetDataOfGird = true;
    private boolean autoSetGridWidth = true;
    private int dataOfAGird = 10;
    private int bottomTextHeight = 0;
    private ArrayList<String> bottomTextList = new ArrayList<>();
    private ArrayList<Float> dataList = new ArrayList<>();
    private ArrayList<Integer> xCoordinateList = new ArrayList<Integer>();
    private ArrayList<Dot> drawDotList = new ArrayList<>();
    private Paint bottomTextPaint = new Paint();
    private Paint ycoordTextPaint = new Paint();
    private int bottomTextDescent;

    //popup
    private Paint popupTextPaint = new Paint();
    private final int bottomTriangleHeight = 12;//底三角形的高度
    private boolean mShowYCoordinate = true;
    private int topLineLength = DensityUtil.dp2px(getContext(), 12); //顶线长度
    private int sideLineLength = DensityUtil.dp2px(getContext(),45)/3*2;// 右边间距和左边间距
    public int backgroundGridWidth = DensityUtil.dp2px(getContext(),55);//背景网格宽度,也是X轴宽度
    //Constants
    private final int popupTopPadding = DensityUtil.dp2px(getContext(),1); //popup顶部距离
    private final int popupBottomMargin = DensityUtil.dp2px(getContext(),5); // popup底部距离
    private final int bottomTextTopMargin = DensityUtil.sp2px(getContext(),1);//底部文本顶边
    private final  int DOT_INNER_CIR_RADIUS =   4; //小点和线大小
    private final int DOT_OUTER_CIR_RADIUS = DensityUtil.dp2px(getContext(),5); //点大小
    private final int MIN_TOP_LINE_LENGTH = DensityUtil.dp2px(getContext(),12);//背景线密度
    private final static int MIN_VERTICAL_GRID_NUM = 4;
    private final static int MIN_HORIZONTAL_GRID_NUM = 1;
    private final static int BOTTOM_TEXT_COLOR = Color.parseColor("#9B9A9B");  //X轴低
    private final int YCOORD_TEXT_LEFT_MARGIN = 0;//DensityUtil.dip2px(getContext(), 10);

    private boolean  showPopup = false;
    private  Dot selectedDot = null;

    public Canvas canvas;

    OnDataListening dataListening;

    int index;//当前选中的是第几个点

    /**
     * 曲线上总点数
     */
    private Point[] mPoints;
    public LineView(Context context){
        this(context,null);
    }

    public LineView(Context context, AttributeSet attrs){
        super(context, attrs);
        init();
    }

    private void init() {
        popupTextPaint.setAntiAlias(true);
        popupTextPaint.setColor(Color.WHITE);
        popupTextPaint.setTextSize(DensityUtil.sp2px(getContext(), 13));
        popupTextPaint.setStrokeWidth(5);
        popupTextPaint.setTextAlign(Paint.Align.CENTER);

        bottomTextPaint.setAntiAlias(true);
        bottomTextPaint.setTextSize(DensityUtil.sp2px(getContext(),12));
        bottomTextPaint.setTextAlign(Paint.Align.CENTER);
        bottomTextPaint.setStyle(Paint.Style.FILL);
        bottomTextPaint.setColor(BOTTOM_TEXT_COLOR);

        ycoordTextPaint.setAntiAlias(true);
        ycoordTextPaint.setTextSize(DensityUtil.sp2px(getContext(),12));
        ycoordTextPaint.setTextAlign(Paint.Align.LEFT);
        ycoordTextPaint.setStyle(Paint.Style.FILL);
        ycoordTextPaint.setColor(BOTTOM_TEXT_COLOR);
    }


    /**
     * 设置滚动接口
     * @param dataListening
     */
    public void setDataListening(OnDataListening dataListening){
        this.dataListening = dataListening;
    }

    private Runnable animator = new Runnable() {
        @Override
        public void run() {
            boolean needNewFrame = false;
            for(Dot dot : drawDotList){
                dot.update();
                if(!dot.isAtRest()){
                    needNewFrame = true;
                }
            }
            if (needNewFrame) {
                postDelayed(this, 0);
            }
            postInvalidate();
        }
    };

    /**
     * dataList will be reset when called is method.
     * @param bottomTextList The String ArrayList in the bottom.
     */
    public void setBottomTextList(ArrayList<String> bottomTextList){
        this.dataList = null;
        this.bottomTextList = bottomTextList;

        Rect r = new Rect();
        int longestWidth = 0;
        String longestStr = "";
        bottomTextDescent = 0;
        for(String s : bottomTextList){
            bottomTextPaint.getTextBounds(s,0,s.length(),r);
            if(bottomTextHeight < r.height()){
                bottomTextHeight = r.height();
            }
            if(autoSetGridWidth && (longestWidth<r.width())){
                longestWidth = r.width();
                longestStr = s;
            }
            if(bottomTextDescent<(Math.abs(r.bottom))){
                bottomTextDescent = Math.abs(r.bottom);
            }
        }

        if(autoSetGridWidth){
            if(backgroundGridWidth<longestWidth){
                backgroundGridWidth = longestWidth+(int)bottomTextPaint.measureText(longestStr,0,1);
            }

            if(sideLineLength<longestWidth/2){
                sideLineLength = longestWidth/2;
            }
        }
        refreshXCoordinateList(getHorizontalGridNum());
    }

    /**
     *
     * @param dataList The Integer ArrayList for showing,
     *                 dataList.size() must < bottomTextList.size()
     */
    public void setDataList(ArrayList<Float> dataList){
        this.dataList = dataList;
        if(dataList.size() > bottomTextList.size()){
            throw new RuntimeException("dacer.LineView error:" +
                    " dataList.size() > bottomTextList.size() !!!");
        }
        if(autoSetDataOfGird){
            float biggestData = 0;
            for(Float i:dataList){
                if(biggestData<i){
                    biggestData = i;
                }
            }
            dataOfAGird = 1;
            while(biggestData/10 > dataOfAGird){
                dataOfAGird *= 10;
            }
        }

        refreshAfterDataChanged();
        setMinimumWidth(0); // It can help the LineView reset the Width,它可以帮助LineView重置宽度,
        // I don't know the better way..我不知道更好的方法. .
        postInvalidate();
    }

    private void refreshAfterDataChanged(){
        float verticalGridNum = getVerticalGridlNum();
        refreshTopLineLength(verticalGridNum);
        refreshDrawDotList(verticalGridNum);
    }

    private float getVerticalGridlNum(){
        float verticalGridNum = MIN_VERTICAL_GRID_NUM;
        if(dataList != null && !dataList.isEmpty()){
            for(Float integer:dataList){
                if(verticalGridNum<(integer+1)){
                    verticalGridNum = integer+1;
                }
            }
        }
        return verticalGridNum;
    }

    private int getHorizontalGridNum(){
        int horizontalGridNum = bottomTextList.size()-1;
        return (horizontalGridNum <= MIN_HORIZONTAL_GRID_NUM) ? MIN_HORIZONTAL_GRID_NUM : horizontalGridNum;
    }

    private void refreshXCoordinateList(int horizontalGridNum){
        xCoordinateList.clear();
        for(int i=0;i<(horizontalGridNum+1);i++){
            xCoordinateList.add(sideLineLength + backgroundGridWidth*i);
        }
    }

    private void refreshDrawDotList(float verticalGridNum){
        if(dataList != null && !dataList.isEmpty()){
            int drawDotSize = drawDotList.size();
            for(int i=0;i< dataList.size();i++){
                float x = xCoordinateList.get(i);
                //计算Y的值(方法1)
                int t2 = DensityUtil.dp2px(MyApplication.getContext(),60);//90  180
                int t88 = DensityUtil.dp2px(MyApplication.getContext(),29);//40  80
                float t1 = dataList.get(i);
                int y =  (int)t1*t2/(int)verticalGridNum;
                y = t2-y+t88;

                if(dataList.size()==1){ //如果只有一个数据时居中
                    y =  DensityUtil.dp2px(MyApplication.getContext(),50);//90  180
                }

                if(i > drawDotSize-1){
                    drawDotList.add(new Dot(x, 0, x, y, dataList.get(i)));
                }else{
                    drawDotList.set(i, drawDotList.get(i).setTargetData(x,y,dataList.get(i)));
                }
            }
            int temp = drawDotList.size() - dataList.size();
            for(int i=0; i < temp; i++){
                drawDotList.remove(drawDotList.size()-1);
            }
        }
        removeCallbacks(animator);
        post(animator);
    }

    private void refreshTopLineLength(float verticalGridNum){
        if((mViewHeight-topLineLength-bottomTextHeight-bottomTextTopMargin)/
                (verticalGridNum+2)<getPopupHeight()){
            topLineLength = getPopupHeight()+DOT_OUTER_CIR_RADIUS+DOT_INNER_CIR_RADIUS+2;
        }else{
            topLineLength = MIN_TOP_LINE_LENGTH;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        this.canvas = canvas;
        if (mStyle == Linestyle.Curve) {
            drawScrollLine(canvas);
        }else{
            drawLines(canvas);
        }

        for(Dot dot : drawDotList){
            dot.select = false;
        }

        if(showPopup && selectedDot != null){ 画选中的点
            selectedDot.select = true;

            int i = (int) selectedDot.data;
            float i2 = selectedDot.data-i;

         //   LogUtil.e("i2===",i2+"");
            String value = "";
            if(i2>0){
                value= String.valueOf(selectedDot.data);
            }else{
                value = String.valueOf(i);
            }
            drawPopup(canvas,value, selectedDot.getPoint());
        }
        //画全部点
        drawDots(canvas);

        if(dataListening!=null){
            dataListening.getData(bottomTextList.get(index),dataList.get(index),index);
        }
    }

    /**
     *
     * @param canvas  The canvas you need to draw on.
     * @param point   The Point consists of the x y coordinates from left bottom to right top.
     *                Like is              3
     *                2
     *                1
     *                0 1 2 3 4 5
     */
    private void drawPopup(Canvas canvas, String num, Point point){

        boolean singularNum = (num.length() == 1);
        int sidePadding = DensityUtil.dp2px(getContext(),singularNum? 8:5);
        int x = point.x;
        if(mShowYCoordinate == true)
            x += YCOORD_TEXT_LEFT_MARGIN;

        int y = point.y-DensityUtil.dp2px(getContext(),5);
        Rect popupTextRect = new Rect();
        popupTextPaint.getTextBounds(num,0,num.length(),popupTextRect);

        int left= x-popupTextRect.width()/2-sidePadding;
        int right =  x + popupTextRect.width()/2+sidePadding;
        int top;
        int bottom ;

        top = y - popupTextRect.height()-bottomTriangleHeight-popupTopPadding*2-popupBottomMargin;
        bottom = y+popupTopPadding-popupBottomMargin;

        //矩形的位置  画图片
        Rect r = new Rect(left,top, right, bottom);
        Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.kuang);
        byte chunk[] = bmp.getNinePatchChunk();
        NinePatchDrawable popup = new NinePatchDrawable(bmp, chunk, new Rect(), null);
        popup.setBounds(r);
        popup.draw(canvas);
        canvas.drawText(num, x, y-bottomTriangleHeight-popupBottomMargin, popupTextPaint);
    }

    private int getPopupHeight(){
        Rect popupTextRect = new Rect();
        popupTextPaint.getTextBounds("9",0,1,popupTextRect);
        Rect r = new Rect(-popupTextRect.width()/2,
                - popupTextRect.height()-bottomTriangleHeight-popupTopPadding*2-popupBottomMargin,
                + popupTextRect.width()/2,
                +popupTopPadding-popupBottomMargin);
        return r.height();
    }

    private void drawDots(Canvas canvas){
        Paint bigCirPaint = new Paint();
        bigCirPaint.setAntiAlias(true);
        bigCirPaint.setColor(Color.parseColor("#FFFFFF"));//白点
        Paint smallCirPaint = new Paint(bigCirPaint);
        smallCirPaint.setColor(Color.parseColor("#85c942")); //小点
        if(drawDotList!=null && !drawDotList.isEmpty()){
            LogUtil.e("多少个点",drawDotList.size()+"");
            for(Dot dot : drawDotList){
                float x = dot.x;
                if(mShowYCoordinate == true)
                    x += YCOORD_TEXT_LEFT_MARGIN;
                int dotSize=  DOT_INNER_CIR_RADIUS;
                if(dot.select){
                    dotSize = DOT_OUTER_CIR_RADIUS;
                }
                canvas.drawCircle(x,dot.y,DOT_OUTER_CIR_RADIUS,bigCirPaint);
                canvas.drawCircle(x,dot.y,dotSize,smallCirPaint);
            }
        }
    }


    //画折线
    private void drawLines(Canvas canvas){
        Paint linePaint = new Paint();
        linePaint.setAntiAlias(true);
        linePaint.setColor(Color.parseColor("#85c942"));
        linePaint.setStrokeWidth(DOT_INNER_CIR_RADIUS);
        for(int i=0; i< drawDotList.size()-1; i++){
            float x1 = drawDotList.get(i).x;
            float x2 = drawDotList.get(i+1).x;
            if(mShowYCoordinate == true) {
                x1 += YCOORD_TEXT_LEFT_MARGIN;
                x2 += YCOORD_TEXT_LEFT_MARGIN;
            }
            canvas.drawLine(x1,
                    drawDotList.get(i).y,
                    x2,
                    drawDotList.get(i+1).y,
                    linePaint);
        }
    }

    //画曲线
    private void drawScrollLine(Canvas canvas){
        mPoints = getPoints();
        Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.parseColor("#85c942"));
        mPaint.setStrokeWidth(DOT_INNER_CIR_RADIUS);
        mPaint.setStyle(Paint.Style.STROKE);

        Point startp;
        Point endp;
        for (int i = 0; i < mPoints.length - 1; i++)
        {
            startp = mPoints[i];
            endp = mPoints[i + 1];
            int wt = (startp.x + endp.x) / 2;
            Point p3 = new Point();
            p3.y = startp.y;
            p3.x = wt;
            Path path = new Path();
            path.moveTo(startp.x, startp.y);
            path.cubicTo(p3.x, p3.y, p3.x, endp.y, endp.x, endp.y); // (x1,y1) 为控制点,(x2,y2)为控制点,(x3,y3) 为结束点。
            canvas.drawPath(path, mPaint);
        }
    }

    private Point[] getPoints()
    {
        Point[] points = new Point[dataList.size()];
        for (int i = 0; i < dataList.size(); i++) {
            points[i] = new Point((int)drawDotList.get(i).x,(int)drawDotList.get(i).y);
        }
        return points;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int mViewWidth = measureWidth(widthMeasureSpec);
        mViewHeight = measureHeight(heightMeasureSpec);
        setMeasuredDimension(mViewWidth,mViewHeight);
    }

    private int measureWidth(int measureSpec){
        int horizontalGridNum = getHorizontalGridNum();
        int preferred = backgroundGridWidth * horizontalGridNum + sideLineLength*2;
        return getMeasurement(measureSpec, preferred);
    }

    private int measureHeight(int measureSpec){
        int preferred = 0;
        return getMeasurement(measureSpec, preferred);
    }

    private int getMeasurement(int measureSpec, int preferred){
        int specSize = MeasureSpec.getSize(measureSpec);
        int measurement;
        switch(MeasureSpec.getMode(measureSpec)){
            case MeasureSpec.EXACTLY:
                measurement = specSize;
                break;
            case MeasureSpec.AT_MOST:
                measurement = Math.min(preferred, specSize);
                break;
            default:
                measurement = preferred;
                break;
        }
        return measurement;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        //触摸时先隐藏所有的点
        Point point = new Point();
        point.x = (int) event.getX();
        point.y = (int) event.getY();
        Region r = new Region();
        int width = backgroundGridWidth / 2;
        if(drawDotList != null && !drawDotList.isEmpty()){

            for (int i = 0; i <drawDotList.size();i++){
                Dot dot = drawDotList.get(i);
                r.set((int)dot.x-width,(int)dot.y- width,(int)dot.x+width,(int)dot.y+width);

                if (r.contains(point.x,point.y) && event.getAction() == MotionEvent.ACTION_DOWN){
                    selectedDot = dot;
                    LogUtil.e("ACTION_DOWN","点按下");
                }else if (event.getAction() == MotionEvent.ACTION_UP){
                    if (r.contains(point.x,point.y)){
                        showPopup = true;
                        LogUtil.e("ACTION_UP","点抬起");
                        index = i;
                    }
                }
            }
        }
        if (event.getAction() == MotionEvent.ACTION_UP){
            postInvalidate();
        }
        return true;
    }


    private float updateSelf(float origin, float target, float velocity){
        if (origin < target) {
            origin += velocity;
        } else if (origin > target){
            origin-= velocity;
        }
        if(Math.abs(target-origin)<velocity){
            origin = target;
        }
        return origin;
    }

    public class Dot{
        float x;
        float y;
        float data;
        float targetX;
        float targetY;
        float velocity = DensityUtil.dp2px(getContext(),20);
        public boolean select = false;  //有没有被选中 (自行加的)
        Dot(float x,float y,float targetX,float targetY,float data){
            this.x = x;
            this.y = y;
            setTargetData(targetX, targetY,data);
        }
        Point getPoint(){
            return new Point((int)x,(int)y);
        }
        Dot setTargetData(float targetX,float targetY,float data){
            this.targetX = targetX;
            this.targetY = targetY;
            this.data = data;
            return this;
        }

        boolean isAtRest(){
            return (x == targetX) && ( y == targetY);
        }

        void update(){
            x = updateSelf(x, targetX, velocity);
            y = updateSelf(y, targetY, velocity);
        }
    }


    //返回每个点的距离
    public int getDistance(){
        return backgroundGridWidth;
    }

    //返回点列表
    public ArrayList<Dot> getDrawDotList(){
        return  drawDotList;
    }

    //画某一个点
    public void drawPopup(int index){
        this.index = index;
        selectedDot = drawDotList.get(index);
        showPopup = true;
        postInvalidate();
    }

    public interface  OnDataListening{
        void getData(String time,Float data,int index);
    }

    private Linestyle mStyle = Linestyle.Line;
    enum Linestyle {
        Line,// 折线
        Curve//曲线
    }
}

3. 折线图数据处理

package zlc.com.linechartdemo.mvp;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

import zlc.com.linechartdemo.adapter.HealthDataAdapter;
import zlc.com.linechartdemo.utils.JsonUtil;
import zlc.com.linechartdemo.utils.LogUtil;
import zlc.com.linechartdemo.info.MetaListInfo;
import zlc.com.linechartdemo.R;
import zlc.com.linechartdemo.ui.TrendFragment;
import zlc.com.linechartdemo.info.ChartDataInfo;
import zlc.com.linechartdemo.utils.ParamsUtil;

/**
 * @author : zlc
 * @date : On 2017/3/22
 * @eamil : zlc921022@163.com
 */
public class ChartPresentImpl implements ChartPresenter,HealthDataAdapter.OnItemClickLitener{

    private FragmentActivity mActivity;
    public List<ChartDataInfo.BodyBean> metaList;
    public MetaListInfo datalist;
    public TrendFragment fragment;
    public String enName;
    public String cName;
    private RecyclerView id_recycle_data;
    private HealthDataAdapter mDataAdapter;
    private Handler handler;
    public  static  final int DATA_REFRESH = 3;  //刷新走势图数量
    public  static  final int MOVEMENTS_REFRESH = 4;  //刷新文字

    public ChartPresentImpl(Handler handler,FragmentActivity activity){

        this.handler = handler;
        this.mActivity = activity;
        metaList = new ArrayList<>();
        datalist = new MetaListInfo();
        datalist.nameList = new ArrayList<>();
        datalist.valueList = new ArrayList<>();
        datalist.unitList = new ArrayList<>();
        datalist.showList = new ArrayList<>();
    }

    public void initView(RecyclerView id_recycle_data) {
        this.id_recycle_data = id_recycle_data;
    }

    @Override
    public void chartInfo() {
        ChartDataInfo info = JsonUtil.parseJsonToBean(ParamsUtil.getChartInfo(), ChartDataInfo.class);
        if(info==null){
            LogUtil.e("折线图info","JSON解析失败");
        }else if("1".equals(info.status) && info.body!=null && info.body.size()>0){
            setChartInfo(info);
        }else{
            LogUtil.e("折线图info",info.msg);
        }
    }


    @Override
    public void setChartInfo(ChartDataInfo info) {

        metaList.clear();
        metaList.addAll(info.body);
        LogUtil.e("有多少项数据",metaList.size()+"");
        if(metaList!=null && metaList.size()>0){
            setChartAdapter();       //给RecycleView设置Adapter
            setChartFragment(info);  //给折线图设置Fragment
        }else{
            LogUtil.e("setChartInfo","metaList没有数据");
        }
    }

    //给RecycleView设置Adapter
    private void setChartAdapter() {
        datalist.clear();
        for (int i = 0; i < metaList.size();i++) {
            if (i == 0) {
                datalist.showList.add(true);
                enName = metaList.get(0).enName;
                cName = metaList.get(0).name;
            } else {
                datalist.showList.add(false);
            }
            String unit = metaList.get(i).unit;
            String name = metaList.get(i).name;
            this.datalist.nameList.add(name);
            this.datalist.unitList.add(unit);
            LogUtil.e("name", name);
            LogUtil.e("unit", unit);

            List<ChartDataInfo.DatalistBean> datalistBeen = metaList.get(i).datalist;
            String value = datalistBeen != null && datalistBeen.size() > 0 ? datalistBeen.get(0).value : "-";
            this.datalist.valueList.add(value);
        }
        //添加尾部数据
        datalist.addFootData();
        id_recycle_data.setLayoutManager( new LinearLayoutManager(mActivity,LinearLayoutManager.HORIZONTAL,false));
        mDataAdapter = new HealthDataAdapter(mActivity,datalist);
        id_recycle_data.setAdapter(mDataAdapter);
    }

    //给折线图设置Fragment
    private void setChartFragment(ChartDataInfo info) {
        FragmentManager fm = mActivity.getSupportFragmentManager();
        if(fm==null || fm.isDestroyed() || mActivity.isDestroyed()) {
            LogUtil.e("setChartInfo","非法性操作异常");
            return;
        }
        if(fragment==null){
            fragment = new TrendFragment();
            Bundle bundle = new Bundle();
            bundle.putString("enName", enName);
            bundle.putParcelableArrayList("BodyBean",info.body);
            fragment.setArguments(bundle);
            LogUtil.e("showFragment","折线图Fragment没有添加");
            fm.beginTransaction()
                    .add(R.id.fl_member_data, fragment)
                    .show(fragment)
                    .commitAllowingStateLoss();
        }else{
            if(fragment.isHidden())
                fm.beginTransaction().show(fragment).commitAllowingStateLoss();
            fragment.refreshData(info.body,enName);
        }
        mDataAdapter.setOnItemClickLitener(this);
    }


    //根据时间刷新数据
    public  void updateAdapter(String time){
        LogUtil.e("要刷新的时间",time);
        if(metaList!=null&&metaList.size()>0){
            datalist.valueList.clear();
            for (int i=0;i<metaList.size();i++){
                ChartDataInfo.BodyBean metaListBean = metaList.get(i);
                List<ChartDataInfo.DatalistBean> dlist = metaListBean.datalist;
                String value = "-";
                if(dlist==null||dlist.size()==0){
                    value  = "-";
                }else{
                    for (int j = 0;j<dlist.size();j++){
                        ChartDataInfo.DatalistBean bean = dlist.get(j);
                        if(bean.date.equals(time)){
                            value  = bean.value;
                            LogUtil.e("要加入的数据",bean.value);
                            break;
                        }
                    }
                }
                datalist.valueList.add(value);
            }
            mDataAdapter.notifyDataSetChanged();
        }
    }

    @Override
    public void onItemClick(HealthDataAdapter.ViewHolder view, int position) {
        LogUtil.e("position==",position+"");
        if(position >= metaList.size()){
            LogUtil.e("尾部==",position+"");
            return;
        }
        enName = metaList.get(position).enName;
        cName = datalist.nameList.get(position) ;
        for (int i = 0; i < metaList.size(); i++) {
            if(i == position){
                datalist.showList.set(i,true);
            }else{
                datalist.showList.set(i,false);
            }
        }
        mDataAdapter.notifyDataSetChanged();
        LogUtil.e("enName=",enName);

        Message msg = handler.obtainMessage();
        msg.what = MOVEMENTS_REFRESH ;
        Bundle bundle= new Bundle();
        bundle.putString("enName",enName);
        bundle.putString("name",cName);
        msg.setData(bundle);
        handler.sendMessage(msg);
        showFragment(enName);
    }

    //显示折线图Fragment
    private void showFragment(String enName){
        if(!fragment.isAdded()){
            LogUtil.e("showFragment","折线图Fragment没有添加");
        }else{
            LogUtil.e("showFragment","Fragment添加过了");
            fragment.refresh(enName);
        }
        fragment.setOnTrendDataListening(new TrendFragment.OnTrendDataListening() {
            @Override
            public void getData(String time, Float data) {
                LogUtil.e("showFragment_time",time);
                LogUtil.e("showFragment_data",data.toString());
                Message msg = new Message();
                msg.what = DATA_REFRESH ;
                Bundle bundle= new Bundle();
                bundle.putString("time",time);
                bundle.putString("data",String.valueOf(data));
                msg.setData(bundle);
                handler.sendMessage(msg);
            }
        });
    }
}

4. 折线图界面处理

package zlc.com.linechartdemo.ui;

import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.widget.RelativeLayout;


import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import zlc.com.linechartdemo.R;
import zlc.com.linechartdemo.info.ChartDataInfo;
import zlc.com.linechartdemo.utils.DensityUtil;
import zlc.com.linechartdemo.utils.LogUtil;
import zlc.com.linechartdemo.utils.ScreenUtil;
import zlc.com.linechartdemo.view.LineView;
import zlc.com.linechartdemo.view.MyScrollView;


public class TrendFragment extends BaseFragment implements MyScrollView.OnScrollListener{

    LineView lineView;
    MyScrollView scrollView;
    private Handler mHandler = new Handler(Looper.myLooper());
    String enName = "";  //要刷新数据的点
    int shieldingWidth = -8;//屏幕宽度
    int   middlePointNum = 3;
    int distance = -8; //每个点的距离
    int point_num = -8;//每屏有多少个点
    DecimalFormat df;
    ArrayList<Float> dataList  = new ArrayList<>();//放数据
    ArrayList<String> strList = new ArrayList<>();//放时间
    private ArrayList<ChartDataInfo.BodyBean> bodyBeanList;

    @Override
    protected View initView() {

        view = View.inflate(mActivity, R.layout.fragment_trend,null);
        lineView = findView(R.id.line_view);
        scrollView = findView(R.id.scrollView);
        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) lineView.getLayoutParams();
        int margin = ScreenUtil.getScreenWidth(mActivity) / 2 - DensityUtil.dp2px(mActivity, 30);
        lp.setMargins(margin,0,margin,0);
        lineView.setLayoutParams(lp);
        return view;
    }

    @Override
    protected void initData() {

        bodyBeanList = getArguments().getParcelableArrayList("BodyBean");
        enName = getArguments().getString("enName");
        getChartData(enName);
    }


    @Override
    protected void initListener() {
        super.initListener();
        df   =new DecimalFormat("#.00");
        distance = lineView.getDistance();
        shieldingWidth  = ScreenUtil.getScreenWidth(mActivity);
        point_num  = shieldingWidth/distance+1;
        //滑动监听
        scrollView.setOnScrollListener(this);
    }

    //获取折线图数据
    private void getChartData(String enName){
        this.enName = enName;
        if(bodyBeanList==null || bodyBeanList.isEmpty()){
            LogUtil.e("getChartData","列表没东西");
        }else{
            LogUtil.e("getChartData 折线图数据大小",bodyBeanList.size()+"");
            for (ChartDataInfo.BodyBean bean : bodyBeanList) {
                if(null !=bean && bean.enName.equals(enName)){
                    LogUtil.e("getChartData","找到要刷新的那项=="+enName);
                    setChartData(bean.datalist);
                    return;
                }
            }
        }
    }

    //设置折线图数据
    private void  setChartData(List<ChartDataInfo.DatalistBean> datalist){
        scrollView.setVisibility(View.INVISIBLE);
        dataList.clear();
        strList.clear();
        if(datalist==null || datalist.size()==0 ){  //没数据
            scrollView.setVisibility(View.INVISIBLE);
            LogUtil.e("setChartData","chartInfo没数据");
            if(onTrendDataListening!=null){
                onTrendDataListening.getData("-",0f);
            }
        }else{
            LogUtil.e("setChartData 有几条数据",datalist.size()+"");
            final int width = datalist.size() == 1 ? 0 : scrollView.getChildAt(0).getMeasuredWidth();
            mHandler.postDelayed((new Runnable() {
                @Override
                public void run() {
                    scrollView.scrollTo(width,0);//滑动到最后面
                    scrollView.setVisibility(View.VISIBLE);
                }
            }),200);
            //
            for (int i = datalist.size()-1;i >= 0; i--){
                ChartDataInfo.DatalistBean datalistBean = datalist.get(i);
                dataList.add(Float.valueOf(datalistBean.value));
                strList.add(datalistBean.date);
            }

            lineView.setBottomTextList(strList);
            lineView.setDataList(dataList);
            lineView.drawPopup(dataList.size() - 1);//默认选中最后一个
            //数据监听
            lineView.setDataListening(new LineView.OnDataListening() {
                @Override
                public void getData(String time, Float data,final  int index) {
                    if(onTrendDataListening!=null){
                        onTrendDataListening.getData(time,data);
                    }
                    LogUtil.e("setChartData 选中的是第几个==",index+"");
                    mHandler.postDelayed((new Runnable() {
                        @Override public void run() {
                            LogUtil.e("setChartData 前distance===",distance+"");
                            distance = lineView.getDistance();
                            int x = distance * index ;
                            LogUtil.e("setChartData 后distance===",distance+"");
                            LogUtil.e("setChartData index===",index+"");
                            LogUtil.e("setChartData width===",scrollView.getChildAt(0).getMeasuredWidth()+"");
                            scrollView.smoothScrollTo(x,0);//滑动
                        }
                    }),50);
                }
            });
        }
    }

    public void refresh(String enName){
        LogUtil.e("要刷新的数",enName);
        if(this.enName.equals(enName)){
            return;
        }
        getChartData(enName);
    }

    public void refreshData(ArrayList<ChartDataInfo.BodyBean> bodyBeanList, String enName ){

        this.bodyBeanList = bodyBeanList;
        this.enName = enName;
        if(bodyBeanList!=null && bodyBeanList.size()>0){
            LogUtil.e("refreshData","刷新数据");
            getChartData(enName);
        }else{
            LogUtil.e("refreshData","没东西刷");
        }

    }

    @Override
    public void onScroll(int scrollX) {
        int leif = DensityUtil.getScreenWidth(mActivity) / 2;
        double hua = (double)(scrollX-leif) / (double) distance;
        if(hua>0){
            hua +=0.5;
        }else{
            hua -=0.5;
        }
        middlePointNum = (int)hua + point_num/2; //当前滑出屏的是第几个 + 一屏个数的中间数 == 当前的中间点
    }

    @Override
    public void onScrollChanged(MyScrollView.ScrollType scrollType) {
        switch (scrollType){
            case IDLE:
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //计算出当前一屏中最中间的那一个点,并显示出来
                        LogUtil.e("开始画点啦",middlePointNum+"");
                        if(middlePointNum >= lineView.getDrawDotList().size()){
                            middlePointNum = lineView.getDrawDotList().size()-1;
                        }else if(middlePointNum < 0){
                            middlePointNum = 0;
                        }
                        LogUtil.e("真正画点啦",middlePointNum+"");
                        lineView.drawPopup(middlePointNum);
                    }
                },50);
                break;
            default:
                break;
        }
    }

    public  interface  OnTrendDataListening{
        void getData(String time,Float data);
    }
    private OnTrendDataListening onTrendDataListening;
    public void setOnTrendDataListening(OnTrendDataListening onTrendDataListening){
        this.onTrendDataListening = onTrendDataListening;
    }
}

5. 联系方式

qq:1509815887
email : zlc921022@163.com
phone : 18684732678

6. 下载地址

点击去下载

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值