仿微信运动步数折线统计图
来源:互联网 发布:遗传算法密码学 编辑:程序博客网 时间:2024/05/16 03:01
完整代码如下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值转换为dip或dp值,保证尺寸大小不变 * * @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); } /** * 将dip或dp值转换为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) { //压缩到一个最小长度是edgeLength的bitmap 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);}//每个点的点击事件@Overridepublic void onSelectItem(int vid, int item) { switch (vid) { case R.id.wxsport: wxsport.select = item; wxsport.selectbottom = item; wxsport.ShowView(); break; default: break; }}
阅读全文
0 0
- 仿微信运动步数折线统计图
- 仿微信运动折线图
- 统计图折线
- 手动刷微信运动步数
- 检测步数和运动状态
- 论如何刷微信运动步数
- Objective-C修改运动步数
- 论如何刷微信运动步数
- 微信运动修改步数方法
- 自定义一个圆形运动步数de计步效果
- C# 做折线统计图
- 自定义折线统计图
- IOS折线统计图
- 自定义折线统计图
- 画一个折线统计图
- 微信运动步数无限修改教程最高98800
- iOS 教你如何修改微信运动步数
- iOS 教你如何修改微信运动步数
- 验证银行卡号有效性接口 (无效)
- Android 热补丁动态修复
- 获取URL地址参数的方法
- 压缩感知重构算法之正交匹配追踪(OMP)
- 笔记——Safari兼容相关问题(后续跟进)
- 仿微信运动步数折线统计图
- hashcode(),hashset(),hash(),hashMao()相关的知识点
- MySQL注入攻击与防御
- 通俗理解Bag-of-words模型入门
- C语言中volatile关键字的作用
- angular.min.js 在iis服务上 post方法出现 500错误解决办法
- 浅谈RGB
- JAVA MyEclipse(4)---修改MyEclipse的默认工作空间
- MAC OS 您需要安装旧Java SE6 运行环境才能打开“***”问题解决方法