仿微信运动步数折线统计图

完整代码如下

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;

import com.ast.smartlighter.R;
import com.ast.smartlighter.utils.UIUtils;

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

//仿微信运动步数折线分布图
public class WXSportStatistics extends View implements OnTouchListener {

    float mHigh = 0;
    float Width = 0;
    List<String> listValue = new ArrayList<String>();
    List<RectF> listRectF = new ArrayList<RectF>();
    List<String> listDAY = new ArrayList<String>();
    boolean isKcal = false;
    Float MaxValue = 0f;

    private Paint paintbg;
    private Paint paintCircle;
    private Paint paintLine;
    private Paint paint;
    private Paint paintText;
    private Paint paintText2;

    private Path path;
    Shader mShader;
    int color_w = Color.argb(200, 255, 255, 255);

    int CircleR = 5;
    //4fd4d0
    int bottomH = 0;//距离底部高度,给文字显示用的

    int topH = 0;//距离顶部部高度,给选中后的文字显示用的

    Context context;

    public int select = -1;
    public int selectbottom = -1;

    public WXSportStatistics(Context context, AttributeSet attrs) {
        super(context, attrs);
        CircleR = UIUtils.dip2px(context, 3);
        bottomH = UIUtils.dip2px(context, 12);
        topH = UIUtils.dip2px(context, 16);

        this.context = context;
        initView();
    }

    public WXSportStatistics(Context context) {
        super(context);
        CircleR = UIUtils.dip2px(context, 3);
        bottomH = UIUtils.dip2px(context, 12);
        topH = UIUtils.dip2px(context, 16);

        this.context = context;
        initView();
    }

    private void initView() {
        setOnTouchListener(this);

        mHigh = getHeight();
        Width = getWidth();

        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStrokeWidth(2);
        paint.setColor(Color.rgb(255, 255, 255));
        paint.setStyle(Paint.Style.FILL);


        paintText = new Paint();
        paintText.setAntiAlias(true);
        paintText.setStrokeWidth(4);
        paintText.setColor(getResources().getColor(R.color.white));//Color.rgb(255, 255, 255));
        paintText.setStyle(Paint.Style.FILL);
        paintText.setTextSize(16);


        paintText2 = new Paint();
        paintText2.setAntiAlias(true);
        paintText2.setStrokeWidth(4);
        paintText2.setColor(Color.WHITE);//.rgb(33, 35, 59));
        paintText2.setStyle(Paint.Style.FILL);
        paintText2.setTextSize(20);


        paintLine = new Paint();
        paintLine.setAntiAlias(true);
        paintLine.setStrokeWidth(1);
        paintLine.setColor(Color.rgb(255, 255, 255));

        paintLine.setStyle(Paint.Style.STROKE);
        PathEffect effects = new DashPathEffect(new float[]{6, 4, 6, 4}, 1);
        paintLine.setPathEffect(effects);

        paintbg = new Paint();
        paintbg.setAntiAlias(true);
        paintbg.setStrokeWidth(0);
        paintbg.setColor(Color.rgb(255, 255, 255));
        paintbg.setStyle(Paint.Style.FILL);

        paintCircle = new Paint();
        paintCircle.setAntiAlias(true);
        paintCircle.setStrokeWidth(2);
        paintCircle.setStyle(Paint.Style.FILL);
        paintCircle.setColor(getResources().getColor(R.color.white));

        path = new Path();
        mShader = new LinearGradient(0, 0, 0, getHeight(), new int[]{color_w,
                getResources().getColor(R.color.transparency)}, null, Shader.TileMode.CLAMP);
        paintbg.setShader(mShader);
    }

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

        float High = mHigh - bottomH;

        if (listValue != null && listValue.size() != 0 && listDAY != null && listDAY.size() != 0) {

            for (int i = 0; i < listValue.size(); i++) {
                float h = High - High * Float.parseFloat(listValue.get(i)) / MaxValue;


                h = h + topH;
                float w = (float) (Width / listValue.size() * (i + 0.5));

                if (High * Float.parseFloat(listValue.get(i)) / MaxValue < CircleR) {
                    h = High - CircleR - 1;
                }
                if (h < CircleR) {
                    h = CircleR + 1;
                }
                if (h > High - CircleR) {
                    h = High - CircleR + 1;
                }
                if (MaxValue == 0)
                    h = High - CircleR - 1;
                if (i == 0) {
                    path.moveTo(w, h);
                } else if (i == listValue.size() - 1) {

                    path.lineTo(w, h);
                    path.lineTo(w, High);

                    path.lineTo((float) (Width / listValue.size() * 0.5), High);

                    path.lineTo((float) (Width / listValue.size() * 0.5),
                            High - High * Float.parseFloat(listValue.get(0)) / MaxValue);

                    path.close();

                    canvas.drawPath(path, paintbg);

                } else {
                    path.lineTo(w, h);
                }

                if (i != listValue.size() - 1) {
                    float stopY = High - High * Float.parseFloat(listValue.get(i + 1)) / MaxValue + topH;


                    float stopX = (float) (Width / listValue.size() * (i + 1.5));


                    if (High * Float.parseFloat(listValue.get(i + 1)) / MaxValue < CircleR) {
                        stopY = High - CircleR - 1;
                    }
                    if (stopY < CircleR) {
                        stopY = CircleR + 1;
                    }
                    if (MaxValue == 0)
                        stopY = High - CircleR - 1;

                    if (stopY > High - CircleR) {
                        stopY = High - CircleR + 1;
                    }


                    canvas.drawLine(w, h, stopX, stopY, paint);
                }
            }
            listRectF.clear();

            for (int i = 0; i < listDAY.size(); i++) {
                float w = (float) (Width / listValue.size() * (i + 0.5));
                String day = listDAY.get(i);
                if (listDAY.size() == 7) {
                    paintText.setTextSize(UIUtils.dip2px(getContext(), 10));
                    paintText2.setTextSize(UIUtils.dip2px(getContext(), 10));
                    int width = getTextWidth(paintText, day);

                    if (selectbottom == i) {

                        canvas.drawText(day, w - width / 2, mHigh - 2, paintText2);

                        selectbottom = -1;
                    } else {

                        canvas.drawText(day, w - width / 2, mHigh - 2, paintText);
                    }
                } else if (listDAY.size() == 12) {
                    paintText.setTextSize(UIUtils.dip2px(getContext(), 10));
                    paintText2.setTextSize(UIUtils.dip2px(getContext(), 10));
                    int width = getTextWidth(paintText, day);

                    if (selectbottom == i) {

                        canvas.drawText(day, w - width / 2, mHigh - 2, paintText2);

                        selectbottom = -1;
                    } else {

                        canvas.drawText(day, w - width / 2, mHigh - 2, paintText);
                    }
                } else if (listDAY.size() == 30) {
                    paintText.setTextSize(UIUtils.dip2px(getContext(), 10));
                    paintText2.setTextSize(UIUtils.dip2px(getContext(), 10));
                    if (i == 0 || i == 7 || i == 15 || i == 22 || i == 29) {

                        int width = getTextWidth(paintText, day);

                        if (selectbottom == i) {

                            if (i == 0) {
                                canvas.drawText(day, w, mHigh - 2, paintText2);

                            } else {
                                canvas.drawText(day, w - width / 2, mHigh - 2, paintText2);

                            }
                            selectbottom = -1;
                        } else {
                            if (i == 0) {
                                canvas.drawText(day, w, mHigh - 2, paintText);

                            } else {
                                canvas.drawText(day, w - width / 2, mHigh - 2, paintText);

                            }
                        }
                    }


                } else if (listDAY.size() == 31) {

                    paintText.setTextSize(UIUtils.dip2px(getContext(), 10));
                    paintText2.setTextSize(UIUtils.dip2px(getContext(), 10));
                    if (i == 0 || i == 7 || i == 15 || i == 22 || i == 30) {

                        int width = getTextWidth(paintText, day);

                        if (selectbottom == i) {

                            if (i == 0) {
                                canvas.drawText(day, w, mHigh - 2, paintText2);

                            } else {
                                canvas.drawText(day, w - width / 2, mHigh - 2, paintText2);

                            }
                            selectbottom = -1;
                        } else {
                            if (i == 0) {
                                canvas.drawText(day, w, mHigh - 2, paintText);

                            } else {
                                canvas.drawText(day, w - width / 2, mHigh - 2, paintText);

                            }
                        }
                    }


                } else if (listDAY.size() == 29) {
                    paintText.setTextSize(UIUtils.dip2px(getContext(), 10));
                    paintText2.setTextSize(UIUtils.dip2px(getContext(), 10));
                    if (i == 0 || i == 7 || i == 15 || i == 22 || i == 28) {

                        int width = getTextWidth(paintText, day);

                        if (selectbottom == i) {

                            if (i == 0) {
                                canvas.drawText(day, w, mHigh - 2, paintText2);

                            } else {
                                canvas.drawText(day, w - width / 2, mHigh - 2, paintText2);

                            }
                            selectbottom = -1;
                        } else {
                            if (i == 0) {
                                canvas.drawText(day, w, mHigh - 2, paintText);

                            } else {
                                canvas.drawText(day, w - width / 2, mHigh - 2, paintText);

                            }
                        }
                    }

                } else if (listDAY.size() == 28) {

                    paintText.setTextSize(UIUtils.dip2px(getContext(), 10));
                    paintText2.setTextSize(UIUtils.dip2px(getContext(), 10));
                    if (i == 0 || i == 7 || i == 15 || i == 22 || i == 27) {

                        int width = getTextWidth(paintText, day);

                        if (selectbottom == i) {

                            if (i == 0) {
                                canvas.drawText(day, w, mHigh - 2, paintText2);

                            } else {
                                canvas.drawText(day, w - width / 2, mHigh - 2, paintText2);

                            }
                            selectbottom = -1;
                        } else {
                            if (i == 0) {
                                canvas.drawText(day, w, mHigh - 2, paintText);

                            } else {
                                canvas.drawText(day, w - width / 2, mHigh - 2, paintText);

                            }
                        }
                    }
                }


            }
            for (int i = 0; i < listValue.size(); i++) {
                float h = High - High * Float.parseFloat(listValue.get(i)) / MaxValue + topH;
                float w = (float) (Width / listValue.size() * (i + 0.5));

                if (High * Float.parseFloat(listValue.get(i)) / MaxValue < CircleR) {
                    h = High - CircleR - 1;
                }
                if (h < CircleR) {
                    h = CircleR + 1;
                }
                if (h > High - CircleR) {
                    h = High - CircleR + 1;
                }


                if (MaxValue == 0)
                    h = High - CircleR - 1;
                canvas.drawCircle(w, h, CircleR, paint);

                RectF f1 = new RectF();

                float wrf = (float) (Width / listValue.size() / 2);

                f1.set(w - wrf, 0, w + wrf, getHeight());


                if (select == i) {

                    int width = getTextWidth(paintText2, Float.parseFloat(listValue.get(i)) + "");
                    int high = (int) getTextHigh(paintText2);


                    if (w - width / 2 < 0) {
                        canvas.drawText(Float.parseFloat(listValue.get(i)) + "", w, high, paintText2);

                    } else if (w + width / 2 > Width) {
                        canvas.drawText(Float.parseFloat(listValue.get(i)) + "", w - width, high, paintText2);
                    } else {
                        canvas.drawText(Float.parseFloat(listValue.get(i)) + "", w - width / 2, high,
                                paintText2);

                    }

                    select = -1;
                }

                listRectF.add(f1);

            }

        }

    }

    Animation popup_enter_bottom;
    Animation popup_out_bottom;
    SelectItem mselectItem;
    int vid = 0;

    public void setValue(final List<String> listValue, final boolean cal, final boolean anim,
                         final List<String> listDay, SelectItem mselectItem, int vid) {
        this.mselectItem = mselectItem;
        this.vid = vid;
        this.listDAY = new ArrayList<String>();
        ;
        this.listDAY.addAll(listDay);
        this.isKcal = cal;
        if (this.listValue != null && this.listValue.size() != 0 && anim) {

            popup_out_bottom = AnimationUtils.loadAnimation(getContext(), R.anim.sacle_bottom_out);
            startAnimation(popup_out_bottom);

            popup_out_bottom.setAnimationListener(new AnimationListener() {

                @Override
                public void onAnimationStart(Animation arg0) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onAnimationRepeat(Animation arg0) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onAnimationEnd(Animation arg0) {
                    setVisibility(View.INVISIBLE);
                    play(listValue, cal, anim, 10);

                }
            });

        } else {

            play(listValue, cal, anim, 600);

        }
    }

    private void play(final List<String> listValue, final boolean cal, boolean anim, int time) {
        this.listValue = new ArrayList<String>();
        this.listValue.addAll(listValue);
        MaxValue = 0f;
        post(new Runnable() {

            @Override
            public void run() {
                for (String a : listValue) {
                    if (Float.parseFloat(a) > MaxValue)
                        MaxValue = Float.parseFloat(a);
                }
                initView();
                invalidate();
            }
        });

        if (anim) {
            setVisibility(View.INVISIBLE);
            popup_enter_bottom = AnimationUtils.loadAnimation(getContext(), R.anim.sacle_bottom_in);
            popup_enter_bottom.setAnimationListener(new AnimationListener() {

                @Override
                public void onAnimationStart(Animation arg0) {
                    setVisibility(View.VISIBLE);
                }

                @Override
                public void onAnimationRepeat(Animation arg0) {
                    // TODO Auto-generated method stub

                }

                @Override
                public void onAnimationEnd(Animation arg0) {
                    // TODO Auto-generated method stub

                }
            });
            postDelayed(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    startAnimation(popup_enter_bottom);
                }
            }, time);

        }

    }

    @Override
    public boolean onTouch(View arg0, MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_UP) {
            float x = event.getX();
            float y = event.getY();

            for (int i = 0; i < listRectF.size(); i++) {
                if (listRectF.get(i).contains(x, y)) {

                    if (mselectItem != null) {
                        select = i;
                        selectbottom = i;
                        mselectItem.onSelectItem(this.vid, i);
                    }

                    break;
                }

            }
        }
        return true;
    }

    public void ShowView() {
        setValue(this.listValue, this.isKcal, false, this.listDAY, mselectItem, this.vid);
    }

    public interface SelectItem {
        void onSelectItem(int vid, int item);
    }


    public int getTextWidth(Paint paint, String str) {
        int iRet = 0;
        if (str != null && str.length() > 0) {
            int len = str.length();
            float[] widths = new float[len];
            paint.getTextWidths(str, widths);
            for (int j = 0; j < len; j++) {
                iRet += (int) Math.ceil(widths[j]);
            }
        }
        return iRet;
    }

    public static float getTextHigh(Paint paint) {
        Paint.FontMetrics fm = paint.getFontMetrics();
        return fm.descent - fm.ascent;
    }

}
用到的动画 
 R.anim.sacle_bottom_in
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <scale
        android:duration="500"
        android:fillAfter="false"
        android:fromXScale="1.0"
        android:fromYScale="0.0"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:pivotX="0%"
        android:pivotY="100%"
        android:toXScale="1.0"
        android:toYScale="1.0" />

</set>
======================================================
 R.anim.sacle_bottom_out
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <scale
        android:duration="300"
        android:fillAfter="false"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:pivotX="0%"
        android:pivotY="100%"
        android:toXScale="1.0"
        android:toYScale="0.0" />

</set>

用到的工具类
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

import com.ast.smartlighter.MyApplication;

import java.lang.reflect.Field;


public class UIUtils {
    /**
     * 获取屏幕宽度
     *
     * @param activity
     * @return
     * @Description:
     */
    public static int getScreenWidth(Activity activity) {
        if (activity == null) {
            return 0;
        }
        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        return dm.widthPixels;
    }

    /**
     * 获取屏幕高度
     *
     * @param activity
     * @return
     * @Description:
     */
    public static int getScreenHeight(Activity activity) {
        if (activity == null) {
            return 0;
        }
        DisplayMetrics dm = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
        return dm.heightPixels;
    }

    /**
     * 获取状态栏高度
     *
     * @param activity
     * @return
     * @Description:
     */
    public static int getStatusBarHeight(Activity activity) {
        int result = 0;
        int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = activity.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    public static int getStatusBarHeight(Context context) {
        Class<?> c = null;
        Object obj = null;
        Field field = null;
        int x = 0, statusBarHeight = 0;
        try {
            c = Class.forName("com.android.internal.R$dimen");
            obj = c.newInstance();
            field = c.getField("status_bar_height");
            x = Integer.parseInt(field.get(obj).toString());
            statusBarHeight = context.getResources().getDimensionPixelSize(x);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        return statusBarHeight;
    }

    /**
     * px值转换为dipdp值,保证尺寸大小不变
     *
     * @param pxValue
     * @param scale   DisplayMetrics类中属性density     * @return
     */
    public static int px2dip(float pxValue) {
        final float scale = MyApplication.getContext().getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * dipdp值转换为px值,保证尺寸大小不变
     *
     * @param dipValue
     * @param scale    DisplayMetrics类中属性density     * @return
     */
    public static int dip2px(Context context, float dipValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dipValue * scale + 0.5f);
    }

    /**
     * px值转换为sp值,保证文字大小不变
     *
     * @param pxValue
     * @param fontScale DisplayMetrics类中属性scaledDensity     * @return
     */
    public static int px2sp(Context context, float pxValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (pxValue / fontScale + 0.5f);
    }

    /**
     * sp值转换为px值,保证文字大小不变
     *
     * @param spValue
     * @param fontScale DisplayMetrics类中属性scaledDensity     * @return
     */
    public static int sp2px(float spValue) {
        final float fontScale = MyApplication.getContext().getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    public static View inflate(int layoutId) {
        return View.inflate(MyApplication.getContext(), layoutId, null);
    }

    public static <T extends Object> T checkNull(String msg, T t) {
        if (t == null) {
            throw new NullPointerException(msg + " can not be null!");
        }
        return t;
    }

    public static <T extends Object> T checkNull(T t) {
        return checkNull("params", t);
    }


    /**
     * @param bitmap     原图
     * @param edgeLength 希望得到的正方形部分的边长
     * @return 缩放截取正中部分后的位图。
     */
    public static Bitmap centerSquareScaleBitmap(Bitmap bitmap, int edgeLength) {
        if (null == bitmap || edgeLength <= 0) {
            return null;
        }

        Bitmap result = bitmap;
        int widthOrg = bitmap.getWidth();
        int heightOrg = bitmap.getHeight();

        if (widthOrg > edgeLength && heightOrg > edgeLength) {
            //压缩到一个最小长度是edgeLengthbitmap
            int longerEdge = (int) (edgeLength * Math.max(widthOrg, heightOrg) / Math.min(widthOrg, heightOrg));
            int scaledWidth = widthOrg > heightOrg ? longerEdge : edgeLength;
            int scaledHeight = widthOrg > heightOrg ? edgeLength : longerEdge;
            Bitmap scaledBitmap;

            try {
                scaledBitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, scaledHeight, true);
            } catch (Exception e) {
                return null;
            }

            //从图中截取正中间的正方形部分。
            int xTopLeft = (scaledWidth - edgeLength) / 2;
            int yTopLeft = (scaledHeight - edgeLength) / 2;

            try {
                result = Bitmap.createBitmap(scaledBitmap, xTopLeft, yTopLeft, edgeLength, edgeLength);
                scaledBitmap.recycle();
            } catch (Exception e) {
                return null;
            }
        }

        return result;
    }


    //此方法,如果显示则隐藏,如果隐藏则显示
    public static void hintKbOne(Context context) {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        // 得到InputMethodManager的实例
        if (imm.isActive()) {
            // 如果开启
            imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT,
                    InputMethodManager.HIDE_NOT_ALWAYS);

        }
    }

    //隐藏键盘
    public static void hidekeybroad(Context context, EditText et) {

        InputMethodManager imm2 = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm2 != null) {
            imm2.hideSoftInputFromWindow(et.getWindowToken(), 0);
        }

    }
}


//在代码中使用

<com.ast.smartlighter.view.WXSportStatistics
    android:id="@+id/wxsport"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
 
private void show(List<String> data, List<String> day) {
   //设置数据源
    wxsport.setValue(data, false, true, day, this, R.id.wxsport);
}

//每个点的点击事件
@Override
public void onSelectItem(int vid, int item) {
    switch (vid) {
        case R.id.wxsport:
            wxsport.select = item;
            wxsport.selectbottom = item;
            wxsport.ShowView();
            break;
        default:
            break;

    }
}







 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值