Android折线图小工具
Rose J 人气:01.LineChart类
public class LineChart extends View { private Paint XPaint; private Paint YPaint; private Paint pointPaint; private Paint circlePaint; private Paint shapePaint; private Paint effectPaint, effectPaint1; private float yandianx, yuandiany, height, wigth; private Context context; private String ysplit[]; private String unit; private float max; private int textSize = 7; private int margin = 20; private float gao; private boolean start = false; private Map<String, Float> mapx; public LineChart(Context context) { super(context); this.context = context; } public LineChart(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } public LineChart(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.context = context; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public LineChart(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); this.context = context; } private void initView() { XPaint = new Paint(Paint.ANTI_ALIAS_FLAG); XPaint.setAntiAlias(true); XPaint.setColor(Color.parseColor("#1e90ff")); XPaint.setStrokeWidth(dp2px(1)); YPaint = new Paint(Paint.ANTI_ALIAS_FLAG); YPaint.setAntiAlias(true); YPaint.setColor(Color.BLACK); YPaint.setStrokeWidth(dp2px(2)); pointPaint = new Paint(Paint.ANTI_ALIAS_FLAG); pointPaint.setAntiAlias(true); pointPaint.setColor(Color.BLACK); pointPaint.setStyle(Paint.Style.STROKE); pointPaint.setStrokeWidth(dp2px(1)); circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); circlePaint.setAntiAlias(true); circlePaint.setColor(Color.WHITE); circlePaint.setStyle(Paint.Style.FILL); circlePaint.setStrokeWidth(1); shapePaint = new Paint(Paint.ANTI_ALIAS_FLAG); shapePaint.setAntiAlias(true); shapePaint.setColor(Color.TRANSPARENT); shapePaint.setStyle(Paint.Style.FILL); shapePaint.setStrokeWidth(1); effectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); effectPaint.setAntiAlias(true); effectPaint.setColor(Color.BLACK); effectPaint.setStyle(Paint.Style.FILL); effectPaint.setStrokeWidth(1); effectPaint.setTextSize(sp2px(textSize)); effectPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG); effectPaint1.setAntiAlias(true); effectPaint1.setColor(Color.BLACK); effectPaint1.setStyle(Paint.Style.FILL); effectPaint1.setStrokeWidth(1); effectPaint1.setTextSize(sp2px(9)); } @Override protected void onDraw(Canvas canvas) { if (start) { yandianx = dp2px(margin); yuandiany = getMeasuredHeight() - dp2px(margin); wigth = getMeasuredWidth() - dp2px(margin * 2); height = getMeasuredHeight() - dp2px(margin * 2); float point[] = new float[]{yandianx, yuandiany, yandianx, yandianx, yandianx - dp2px(3), yandianx + dp2px(textSize / 2)}; canvas.drawLines(point, 0, 4, YPaint); canvas.drawLines(point, 2, 4, YPaint); canvas.drawLine(yandianx, yandianx, yandianx + dp2px(3), yandianx + dp2px(textSize / 2), YPaint); canvas.drawLine(yandianx, yuandiany, yandianx + wigth, yuandiany, YPaint); canvas.drawLine(yandianx + wigth, yuandiany, yandianx + wigth - dp2px(textSize / 2), yuandiany - dp2px(3), YPaint); canvas.drawLine(yandianx + wigth, yuandiany, yandianx + wigth - dp2px(textSize / 2), yuandiany + dp2px(3), YPaint); canvas.drawText("0", yandianx - sp2px(textSize) - dp2px(2), yuandiany + sp2px(textSize) + dp2px(2), effectPaint); if (null != unit) { canvas.drawText(unit, yandianx - sp2px(textSize) * unit.length() / 2, yuandiany - height - dp2px(3), effectPaint); } if (null != ysplit && ysplit.length > 0) { gao = height / (ysplit.length + 1); for (int i = 0; i < ysplit.length; i++) { float a = Float.parseFloat(ysplit[i]); if (max < a) { max = a; } canvas.drawLine(yandianx, yuandiany - (i + 1) * gao, yandianx + dp2px(3), yuandiany - (i + 1) * gao, YPaint); canvas.drawText(ysplit[i], yandianx - (sp2px(textSize) * (ysplit[i].length())), yuandiany - (i + 1) * gao + sp2px(textSize / 2), effectPaint); } } if (mapx.size() > 0) { float kuan = wigth / (mapx.size() + 1); Object o[] = mapx.keySet().toArray(); for (int i = 0; i < o.length; i++) { String s = o[i].toString(); float x = yandianx + (i + 1) * kuan; float y = yuandiany - (height - gao) / max * mapx.get(o[i]); canvas.drawLine(x, yuandiany, x, yuandiany - dp2px(3), YPaint); canvas.drawText(s, x - (sp2px(textSize) * (s.length() / 2)), yuandiany + sp2px(textSize) + dp2px(3), effectPaint); if (i > 0) { canvas.drawLine(yandianx + i * kuan, yuandiany - (height - gao) / max * mapx.get(o[i - 1]), x, y, XPaint); } int size = dp2px(3); for (int i1 = 0; i1 < (x - yandianx) / size; i1++) { if (i1 % 2 == 0) canvas.drawLine(i1 * size + yandianx, y, (i1 + 1) * size + yandianx, y, shapePaint); } for (int i1 = 0; i1 < (yuandiany - y) / size; i1++) { if (i1 % 2 == 0) canvas.drawLine(x, yuandiany - i1 * size, x, yuandiany - (i1 + 1) * size, shapePaint); } String text = mapx.get(o[i]).toString(); canvas.drawText(text, x - text.length() * sp2px(textSize / 4), y - dp2px(3), effectPaint1); } for (int i = 0; i < o.length; i++) { float x = yandianx + (i + 1) * kuan; float y = yuandiany - (height - gao) / max * mapx.get(o[i]); canvas.drawCircle(x, y, dp2px(3), circlePaint); canvas.drawCircle(x, y, dp2px(3), pointPaint); } } } } public void startDraw(Map<String, Float> mapx, String[] ysplit, String unit, int margin, int textSize) { start = true; this.mapx = mapx; this.ysplit = ysplit; this.unit = unit; this.textSize = textSize; this.margin = margin; initView(); invalidate(); } /** * sp转换成px */ private int sp2px(float spValue) { float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); } /** * dp转换成px */ private int dp2px(float dpValue) { float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } }
2.Fragment代码
1.布局文件
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.hnucm18jr.myapplication.LineChart android:id="@+id/lineChart" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
2.逻辑代码
public class Zt_fragment extends Fragment { LineChart mLineChart; Calendar calendar = Calendar.getInstance(); @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_zt_fragment, container, false); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); mLineChart=getActivity(). findViewById(R.id.lineChart); //月 int month = calendar.get(Calendar.MONTH)+1; //日 int day = calendar.get(Calendar.DAY_OF_MONTH); Log.i("TIME","-------"+month+day); Map<String ,Float> map=new LinkedHashMap<>() ;//一定要用有序的Map int min=6; int max=18; Random random = new Random(); float num1 = random.nextInt(max)%(max-min+1) + min; float num2 = random.nextInt(max)%(max-min+1) + min; float num3 = random.nextInt(max)%(max-min+1) + min; float num4 = random.nextInt(max)%(max-min+1) + min; float num5 = random.nextInt(max)%(max-min+1) + min; float num6 = random.nextInt(max)%(max-min+1) + min; float num7 = random.nextInt(max)%(max-min+1) + min; if ((day-6)<=0){ String s1= (month-1) + "." + (30+day-6); map.put(s1,num1); }else { String s1= month + "." + (day-6); map.put(s1,num1); } if ((day-5)<=0){ String s2= (month-1) + "." + (30+day-5); map.put(s2,num2); }else { String s2= month + "." + (day-5); map.put(s2,num2); } if ((day-4)<=0){ String s3= (month-1) + "." + (30+day-4); map.put(s3,num3); }else { String s3= month + "." + (day-4); map.put(s3,num3); } if ((day-3)<=0){ String s4= (month-1) + "." + (30+day-3); map.put(s4,num4); }else { String s4= month + "." + (day-3); map.put(s4,num4); } if ((day-2)<=0){ String s5= (month-1) + "." + (30+day-2); map.put(s5,num5); }else { String s5= month + "." + (day-2); map.put(s5,num5); } if ((day-1)<=0){ String s6= (month-1) + "." + (30+day-1); map.put(s6,num6); }else { String s6= month + "." + (day-1); map.put(s6,num6); } String s7= month + "." + day; map.put(s7,num7); String[] a=new String[]{"06","12","18","24"}; mLineChart.startDraw(map,a,"小时",40,10);//map为横坐标数据和点数据,a为纵坐标刻度(为数字类型的字符串,m/s为纵坐标单位,40为坐标轴距离边界的位置dp,14是坐标轴字体大小) } }
3.Activity代码
1.布局文件
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <FrameLayout android:id="@+id/frameLayout" android:layout_width="0dp" android:layout_height="300dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
2.逻辑代码
public class MainActivity extends AppCompatActivity { Zt_fragment mZt_fragment=new Zt_fragment(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout,mZt_fragment).commit(); } }
运行
加载全部内容