目前只是简单的显示,后面有时间弄的话会继续完善,目前在做天气预报
发现一篇文章做了24小时天气的曲线图,简单实现,好看,推荐:Android 天气APP(二十七)增加地图天气的逐小时天气、太阳和月亮数据_android 月亮api-CSDN博客
自己实现的方法如下:
导入依赖:implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
导入依赖问题可以看我另一篇文章
mainactivity代码
对应光标的做法
计算游标位置的 X 值 因为能滑动的距离是图表的总长度-可见区域总长度 | 看见区域 | <—— 滑动距离 ——> | | 总长度 | 所以不能以每滑动一格,游标就往右移动一格,这样游标一直在左边,不好看, 所以我们可以把 光标的位置=可见的左边的x轴位置+可见区域的长度除以滑动距离的长度 把多出来的那部分分摊下去,这样就可以实现在最左边时,光标在左边,在最右边时光标在最右边
package com.gpnu.yuan.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.graphics.Color; import android.os.Bundle; import android.view.MotionEvent; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.MarkerView; 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.highlight.Highlight; import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { // 创建 LineChart 对象 private LineChart chart; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 设置布局文件 setContentView(R.layout.activity_main); // 从布局文件中获取 LineChart 控件 chart = findViewById(R.id.chart); // 设置图表可拖动,但不可缩放,并去掉图表的描述 chart.setDragEnabled(true); chart.setScaleEnabled(false); chart.setDescription(null); // 获取 X 轴并设置其位置在底部,同时关闭网格线的显示 XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setDrawGridLines(false); // 获取左侧的 Y 轴并显示网格线 YAxis leftAxis = chart.getAxisLeft(); leftAxis.setDrawGridLines(true); // 获取右侧的 Y 轴并禁用它 YAxis rightAxis = chart.getAxisRight(); rightAxis.setEnabled(false); // 假设有24个数据点,每个代表一小时 ArrayListvalues = new ArrayList<>(); for (int i = 0; i < 24; i++) { float val = (float) (Math.random() * 30); // 随机生成温度 values.add(new Entry(i, val)); } // 使用数据点集合创建 LineDataSet 对象,表示温度数据集 LineDataSet set1 = new LineDataSet(values, "Temperature"); // 设置数据集的依赖轴、颜色、值的文字颜色和线宽 set1.setAxisDependency(YAxis.AxisDependency.LEFT); set1.setColor(Color.RED); set1.setValueTextColor(Color.RED); set1.setLineWidth(2f); //开启高亮线下部分填充 set1.setDrawFilled(true); set1.setFillAlpha(10);//透明度 set1.setFillColor(Color.RED);//填充颜色 // 设置高亮线颜色,关闭绘制圆点和值 set1.setHighLightColor(Color.rgb(244, 117, 117)); set1.setDrawCircles(false); set1.setDrawValues(false); // 设置线条为三次贝塞尔曲线 set1.setMode(LineDataSet.Mode.CUBIC_BEZIER); // 使用数据集创建 LineData 对象 LineData data = new LineData(set1); // 将 LineData 设置给图表 chart.setData(data); // 设置图表默认显示的 x 范围和初始位置 chart.setVisibleXRangeMaximum(6); chart.moveViewToX(10); // 允许高亮线-指示器 chart.setHighlightPerDragEnabled(true); // 设置图表数据后调用自定义的 moveHighlight() 方法 chart.setData(data); moveHighlight(); // 设置图表手势监听器 chart.setOnChartGestureListener(new OnChartGestureListener() { @Override public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { // 当图表手势开始时调用 // 无需实现此方法,因为我们在此应用中不需要处理图表手势开始的事件 } @Override public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { // 当图表手势结束时调用 // 无需实现此方法,因为我们在此应用中不需要处理图表手势结束的事件 } @Override public void onChartLongPressed(MotionEvent me) { // 当用户长按图表时调用 // 无需实现此方法,因为我们在此应用中不需要处理长按事件 } @Override public void onChartDoubleTapped(MotionEvent me) { // 当用户双击图表时调用 // 无需实现此方法,因为我们在此应用中不需要处理双击事件 } @Override public void onChartSingleTapped(MotionEvent me) { // 当用户单击图表时调用 // 无需实现此方法,因为我们在此应用中不需要处理单击事件 } @Override public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { // 当用户用快速滑动手势在图表上进行滑动时调用 // 无需实现此方法,因为我们在此应用中不需要处理滑动事件 } @Override public void onChartScale(MotionEvent me, float scaleX, float scaleY) { // 当图表缩放时调用 // 在缩放时更新指示器的位置 moveHighlight(); } @Override public void onChartTranslate(MotionEvent me, float dX, float dY) { // 当图表平移时调用 // 在平移时更新指示器的位置 moveHighlight(); } }); // 启用绘制 MarkerView,并设置自定义的 MarkerView chart.setDrawMarkers(true); MarkerView mv = new CustomMarkerView(this, R.layout.marker_view); mv.setChartView(chart); chart.setMarker(mv); } // 一个自定义方法来移动高亮指示器到当前视图的中心位置 private void moveHighlight() { // 获取当前可见区域最低的 X 值 float lowestVisibleX = chart.getLowestVisibleX(); // 获取当前可见区域最高的 X 值 float highestVisibleX = chart.getHighestVisibleX(); float VisibleChartWidth = chart.getHighestVisibleX() - chart.getLowestVisibleX(); //获取图表的总长度 float totalChartWidth = chart.getXChartMax() - chart.getXChartMin(); // 计算中心位置的 X 值 float x = lowestVisibleX + lowestVisibleX * (VisibleChartWidth / (totalChartWidth - VisibleChartWidth)); // 创建一个高亮对象,指定 X、Y、以及数据集索引 Highlight highlight = new Highlight(x, 0, 0); // 将高亮设置到图表上,并刷新图表 chart.highlightValue(highlight, true); chart.invalidate(); // 刷新图表 } }
CustomMarkerView代码
package com.gpnu.yuan.myapplication; import android.content.Context; import android.widget.TextView; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.MPPointF; public class CustomMarkerView extends MarkerView { private TextView tvContent; public CustomMarkerView(Context context, int layoutResource) { super(context, layoutResource); tvContent = findViewById(R.id.tvContent); } // 每次重绘指示器时调用此函数更新文本内容 @Override public void refreshContent(Entry e, Highlight highlight) { tvContent.setText(String.format("时间: %d点, 空气质量: %.1f", (int)e.getX(), e.getY())); super.refreshContent(e, highlight); } // 控制指示器的位置,这里将指示器显示在所选点的上方 @Override public MPPointF getOffset() { return new MPPointF(-(getWidth() / 2f), -getHeight() - 10); } }
activity_main.xml
marker_view.xml
marker_bg.xml