Android自定义折线图 不用三方库

没有发博文的习惯,这算是个小开始吧,写个关于折线的例子,网上找了一大堆,好在能看懂部分内容了 就照着写了一个,有点简单,本人是小白,所以有点low 不喜勿喷呐 嘿~嘿~嘿~

先上代码吧 注释很详细,


import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;

public class DrawView extends View{
    public int XPoint = 60; // 原点的X坐标
    public int YPoint ;// 原点的Y坐标260
    public int XScale ; // X的刻度长度55
    public int YScale ; // Y的刻度长度40
    public int XLength ; // X轴的长度380
    public int YLength ; // Y轴的长度240
//  private int scaleLength = 10;//刻度线的长度 TTTTTT
    private int top = 10;//上边缘距离
    private int left = 40;//左边缘距离
    private int right = 10;//右边缘距离
    private int bottom = 40;//下边缘距离
    private String[] YLabel;//y轴的刻度值
    private String[] XLabel;//X轴的刻度值
    public String[] DataStr; // 数据
    public String[] DataStr1; // 数据

//  private Bitmap mBackGround;
    public DrawView(Context context) {
        super(context);
//      mBackGround  = ((BitmapDrawable) this.getResources().getDrawable(R.drawable.viewbackground)).getBitmap(); //获取背景图片
    }
    public void setDate(String[] YLabel,String[] XLabel,String[] DataStr,String[] DataStr1) {//如果只需要一条折线,最后这个参数给null就行了
        this.YLabel = YLabel;
        this.XLabel = XLabel;
        this.DataStr = DataStr;
        this.DataStr1 = DataStr1;
        invalidate();
    }
    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Log.i("Main", "Width = " + getWidth());//1280
        Log.i("Main", "Height = " + getHeight());//670  测量整个view的高度不包括状态栏

        Log.i("Main", "Width = " + getMeasuredWidth());//一个是测量整个view的高度  一个是测量view里内容的高度
        Log.i("Main", "Height = " + getMeasuredHeight());

        YLength = getHeight()-bottom-top;//整个Y轴的长度
        XLength = getWidth()-right-left;
        YPoint = getHeight()-bottom;
        XScale = (XLength/XLabel.length);//--x轴的刻度平均长度
        YScale = (YLength/YLabel.length);//Y--Y轴的刻度平均长度

        Paint paint = new Paint();
        paint.setStrokeWidth(2);
        paint.setColor(Color.GRAY);
        paint.setTextSize(20);
        paint.setAntiAlias(true);
        paint.setTextAlign(Paint.Align.CENTER);

//      canvas.drawBitmap(mBackGround, 0, 0, paint); //画背景图片
        //画竖线
        canvas.drawLine(XPoint,YPoint, XPoint,top, paint);
        for (int i = 1; i * YScale <= YLength; i++) {//画横刻度
            canvas.drawLine(XPoint, YPoint - i * YScale, XLength, YPoint - i* YScale, paint);
            paint.setColor(Color.BLACK);
            canvas.drawText(YLabel[i-1], XPoint - 30,YPoint - i * YScale +7, paint);  
            paint.setColor(Color.GRAY);
        }
        //画横线
        canvas.drawLine(XPoint, YPoint, XLength, YPoint, paint);
        for (int i = 1; i * XScale <= XLength; i++) {//画竖刻度
            canvas.drawLine(XPoint + (i-1) * XScale, YPoint, XPoint + (i-1) * XScale,top, paint);
            paint.setColor(Color.BLACK);
            canvas.drawText(XLabel[i-1], XPoint + (i-1) * XScale - 3,YPoint+30, paint);
            paint.setColor(Color.GRAY);
        }
        //画数据图
        paint.setColor(Color.GREEN);
        for (int i = 0; i<DataStr.length; i++) {
            canvas.drawCircle((float)XPoint+(i+1)*XScale,(float)calcuLations(DataStr[i]),5, paint);
            if (i+1<DataStr.length){
                canvas.drawLine((float)XPoint+(i+1)*XScale,(float)calcuLations(DataStr[i])
                        ,(float)XPoint+(i+2)*XScale,(float)calcuLations(DataStr[i+1]), paint);
            }
        }

        if (null!=DataStr1) {
            //画数据图第二条线(待封装扩展)
            paint.setColor(Color.RED);
            for (int i = 0; i<DataStr1.length; i++) {
                canvas.drawCircle((float)XPoint+(i+1)*XScale,(float)calcuLations(DataStr1[i]),5, paint);
                if (i+1<DataStr1.length){
                    canvas.drawLine((float)XPoint+(i+1)*XScale,(float)calcuLations(DataStr1[i])
                            ,(float)XPoint+(i+2)*XScale,(float)calcuLations(DataStr1[i+1]), paint);
                }
            }
        }
    }
    private int calcuLations(String y0) //计算y轴坐标
    {
        double y;
        try {
            y = Double.parseDouble(y0);
        } catch (Exception e) {
            return -100; 
        }
        return (int)(YPoint-YPoint*(y/Double.parseDouble(YLabel[YLabel.length-1])));
    }
}

说明一下:代码虽然很low 但是通俗易懂,所以这里是借鉴来用 自己可以稍微改改外观,完善以后我再来修改一下吧

activity里:

public class DiyViewsActivity extends Activity{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.diy_layout);
        init();
    }
    @SuppressWarnings("deprecation")
    private void init() {
        LinearLayout layout = (LinearLayout) findViewById(R .id.root);
        DrawView view = new DrawView(this);
        String[] DataStr1 = new String[]{"223","245","110","236","125","232","120","36","45","223","10","136","110","136","145"};  //数据
        String[] DataStr = new String[]{"123","110","136","145","123","110","136","145"};  //数据
        String[] YLabel = new String[]{"50","100","150","200","250","300","350","400"};
        String[] XLabel = new String[]{"0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15"};
        view.setDate(YLabel,XLabel,DataStr,DataStr1);
//      view.setBackgroundDrawable(getResources().getDrawable(R.drawable.viewbackground));//给整个View加背景
        layout.addView(view);
    }
}

xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout 
        android:id="@+id/root"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

    </LinearLayout>
</LinearLayout>

这里写图片描述

这是改过之后的 一个是修改了上次多条线的封装的问题, 一个是去掉了网格 改成短刻度

package com.muze.hrip.resident.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;

public class DrawView extends View{
    public int XPoint = 60; // 原点的X坐标
    public int YPoint ;// 原点的Y坐标260
    public int XScale ; // X的刻度长度55
    public int YScale ; // Y的刻度长度40
    public int XLength ; // X轴的长度380
    public int YLength ; // Y轴的长度240
//  private int scaleLength = 10;//刻度线的长度 TTTTTT
    private int top = 10;//上边缘距离
    private int left = 40;//左边缘距离
    private int right = 10;//右边缘距离
    private int bottom = 40;//下边缘距离
    private String[] YLabel;//y轴的刻度值
    private String[] XLabel;//X轴的刻度值
    private String[][] dateStr;
//  private Bitmap mBackGround;
    public DrawView(Context context) {
        super(context);
//      mBackGround  = ((BitmapDrawable) this.getResources().getDrawable(R.drawable.viewbackground)).getBitmap(); //获取背景图片
    }
    public void setDate(String[] YLabel,String[] XLabel,String[][] dates) {
        this.YLabel = YLabel;
        this.XLabel = XLabel;
        dateStr = dates;
        invalidate();
    }
    @SuppressLint("DrawAllocation")
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        Log.i("Main", "Width = " + getWidth());//1280
        Log.i("Main", "Height = " + getHeight());//670  测量整个view的高度不包括状态栏

        Log.i("Main", "Width = " + getMeasuredWidth());//一个是测量整个view的高度  一个是测量view里内容的高度
        Log.i("Main", "Height = " + getMeasuredHeight());

        YLength = getHeight()-bottom-top;//整个Y轴的长度
        XLength = getWidth()-right-left;
        YPoint = getHeight()-bottom;
        XScale = (XLength/XLabel.length);//--x轴的刻度平均长度
        YScale = (YLength/YLabel.length);//Y--Y轴的刻度平均长度

        Paint paint = new Paint();
        paint.setStrokeWidth(2);
        paint.setColor(Color.GRAY);
        paint.setTextSize(20);
        paint.setAntiAlias(true);
        paint.setTextAlign(Paint.Align.CENTER);

//      canvas.drawBitmap(mBackGround, 0, 0, paint); //画背景图片
        //画竖线
        canvas.drawLine(XPoint,YPoint, XPoint,top, paint);
        canvas.drawLine(XPoint-5,top+10, XPoint,top,paint);
        canvas.drawLine(XPoint+5,top+10, XPoint,top,paint);
        for (int i = 1; i * YScale <= YLength; i++) {//画横刻度
//          canvas.drawLine(XPoint, YPoint - i * YScale, XLength, YPoint - i* YScale, paint);
            canvas.drawLine(XPoint, YPoint - i * YScale, XPoint+5, YPoint - i* YScale, paint);
            paint.setColor(Color.BLACK);
            canvas.drawText(YLabel[i-1], XPoint - 30,YPoint - i * YScale +7, paint);  
            paint.setColor(Color.GRAY);
        }
        //画横线
        canvas.drawLine(XPoint, YPoint, XLength, YPoint, paint);
        canvas.drawLine(XLength-10, YPoint+5, XLength, YPoint,paint);
        canvas.drawLine(XLength-10, YPoint-5, XLength, YPoint,paint);

        for (int i = 1; i * XScale <= XLength; i++) {//画竖刻度
//          canvas.drawLine(XPoint + (i-1) * XScale, YPoint, XPoint + (i-1) * XScale,top, paint);
            canvas.drawLine(XPoint + (i-1) * XScale, YPoint, XPoint + (i-1) * XScale,YPoint-5, paint);
            paint.setColor(Color.BLACK);
            canvas.drawText(XLabel[i-1], XPoint + (i-1) * XScale - 3,YPoint+30, paint);
            paint.setColor(Color.GRAY);
        }
        //画数据图
        drawData(paint,canvas,dateStr);
    }
    private void drawData(Paint paint,Canvas canvas,String[][] dates) {

        for (int i = 0; i < dates.length; i++) {
            paint.setColor(Color.GREEN);
            for (int j = 0; j < dates[i].length; j++) {
                canvas.drawCircle((float)XPoint+(j+1)*XScale,(float)calcuLations(dates[i][j]),5, paint);
                paint.setColor(Color.BLACK);
                canvas.drawText("("+dates[i][j]+")", (float)XPoint+(j+1)*XScale-5,(float)calcuLations(dates[i][j])-20, paint);
                paint.setColor(Color.GREEN);
                if (j+1<dates[i].length){
                    canvas.drawLine((float)XPoint+(j+1)*XScale,(float)calcuLations(dates[i][j])
                            ,(float)XPoint+(j+2)*XScale,(float)calcuLations(dates[i][j+1]), paint);
                }
            }
        }






//      paint.setColor(Color.GREEN);
//      for (int i = 0; i<DataStr.length; i++) {
//          canvas.drawCircle((float)XPoint+(i+1)*XScale,(float)calcuLations(DataStr[i]),5, paint);
//          paint.setColor(Color.BLACK);
//          canvas.drawText("("+DataStr[i]+")", (float)XPoint+(i+1)*XScale-5,(float)calcuLations(DataStr[i])-20, paint);
//          paint.setColor(Color.GREEN);
//          if (i+1<DataStr.length){
//              canvas.drawLine((float)XPoint+(i+1)*XScale,(float)calcuLations(DataStr[i])
//                      ,(float)XPoint+(i+2)*XScale,(float)calcuLations(DataStr[i+1]), paint);
//          }
//      }
    }
    private int calcuLations(String y0) //计算y轴坐标
    {
        double y;
        try {
            y = Double.parseDouble(y0);
        } catch (Exception e) {
            return -100; 
        }
        return (int)(YPoint-YPoint*(y/Double.parseDouble(YLabel[YLabel.length-1])));
    }
}

Activity 里

DrawView view = new DrawView(this);
        String[] DataStr1 = new String[]{"223","245","210","236","225","232","220","236","245"};  //数据
        String[] DataStr = new String[]{"123","110","136","145","123","110","136","145","123"};  //数据
        String[][] datas = new String[][]{DataStr1,DataStr};
        String[] YLabel = new String[]{"50","100","150","200","250","300","350","400"};
        String[] XLabel = new String[]{"0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15"};
        view.setDate(YLabel,XLabel,datas);
        view.setBackgroundColor(getResources().getColor(R.color.ffffff));
        ll_graph.addView(view);

这是改了后的效果图

这里写图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在 Android 中创建平滑的折线图,可以通过以下步骤实现: 1. 创建一个继承自 View自定义视图,并在其中实现绘制折线图的逻辑。 2. 在自定义视图的 onDraw 方法中,使用 Path 对象绘制折线图的路径。 3. 在绘制路径之前,可以使用贝塞尔曲线算法将路径进行平滑处理,以确保折线图的线条更加平滑。 4. 在绘制路径之后,使用 Paint 对象设置线条的颜色、宽度等样式属性。 5. 最后,将自定义视图添加到布局中并显示出来。 以下是一个简单的示例代码,用于绘制平滑的折线图: ```java public class SmoothLineChartView extends View { private Path mPath; private Paint mPaint; public SmoothLineChartView(Context context) { super(context); init(); } public SmoothLineChartView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public SmoothLineChartView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { mPath = new Path(); mPaint = new Paint(); mPaint.setColor(Color.BLUE); mPaint.setStrokeWidth(5); mPaint.setStyle(Paint.Style.STROKE); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 绘制平滑的折线图 drawSmoothLineChart(canvas); } private void drawSmoothLineChart(Canvas canvas) { // TODO: 获取折线图数据,计算平滑曲线 // 绘制平滑曲线 canvas.drawPath(mPath, mPaint); } } ``` 在以上代码中,我们创建了一个继承自 View自定义视图 SmoothLineChartView,并在其中实现了绘制平滑的折线图的逻辑。具体实现中,我们使用了 Path 对象来绘制折线图的路径,并使用 Paint 对象设置线条的颜色、宽度等样式属性。在绘制路径之前,我们可以使用贝塞尔曲线算法将路径进行平滑处理,以确保折线图的线条更加平滑。最后,我们将自定义视图添加到布局中并显示出来。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值