在Android 中使用 echarts

2,407 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

做Android开发经常会需要画一些图表,自己写的话不仅麻烦而且工作量太大,所以一般都会采用第三方图表框架 ,这时候就用到了ECharts

在这里插入图片描述

前言

ECharts 是由百度开发提供的开源框架,主要提供给Web使用,所以Android中一般使用WebView加载显示,其实本质上也就是用 WebView 加载本地 H5。 ECharts的图表样式主要由option控制,option是由js编写,如下面代码就是一个简单折线图的option。

在andorid中使用ECharts,一般来讲我们有两种实现方案

  • Android获取数据并封装好option,然后传递给h5,h5再对数据进行解析,调用ECharts绘制。 这种方案的难点在于option的属性太多了,封装起来太麻烦。
  • h5处理所有操作,进行获取数据,并调用ECharts进行绘制。 这种方案需要对js比较熟悉。

以第一种为例: 下载自定义图表

  • 将下载好的echarts.min.js文件放入工程中assets目录下。 在这里插入图片描述

  • 编写healthy.html文件,并将healthy.html放入assets目录。 在这里插入图片描述 在这里插入图片描述 (或者直接输入healthy.html)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="renderer" content="webkit">
    <!-- 引入 ECharts 文件 -->
    <script src="echarts.min.js"></script>
</head>
<body>
<!-- 为 ECharts 准备一个具备大小(宽高)的 DOM -->
<div id="main" style="height: 244px;"></div>
<script type="text/javascript">
     var myChart1 = echarts.init(document.getElementById('main'));

var option;
option = {
        title: {
          text: "工单数波形图",
          textStyle: {
            color: "#2DC3FB",
            fontWeight: "bold",
            fontSize: "16",
          },
          padding: [20, 0, 0, 0],
        },
        tooltip: {
          backgroundColor: "#31516B",
          opacity: 0.3,
          trigger: "axis",
          axisPointer: {  // 焦点处样式
            type: "cross",
          },
          extraCssText: "text-align: center;",
          //在这里设置
          formatter: "{b0}<br/>{c0}个",
          textStyle: {
            color: "rgba(145, 201, 246, 1)",
          },
        },
        legend: {
          data: ["总工单", "未完成工单"],
          textStyle: {
            color: "#738CA0",
          },
          itemWidth: 10,
          itemHeight: 10,
          icon: "rect",
          right: 16,
          top: 16,
        },
        grid: {
          left: "3%",
          right: "4%",
          bottom: "3%",
          containLabel: true,
        },
        xAxis: {
          type: "category",
          axisTick: {
            show: false,
          },
          axisLabel: {
            color: "#20dbfd",
          },
          axisLine: {
            lineStyle: {
              color: "#20dbfd",
            },
          },
          data: ["07-11", "07-12", "07-13", "07-14", "07-15", "07-16", "07-17"],
        },
        yAxis: {
          type: "value",
          min: 0,
          max: 100,
          axisTick: {
            show: false,
          },
          axisLabel: {
            // 折线下方阴影
            color: "#20dbfd",
          },
          axisLine: {
            // 坐标轴线
            lineStyle: {
              color: "#20dbfd",
            },
          },
          splitLine: {
            // y轴 辅助线
            show: false,
          },
        },
        series: [
          {
            name: "总工单",
            type: "line",
            smooth: false,
            stack: "总工单",
            symbol: "circle", // 拐点为实心的 默认为空心
            itemStyle: {
              color: "#72F5FF",
            },
            lineStyle: {
              shadowBlur: 5,
              color: "#17D5E3",
              shadow: "0px 5px 1px 0px rgba(0, 0, 0, 0.41)",
            },
            areaStyle: {
              opacity: 0.5,
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: "rgba(13, 182, 252, 0.5)",
                },
                {
                  offset: 1,
                  color: "rgba(13, 182, 252, 0)",
                },
              ]),
            },
            data: [30, 26, 60, 67, 50, 80, 37],
          },
          {
            name: "未完成工单",
            type: "line",
            smooth: false,
            stack: "未完成工单",
            symbol: "circle", // 拐点为实心的 默认为空心
            itemStyle: {
              color: "#ff3f68",
            },
            lineStyle: {
              shadowBlur: 5,
              color: "#E74867",
              shadow: "0px 5px 1px 0px rgba(0, 0, 0, 0.41)",
            },
            areaStyle: {
              opacity: 0.5,
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                {
                  offset: 0,
                  color: "rgba(231, 72, 103, 0.5)",
                },
                {
                  offset: 1,
                  color: "rgba(231, 72, 103, 0)",
                },
              ]),
            },
            data: [10, 6, 37, 25, 30, 8, 16],
          },
        ],
      };
      //先初始化默认的echarts图 ,setData() 这个方法是来接收需要改变echarts图的地方
myChart1.setOption(option);
   function setData(option) {
            // 基于准备好的dom,初始化echarts实例
            var myChart = echarts.init(document.getElementById('main'));
            // 使用刚指定的配置项和数据显示图表。
            myChart.setOption(option);
        }
        </script>
    </body>
</html>
  • 第一种方法 :简单的使用

activity_main.xml

  <WebView
            android:id="@+id/orderrcharts_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />

MainActivity.kt

==(kotlin写法)==

//设置webview透明
  webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
  webView.setBackgroundColor(0)
  //开启本地文件读取(默认为true,不设置也可以)
  webView.settings.allowFileAccess = true
  //开启脚本支持
  webView.settings.javaScriptEnabled = true
  webView.loadUrl("file:///android_asset/healthy.html")

==(Java写法)==

WebView webView=findViewById(R.id.webview);
        webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        webView.setBackgroundColor(0);
        //开启本地文件读取(默认为true,不设置也可以)
        webView.getSettings().setAllowFileAccess(true);
        //开启脚本支持
        webView.getSettings().setJavaScriptEnabled(true);
        webView.loadUrl("file:///android_asset/healthy.html");
  • 第二种方法 :

activity_main.xml

 <com.board.utils.HtEChartView
             android:id="@+id/orderrcharts_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

MainActivity.kt ==(kotlin写法)==

// y,x 是横坐标和纵坐标的值
 surgarHightBlood_main.setData2(y, x)
  • 获取值 动态的给图赋值

public class HtEChartView extends LinearLayout {
    private WebView webView;
    private boolean isScrollEnabled = true;
    public HtEChartView(Context context) {
        this(context, null);
    }

    public HtEChartView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HtEChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    @SuppressLint({"SetJavaScriptEnabled", "ClickableViewAccessibility"})
    private void initView(Context context) {
        LayoutInflater layoutInflater = LayoutInflater.from(context);
        if (layoutInflater == null) {
            return;
        }
        View view =layoutInflater.inflate(R.layout.activity_ht_echart, this);
        webView = view.findViewById(R.id.web_view_id);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.setScrollContainer(false);
        webView.setVerticalScrollBarEnabled(false);
        webView.setHorizontalScrollBarEnabled(false);
    }

    /**
     * 绑定数据  健康指数
     * @param ydata
     * @param xdata
     */
    public void setData2(ArrayList<Double> ydata, ArrayList<String> xdata) {
        if (webView == null) {
            return;
        }
        webView.setWebViewClient(new HtWebViewClient(ydata,xdata));
        webView.loadUrl("file:///android_asset/healthy.html");
    }
}
  • HtWebViewClient

public class HtWebViewClient extends WebViewClient {
    private ArrayList<Double> ydata;
    private  ArrayList<String> xdata;
    public HtWebViewClient(ArrayList<Double> ydata, ArrayList<String> xdata) {
        this.ydata=ydata;
        this.xdata=xdata;
    }

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
    }

    @Override
    public void onPageFinished(final WebView view, String url) {
        super.onPageFinished(view, url);
        view.post(new Runnable() {
            @Override
            public void run() {
               //设置webview透明
                view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
                view.setBackgroundColor(0);
               //开启本地文件读取(默认为true,不设置也可以)
                view.getSettings().setAllowFileAccess(true);
               //把穿过来的值 ,转换成字符串
                String dataX="[";
                String dataY="[";
                for(int i=0;i<xdata.size();i++){
                    if(i<xdata.size()-1){
                        dataX=dataX+"\""+xdata.get(i)+"\",";
                        dataY=dataY+"\""+ydata.get(i)+"\",";
                    }else{
                        dataX=dataX+"\""+xdata.get(i)+"\"]";
                        dataY=dataY+"\""+ydata.get(i)+"\"]";
                    }
                }
                //取出最小值
                double min= ydata.get(0);
                for (int i=1;i<ydata.size()-1;i++){
                    if (min> ydata.get(i)){
                        min= ydata.get(i);
                    }
                }
                min-=0.2;
                String result = String.format("%3.2f", min);
                //这是需要显示的数值
                String option=" {\n" +
                        "        \"xAxis\": {\n" +
                        "            \"data\": " +dataX+ ", \n" +
                        "        },\n" +
                        " \"yAxis\": {\n"+
                        "     \"min\":"+result+",\n"+
                        "   },\n"+
                        "        \"series\": [\n" +
                        "            {\n" +
                        "                \"data\":" +dataY+ "\n" +
                        "    }\n" +
                        "], \n" +
                        "    }";
                view.loadUrl(String.format("javascript:setData(%s)", option));
            }
        });
    }

    @Override
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
        super.onReceivedError(view, request, error);
    }
}