android 大屏图表 MPAndroidChart 水平柱状图 水平圆角柱状图

//图表库
 implementation  'com.github.PhilJay:MPAndroidChart:v3.1.0'

X轴:XAxis
Y轴:YAxis
图例:Legend
描述:Description
限制线:LimitLine
显示的视图:MarkerView (就是选择中的时候显示的样子)

MPAndroidChart最重要的核心功能

许多不同的图表类型:LineChart(线型图),BarChart(条状图,垂直,水平,堆叠,分组),PieChart(饼图),ScatterChart(散点图),CandleStickChart(K线图、蜡烛图),RadarChart(雷达图、蜘蛛网络图表),BubbleChart(气泡图)
组合图表(例如,一条线和一条条)
在两个轴上缩放(带有触摸手势,单独的轴或捏缩放)
拖动/平移(带有触摸手势)
分开的(双)y轴
突出显示值(带有可自定义的弹出视图)
将图表保存到SD卡(作为图像)
预定义的颜色模板
图例(自动生成,可自定义)
可自定义的轴(x轴和y轴)
动画(在x轴和y轴上建立动画)
极限线(提供其他信息,最大值等)
触摸,手势和选择回调的侦听器
完全可定制(绘画,字体,图例,颜色,背景,虚线等)
通过MPAndroidChart-Realm库支持Realm.io移动数据库
在Line-Chart和BarChart中平滑渲染多达10.000个数据点(在运行Android 6.0的2014 OnePlus One上测试)
轻量级(方法计数〜1.4K)
可作为.jar文件使用(大小仅为500kb)
可作为gradle依赖项并通过Maven获得
Google-PlayStore演示应用程序
广泛使用,对GitHub和stackoverflow 都提供了强大的支持– mpandroidchart
也可用于iOS:图表(API的工作方式相同)
也可用于Xamarin:MPAndroidChart.Xamarin
对动态和实时数据的有限的支持

水平柱状图

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

    <com.github.mikephil.charting.charts.HorizontalBarChart
        android:id="@+id/chart1"
        android:layout_width="444px"
        android:layout_height="444px"
        android:background="@android:color/white" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="500px"
        android:orientation="horizontal">

        <Button
            android:id="@+id/actionToggleBarBorders"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="边框"></Button>

        <Button
            android:id="@+id/actionToggleValues"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="显示条形框的值"></Button>

        <Button
            android:id="@+id/actionToggleIcons"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="显示图标"></Button>

        <Button
            android:id="@+id/actionToggleHighlight"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="高亮显示"></Button>

        <Button
            android:id="@+id/actionTogglePinch"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="手势"></Button>


    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="590px"
        android:orientation="horizontal">

        <Button
            android:id="@+id/actionToggleAutoScaleMinMax"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="比例"></Button>

        <Button
            android:id="@+id/animateX"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="X轴动画"></Button>

        <Button
            android:id="@+id/animateY"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Y轴动画"></Button>

        <Button
            android:id="@+id/animateXY"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="XY轴动画"></Button>

        <Button
            android:id="@+id/actionSave"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="保存"></Button>
    </LinearLayout>

    <SeekBar
        android:id="@+id/seekBar2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:layout_margin="8dp"
        android:layout_marginRight="5dp"
        android:layout_toLeftOf="@+id/tvYMax"
        android:max="200"
        android:paddingBottom="12dp" />

    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:visibility="gone"
        android:layout_height="wrap_content"
        android:layout_above="@+id/seekBar2"
        android:layout_margin="8dp"
        android:layout_marginRight="5dp"
        android:layout_marginBottom="35dp"
        android:layout_toLeftOf="@+id/tvXMax"
        android:max="500"
        android:paddingBottom="12dp" />

    <TextView
        android:id="@+id/tvXMax"
        android:layout_width="50dp"
        android:visibility="gone"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/seekBar1"
        android:layout_alignParentRight="true"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="15dp"
        android:gravity="right"
        android:text="@string/dash"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <TextView
        android:id="@+id/tvYMax"
        android:visibility="gone"
        android:layout_width="50dp"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/seekBar2"
        android:layout_alignParentRight="true"
        android:layout_marginRight="10dp"
        android:layout_marginBottom="15dp"
        android:gravity="right"
        android:text="@string/dash"
        android:textAppearance="?android:attr/textAppearanceMedium" />

</RelativeLayout>

package com.xxmassdeveloper.mpchartexample;import com.sbas.xueliapplication.R;

import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Bundle;
import androidx.core.content.ContextCompat;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

import com.github.mikephil.charting.charts.HorizontalBarChart;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.XAxis.XAxisPosition;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.github.mikephil.charting.utils.MPPointF;
import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase;

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

public class HorizontalBarChartActivity extends DemoBase implements
        OnChartValueSelectedListener, View.OnClickListener {

    private HorizontalBarChart chart;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_horizontalbarchart);

        setTitle("HorizontalBarChartActivity");



        chart = findViewById(R.id.chart1);
        chart.setOnChartValueSelectedListener(this);
        // chart.setHighlightEnabled(false);

        chart.setDrawBarShadow(false);

        chart.setDrawValueAboveBar(true);

        chart.getDescription().setEnabled(false);

        // if more than 60 entries are displayed in the chart, no values will be
        // drawn
        chart.setMaxVisibleValueCount(60);

        // scaling can now only be done on x- and y-axis separately
        chart.setPinchZoom(false);

        // draw shadows for each bar that show the maximum value
        // chart.setDrawBarShadow(true);

        chart.setDrawGridBackground(false);

        XAxis xl = chart.getXAxis();
        xl.setPosition(XAxisPosition.BOTTOM);
        xl.setTypeface(tfLight);
        xl.setDrawAxisLine(true);
        xl.setDrawGridLines(false);
        xl.setGranularity(10f);

        YAxis yl = chart.getAxisLeft();
        yl.setTypeface(tfLight);
        yl.setDrawAxisLine(true);
        yl.setDrawGridLines(true);
        yl.setAxisMinimum(0f); // this replaces setStartAtZero(true)
//        yl.setInverted(true);

        YAxis yr = chart.getAxisRight();
        yr.setTypeface(tfLight);
        yr.setDrawAxisLine(true);
        yr.setDrawGridLines(false);
        yr.setAxisMinimum(0f); // this replaces setStartAtZero(true)
//        yr.setInverted(true);

        chart.setFitBars(true);
        chart.animateY(2500);

        // setting data
        setDataHorizontalBarChar(5,50);

        Legend l = chart.getLegend();
        l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM);
        l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
        l.setOrientation(Legend.LegendOrientation.HORIZONTAL);
        l.setDrawInside(false);
        l.setFormSize(8f);
        l.setXEntrySpace(4f);

        initButton();
    }

    private void initButton() {
        Button actionToggleBarBorders =  findViewById(R.id.actionToggleBarBorders);
        actionToggleBarBorders.setOnClickListener(this::onClick);
        Button actionToggleValues =  findViewById(R.id.actionToggleValues);
        actionToggleValues.setOnClickListener(this::onClick);
        Button actionToggleIcons =  findViewById(R.id.actionToggleIcons);
        actionToggleIcons.setOnClickListener(this::onClick);
        Button actionToggleHighlight =  findViewById(R.id.actionToggleHighlight);
        actionToggleHighlight.setOnClickListener(this::onClick);
        Button actionTogglePinch =  findViewById(R.id.actionTogglePinch);
        actionTogglePinch.setOnClickListener(this::onClick);
        Button actionToggleAutoScaleMinMax =  findViewById(R.id.actionToggleAutoScaleMinMax);
        actionToggleAutoScaleMinMax.setOnClickListener(this::onClick);
        Button animateX =  findViewById(R.id.animateX);
        animateX.setOnClickListener(this::onClick);
        Button animateY =  findViewById(R.id.animateY);
        animateY.setOnClickListener(this::onClick);
        Button animateXY =  findViewById(R.id.animateXY);
        animateXY.setOnClickListener(this::onClick);
        Button actionSave =  findViewById(R.id.actionSave);
        actionSave.setOnClickListener(this::onClick);


    }

    private void setDataHorizontalBarChar(int count, float range) {

        float barWidth = 9f;
        float spaceForBar = 10f;
        ArrayList<BarEntry> values = new ArrayList<>();

        for (int i = 0; i < count; i++) {
            float val = (float) (Math.random() * range);
            values.add(new BarEntry(i * spaceForBar, val,
                    getResources().getDrawable(R.drawable.star)));
        }

        BarDataSet set1;

        if (chart.getData() != null &&
                chart.getData().getDataSetCount() > 0) {
            set1 = (BarDataSet) chart.getData().getDataSetByIndex(0);
            set1.setValues(values);
            chart.getData().notifyDataChanged();
            chart.notifyDataSetChanged();
        } else {
            set1 = new BarDataSet(values, "DataSet 1");

            set1.setDrawIcons(false);

            ArrayList<IBarDataSet> dataSets = new ArrayList<>();
            dataSets.add(set1);

            BarData data = new BarData(dataSets);
            data.setValueTextSize(10f);
            data.setValueTypeface(tfLight);
            data.setBarWidth(barWidth);
            chart.setData(data);
        }
    }



    @Override
    protected void saveToGallery() {
        saveToGallery(chart, "HorizontalBarChartActivity");
    }


    private final RectF mOnValueSelectedRectF = new RectF();

    @Override
    public void onValueSelected(Entry e, Highlight h) {

        if (e == null)
            return;

        RectF bounds = mOnValueSelectedRectF;
        chart.getBarBounds((BarEntry) e, bounds);

        MPPointF position = chart.getPosition(e, chart.getData().getDataSetByIndex(h.getDataSetIndex())
                .getAxisDependency());

        Log.i("bounds", bounds.toString());
        Log.i("position", position.toString());

        MPPointF.recycleInstance(position);
    }

    @Override
    public void onNothingSelected() {}

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.viewGithub: {
                Intent i = new Intent(Intent.ACTION_VIEW);
                i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java"));
                startActivity(i);
                break;
            }
            case R.id.actionToggleValues: {
                List<IBarDataSet> sets = chart.getData()
                        .getDataSets();

                for (IBarDataSet iSet : sets) {
                    iSet.setDrawValues(!iSet.isDrawValuesEnabled());
                }
                chart.invalidate();
                break;
            }
            case R.id.actionToggleIcons: {
                List<IBarDataSet> sets = chart.getData()
                        .getDataSets();

                for (IBarDataSet iSet : sets) {
                    iSet.setDrawIcons(!iSet.isDrawIconsEnabled());
                }

                chart.invalidate();
                break;
            }
            case R.id.actionToggleHighlight: {
                if(chart.getData() != null) {
                    chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled());
                    chart.invalidate();
                }
                break;
            }
            case R.id.actionTogglePinch: {
                if (chart.isPinchZoomEnabled())
                    chart.setPinchZoom(false);
                else
                    chart.setPinchZoom(true);

                chart.invalidate();
                break;
            }
            case R.id.actionToggleAutoScaleMinMax: {
                chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled());
                chart.notifyDataSetChanged();
                break;
            }
            case R.id.actionToggleBarBorders: {
                for (IBarDataSet set : chart.getData().getDataSets())
                    ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f);

                chart.invalidate();
                break;
            }
            case R.id.animateX: {
                chart.animateX(2000);
                break;
            }
            case R.id.animateY: {
                chart.animateY(2000);
                break;
            }
            case R.id.animateXY: {
                chart.animateXY(2000, 2000);
                break;
            }
            case R.id.actionSave: {
                if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
                    saveToGallery();
                } else {
                    requestStoragePermission(chart);
                }
                break;
            }
        }
    }
}

package com.xxmassdeveloper.mpchartexample.notimportant;

import android.Manifest;
import android.content.pm.PackageManager;
import android.graphics.Typeface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.snackbar.Snackbar;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.view.View;
import android.widget.Toast;

import com.github.mikephil.charting.charts.Chart;
import com.sbas.xueliapplication.R;

/**
 * Base class of all Activities of the Demo Application.
 *
 * @author Philipp Jahoda
 */
public abstract class DemoBase extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback {

    protected final String[] months = new String[] {
            "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec"
    };

    protected final String[] parties = new String[] {
            "Party A", "Party B", "Party C", "Party D", "Party E", "Party F", "Party G", "Party H",
            "Party I", "Party J", "Party K", "Party L", "Party M", "Party N", "Party O", "Party P",
            "Party Q", "Party R", "Party S", "Party T", "Party U", "Party V", "Party W", "Party X",
            "Party Y", "Party Z"
    };

    private static final int PERMISSION_STORAGE = 0;

    protected Typeface tfRegular;
    protected Typeface tfLight;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        tfRegular = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf");
        tfLight = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf");
    }

    protected float getRandom(float range, float start) {
        return (float) (Math.random() * range) + start;
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        overridePendingTransition(R.anim.move_left_in_activity, R.anim.move_right_out_activity);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == PERMISSION_STORAGE) {
            if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                saveToGallery();
            } else {
                Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT)
                        .show();
            }
        }
    }

    protected void requestStoragePermission(View view) {
        if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
            Snackbar.make(view, "Write permission is required to save image to gallery", Snackbar.LENGTH_INDEFINITE)
                    .setAction(android.R.string.ok, new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            ActivityCompat.requestPermissions(DemoBase.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_STORAGE);
                        }
                    }).show();
        } else {
            Toast.makeText(getApplicationContext(), "Permission Required!", Toast.LENGTH_SHORT)
                    .show();
            ActivityCompat.requestPermissions(DemoBase.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_STORAGE);
        }
    }

    protected void saveToGallery(Chart chart, String name) {
        if (chart.saveToGallery(name + "_" + System.currentTimeMillis(), 70))
            Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!",
                    Toast.LENGTH_SHORT).show();
        else
            Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT)
                    .show();
    }

    protected abstract void saveToGallery();
}

 如果不想要上边的线      yl.setEnabled(false);

        YAxis yl = chart.getAxisLeft();
        yl.setEnabled(false);
        yl.setTypeface(tfLight);
        yl.setDrawAxisLine(true);
        yl.setDrawGridLines(false);
        yl.setAxisMinimum(0f); // this replaces setStartAtZero(true)
//        yl.setInverted(true);

如果想要圆角柱状图  修改

HorizontalBarChartRenderer.java

 

 

            if (isCustomFill) {
                dataSet.getFill(pos)
                        .fillRect(
                                c, mRenderPaint,
                                buffer.buffer[j],
                                buffer.buffer[j + 1],
                                buffer.buffer[j + 2],
                                buffer.buffer[j + 3],
                                isInverted ? Fill.Direction.LEFT : Fill.Direction.RIGHT);
            }
            else {
//                c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
//                        buffer.buffer[j + 3], mRenderPaint);
                RectF rectF=new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],buffer.buffer[j + 3]);
                c.drawRoundRect(rectF,(float)25,(float)25,mRenderPaint);

            }

但是,如果想要自定义四个角的弧度,就需要使用Path类绘制。做以下修改: 

HorizontalBarChartRenderer.java

            if (isCustomFill) {
                dataSet.getFill(pos)
                        .fillRect(
                                c, mRenderPaint,
                                buffer.buffer[j],
                                buffer.buffer[j + 1],
                                buffer.buffer[j + 2],
                                buffer.buffer[j + 3],
                                isInverted ? Fill.Direction.LEFT : Fill.Direction.RIGHT);
            }
            else {
//                c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
//                        buffer.buffer[j + 3], mRenderPaint);
//                RectF rectF=new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],buffer.buffer[j + 3]);
//                c.drawRoundRect(rectF,(float)25,(float)25,mRenderPaint);
                RectF rectF=new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],buffer.buffer[j + 3]);
                Path path = new Path();
               //float数组中4个角分别是左上、右上、右下、左下
                path.addRoundRect(rectF,new float[]{0, 0, 20, 20, 20, 20, 0, 0},Path.Direction.CCW);
                c.drawPath(path,mRenderPaint);

            }

 

 

调整图形的宽度。

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值