MPAndroidChart添加自定义样式

之前为添加XY轴描述大伤脑筋,因为如果用原生的TextView在图表控件的上方和下方分别作为XY轴加了Legend之后效果会差很多,如果绘制在图表上方又不好控制位置。
之前用textView来左XY轴实现效果:
实现效果
实现效果总的来讲还是可以的,但是因为控件是分离的,不好做到适配。
如果能在图表里面绘制一个就好了,然后发现了图表有Legend的绘制,有得参考了,自己根据Legend写了一个。
话不多说,开搞

分析Legend实现

Android Studio双击Shift找Legend,在框架的components文件夹下找到了Legend这个类。
Legend里面配置了一堆Legend参数:位置,颜色,方向,显示的数据等等…嗯,知道了这个就是用来配置Legend属性的类。

components里面的属性类都继承了ComponentBase这个类,看一下ComponentBase这个类做什么的。
里面是一些抽取出来的共用的配置,文字大小,颜色,是否可用间距等…

Legend在框架中的引用:LegendEntry,LegendRender,BarLineChartBase,Chart,BaseDataSet,IDataSet都有做引用

  1. LegendEntry:跟BarEntry等是一样的,是Legend每个item的属性。因为Legend 有多个数据,所以需要一个Entry的列表的来做存储。
  2. LegendRender:这个是重点,它用来根据属性配置绘制Legend。
  3. BarLineChartBase:这个在这个类的onDraw方法找到了Legend和LegendRender的引用。绘制就在这里了。
  4. Chart:声明Legend和LegendRender,这个是公用的属性。
  5. BaseDataSet和IDataSet:因为Legend跟图表的颜色和label有挂钩,所以需要。

分析上面文件我们需要写两个类,XYDESC(属性配置类),XYDESCRender(绘制类),并且在BarLineChartBase中声明和绘制(只有这两个图有XY轴)

实现我们的XYDESC

在components文件夹下增加XYDESC类


import android.graphics.Paint;

import com.github.mikephil.charting.utils.Utils;

/**
 * @author xiaolong
 * @version v1.0
 * @function <描述功能>
 * @date 2016/10/12-14:09
 */
public class XYDesc extends ComponentBase {
    private String xDesc;
    private String yDesc;
    private float yPadding;
    public String getxDesc() {
        return xDesc;
    }

    public void setxDesc(String xDesc) {
        this.xDesc = xDesc;
    }

    public String getyDesc() {
        return yDesc;
    }

    public void setyDesc(String yDesc) {
        this.yDesc = yDesc;
    }

    public XYDesc() {
        this.setEnabled(false);
    }


    /**
     * returns the maximum length in pixels across all legend labels + formsize
     * + formtotextspace
     *
     * @param p the paint object used for rendering the text
     * @return
     */
    public float getMaximumEntryWidth(Paint p, String desc) {
        float length = (float) Utils.calcTextWidth(p, desc);
        return length;
    }

    /**
     * returns the maximum height in pixels across all legend labels
     *
     * @param p the paint object used for rendering the text
     * @return
     */
    public float getMaximumEntryHeight(Paint p, String desc) {
        float length = (float) Utils.calcTextHeight(p, desc);
        return length;
    }

    public float getyPadding() {
        return yPadding;
    }

    public void setyPadding(float yPadding) {
        this.yPadding = yPadding;
    }
}

分别设置了X轴和Y轴描述,
padding是因为我们是参照Legend写的如果不做padding的话,会跟Legend绘制重叠,所以如果在左上角或右下角有Legend的时候加上padding。

//这两个方法用来计算文字的宽度和高度(Render中需要)

getMaxinumEntryWidth(Paint p,String desc)

getMaximumEntryHeight(Paint p, String desc)

在renderer文件夹下增加XYDESCRender

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;

import com.github.mikephil.charting.components.XYDesc;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;

/**
 * @author xiaolong
 * @version v1.0
 * @function <描述功能>
 * @date 2016/10/12-14:05
 */
public class XYDESCRenderer extends Renderer {


    /**
     * paint for the XYDESCRenderer labels
     */
    protected Paint mXYDESCLabelPaint;
    protected XYDesc mXYDesc;

    public XYDESCRenderer(ViewPortHandler viewPortHandler, XYDesc xydesc) {
        super(viewPortHandler);
        mXYDesc = xydesc;
        //初始化画笔
        mXYDESCLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mXYDESCLabelPaint.setTextSize(Utils.convertDpToPixel(xydesc.getTextSize()));
        mXYDESCLabelPaint.setTextAlign(Paint.Align.LEFT);
    }

    /**
     * Returns the Paint object used for drawing the Legend labels.
     *
     * @return
     */
    public Paint getLabelPaint() {
        return mXYDESCLabelPaint;
    }

    /**
     * 在画布上绘制
     * @param c
     */
    public void renderLegend(Canvas c) {
        if (!mXYDesc.isEnabled())
            return;
        Typeface tf = mXYDESCLabelPaint.getTypeface();

        if (tf != null)
            mXYDESCLabelPaint.setTypeface(tf);

        mXYDESCLabelPaint.setTextSize(mXYDesc.getTextSize());
        mXYDESCLabelPaint.setColor(mXYDesc.getTextColor());
        //获取行高
        float labelLineHeight = Utils.getLineHeight(mXYDESCLabelPaint);
        float yoffset = mXYDesc.getYOffset();
        float xoffset = mXYDesc.getXOffset();
//        drawLabel(c, mViewPortHandler.contentLeft() + mXYDesc.getMaximumEntryWidth(mXYDESCLabelPaint, mXYDesc.getyDesc()), yoffset + labelLineHeight + mXYDesc.getyPadding(), mXYDesc.getyDesc());
        drawLabel(c, mViewPortHandler.contentLeft()
                , yoffset + labelLineHeight + mXYDesc.getyPadding(), mXYDesc.getyDesc());
        drawLabel(c, mViewPortHandler.contentRight() - mXYDesc.getMaximumEntryWidth(mXYDESCLabelPaint, mXYDesc.getxDesc())
                , mViewPortHandler.getChartHeight() - yoffset - mXYDesc.getMaximumEntryHeight(mXYDESCLabelPaint, mXYDesc.getxDesc()) + 10, mXYDesc.getxDesc());

    }

    /**
     * Draws the provided label at the given position.
     *
     * @param c     canvas to draw with
     * @param x
     * @param y
     * @param label the label to draw
     */
    protected void drawLabel(Canvas c, float x, float y, String label) {
        c.drawText(label, x, y, mXYDESCLabelPaint);
    }


}

固定两个drawLabel分别在左上角和右下角。

然后在BarLineChartBase声明XYDESC和XYDESCRender

protected XYDesc mXYDesc;
protected XYDESCRenderer mXYDESCRenderer;
//在init方法中初始化
mXYDesc = new XYDesc();
mXYDESCRenderer = new XYDESCRenderer(mViewPortHandler, mXYDesc);
//在onDraw方法中绘制
找到 mLegendRenderer.renderLegend(canvas);下面加一句
mXYDESCRenderer.renderLegend(canvas);
增加属性设置方法
  public XYDesc getXYDesc() {
        return mXYDesc;
    }

    public XYDESCRenderer getXYDESCRenderer() {
        return mXYDESCRenderer;
    }


    public void setXYDesc(String xDesc, String yDesc) {
        setXYDesc(xDesc, yDesc, 10f);
    }

    public void setXYDesc(String xDesc, String yDesc, float textSize) {
        setXYDesc(xDesc, yDesc, textSize, Color.BLACK);
    }

    public void setXYDesc(String xDesc, String yDesc, float textSize, int textColor) {
        mXYDesc.setxDesc(xDesc);
        mXYDesc.setyDesc(yDesc);
        mXYDesc.setTextSize(textSize);
        mXYDesc.setTextColor(textColor);
        mXYDesc.setEnabled(true);

        if (mLegend.isEnabled() && (mLegend.getPosition() == Legend.LegendPosition.ABOVE_CHART_CENTER
                || mLegend.getPosition() == Legend.LegendPosition.ABOVE_CHART_LEFT
                || mLegend.getPosition() == Legend.LegendPosition.ABOVE_CHART_RIGHT)) {
            mXYDesc.setyPadding(6 * mLegend.getFormSize());
        }
        this.setExtraBottomOffset(12f + textSize);
        this.setExtraTopOffset(12f + textSize);
    }

就可以参考第一篇的来使用了。

package cn.xiaolongonly.mpchartsample.ui;

import android.graphics.Color;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;

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

import cn.xiaolongonly.mpchartsample.R;
import cn.xiaolongonly.mpchartsample.base.BaseActivity;
import cn.xiaolongonly.mpchartsample.chart.markview.DataMarkView;
import cn.xiaolongonly.mpchartsample.chart.util.ColorTemplate;

/**
 * @author xiaolong
 * @version v1.0
 * @function <描述功能>
 * @date 2016/12/6-9:10
 */
public class LineChartActivity1 extends BaseActivity {
    private LineChart chart;

    @Override
    protected int getLayoutId() {
        return R.layout.list_item_linechart;
    }

    @Override
    protected void initView() {
        chart = findView(R.id.chart);

        ChartConfig();
        //XY轴配置
        XAxis xAxis = chart.getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); //定制X轴是在图表上方还是下方。
        xAxis.setDrawGridLines(false);
        xAxis.setGranularity(1);
        xAxis.setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                return (int) value + "年";
            }
        });
        YAxis yAxisRight = chart.getAxisRight();
        yAxisRight.setEnabled(false);
        YAxis yAxisLeft = chart.getAxisLeft();
        yAxisLeft.setAxisMinValue(0);
        //动画效果
        chart.animateX(750);
        chart.animateY(750);
    }

    /**
     * 图表的配置 一些提示和Legend
     */
    private void ChartConfig() {

        //设置覆盖物
        DataMarkView dataMarkView = new DataMarkView(this, 0, "");//自定义覆盖物
        chart.setMarkerView(dataMarkView);

        //背景设置
        chart.setDrawGridBackground(false);//表格背景绘制
        chart.setBackgroundColor(getResources().getColor(R.color.chart_bg));

        //Legend定制
        chart.getLegend().setPosition(Legend.LegendPosition.ABOVE_CHART_LEFT);
        chart.getLegend().setForm(Legend.LegendForm.CIRCLE);//Legend样式

        //图表描述
        chart.setDescription(null);
        // 设置无数据文本提示
        chart.setNoDataText(getResources().getString(R.string.chart_no_data));
        //XY轴描述
        chart.setXYDesc("年份", "总金额(元)");
        //设置单方向和双方向缩放 true x,y方向可以同时控制,false只能控制x方向的缩小放大或者Y方向的缩小放大
        chart.setPinchZoom(true);
        //填充数据
        chart.setData(new LineData(generateLineDataSet()));
    }

    @Override
    protected void setListener() {

    }


    private ILineDataSet generateLineDataSet() {
        int color = ColorTemplate.PIE_COLORS[0];
        LineDataSet dataSet = new LineDataSet(generateData(), "年度营业额曲线");
        dataSet.setLineWidth(2.0f);
        dataSet.setCircleRadius(3.5f);
        dataSet.setDrawCircleHole(true);//填充圆
        dataSet.setValueTextSize(9f);
        dataSet.setHighlightLineWidth(2.0f);
        dataSet.setDrawFilled(true);//区域颜色
        dataSet.setFillAlpha(51);
        dataSet.setFillColor(color); //填充色
        dataSet.setHighLightColor(color); //选中十字线色
        dataSet.setColor(color); //线条颜色
        dataSet.setCircleColor(color); //圆点颜色
        dataSet.setCircleColorHole(Color.WHITE);
        dataSet.setCircleHoleRadius(2.0f);
        dataSet.setDrawValues(false);
        return dataSet;
    }

    private List<Entry> generateData() {
        List<Entry> entryList = new ArrayList<>();
        entryList.add(new Entry(2013, 1000));
        entryList.add(new Entry(2014, 2000));
        entryList.add(new Entry(2015, 3000));
        entryList.add(new Entry(2016, 4000));
        return entryList;
    }
}

效果如下
效果图

将描述写到了图表框架中了。感觉明显就好用多了。

在很多需求中,大部分图表都是大同小异。我们并不想要将同种类型的图表都按需求配置一遍,那样代码会显得多且杂,所以有必要将这些配置写成通用的配置。

下一篇会介绍图表框架的简单封装。

框架地址:https://github.com/PhilJay/MPAndroidChart

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 要在MPAndroidChart添加y轴,可以按照以下步骤进行: 1. 创建一个自定义的Y轴对象。可以使用`axisLeft()`或者`axisRight()`方法来创建一个具体的Y轴对象。例如,创建一个左侧Y轴对象的代码如下: ```java YAxis yAxisLeft = chart.getAxisLeft(); ``` 2. 对Y轴进行一些自定义设置。可以使用以下方法之一来对Y轴进行设置: - `setEnabled()`:设置Y轴是否可用 - `setAxisMaximum()`和`setAxisMinimum()`:设置Y轴的最大值和最小值 - `setDrawGridLines()`:设置是否绘制Y轴的网格线 - `setPosition()`:设置Y轴的位置(左侧或右侧) - `setTextColor()`:设置Y轴标签的颜色 - `setTextSize()`:设置Y轴标签的字体大小 - 其他相关方法 3. 将自定义的Y轴对象设置给图表对象。可以使用以下方法之一将自定义的Y轴对象设置给图表对象: - `setAxisLeft()`:将左侧Y轴对象设置给图表对象 - `setAxisRight()`:将右侧Y轴对象设置给图表对象 下面是一个完整的示例,展示如何添加和设置Y轴: ```java // 创建Y轴对象 YAxis yAxisLeft = chart.getAxisLeft(); // 对Y轴进行设置 yAxisLeft.setEnabled(true); yAxisLeft.setAxisMaximum(100f); yAxisLeft.setAxisMinimum(0f); yAxisLeft.setDrawGridLines(true); yAxisLeft.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART); yAxisLeft.setTextColor(Color.BLACK); yAxisLeft.setTextSize(12f); // 将自定义的Y轴对象设置给图表对象 chart.setAxisLeft(yAxisLeft); ``` 以上就是在MPAndroidChart添加和设置Y轴的步骤与示例代码。根据自己的具体需求,可以根据需要进行相关配置。 ### 回答2: 在使用MPAndroidChart的时候,我们可以通过以下几步来添加y轴: 第一步,创建一个LineDataSet对象,表示要展示的数据集合。其中,LineDataSet需要传入一个数据集合和一个标签。数据集合可以是一个float数组,表示y轴上的数据。 第二步,创建一个LineData对象,表示要展示的全部数据。LineData对象需要传入一个数据集合。将刚刚创建的LineDataSet对象添加到数据集合中。 第三步,创建一个LineChart对象,并设置相关属性。LineChartMPAndroidChart中绘制线条图的主要类。我们可以设置线条的颜色、样式、宽度等属性。 第四步,将LineData对象设置给LineChart对象,通过调用setLineData方法。 第五步,通过调用LineChart对象的getXAxis方法,获取到X轴对象。然后,通过调用setEnabled方法,设置X轴的可用性为false,即禁用X轴。 第六步,通过调用LineChart对象的getAxisLeft方法,获取到左侧Y轴对象。然后,可以设置Y轴的相关属性,如最大值、最小值、标签等。 第七步,通过调用LineChart对象的getAxisRight方法,获取到右侧Y轴对象。可以设置右侧Y轴的可见性、标签等属性。 最后,将LineChart对象添加到布局中,即可展示出带有Y轴数据的LineChart图表。 以上就是在MPAndroidChart添加Y轴的基本步骤。可以根据需要调整Y轴的相关属性,以满足各种需求。 ### 回答3: 在使用MPAndroidChart库绘制图表时,我们可以通过以下步骤来添加Y轴: 1. 首先,我们需要获取要添加Y轴的图表实例,可以通过findViewById方法或者其他方式获取。 例如: ``` LineChart lineChart = findViewById(R.id.line_chart); ``` 2. 创建一个Y轴对象,并设置一些基本属性。可以使用`lineChart.getAxisLeft()`获取左侧Y轴对象,或者使用`lineChart.getAxisRight()`获取右侧Y轴对象。 例如: ``` YAxis yAxis = lineChart.getAxisLeft(); // 或者 lineChart.getAxisRight(); yAxis.setTextColor(Color.BLACK); // 设置Y轴文本颜色为黑色 yAxis.setTextSize(12f); // 设置Y轴文本大小为12 ``` 3. 设置Y轴的最小值和最大值。我们可以使用`setAxisMinimum()`和`setAxisMaximum()`方法设置Y轴的范围。 例如: ``` yAxis.setAxisMinimum(0f); // 设置Y轴的最小值为0 yAxis.setAxisMaximum(100f); // 设置Y轴的最大值为100 ``` 4. 设置Y轴的标签数量。我们可以使用`setLabelCount()`方法设置Y轴的标签数量,这会均匀地将标签分布在Y轴上。 例如: ``` yAxis.setLabelCount(5); // 设置Y轴的标签数量为5 ``` 5. 最后,我们需要将数据设置给图表,并调用`invalidate()`方法刷新图表。 例如: ``` // 设置图表的数据 // ... // 刷新图表 lineChart.invalidate(); ``` 通过以上步骤,我们可以成功地添加Y轴,并设置它的属性和范围。您可以根据需要调整Y轴的其他属性,比如网格线、刻度线等等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值