本文是引用开源图表库框架 MPAndroidChart的LineChart

1.需求:

(1)动态添加RadioButton,点击改变下面的LineChart数据

(2)LineChart绘制价格走势图,只显示最低点的小圆点和View,手指滑动,MarkView数据变化。

(3) 服务端返回端数据,不是每一天端数据,但是x轴显示的必须是每一天的数据,这里是有我自己处理过的。返回里需要显示点的数组,之前的时间点显示的就是第一个点值。

2.实现效果:

最低点显示View和小圆点是自定义的,通过修改 LineChart的源码,下面我们来具体分析代码

3.代码分析

(1)布局的xml

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">

android:id="@+id/mRadioGroup"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="30px"

android:orientation="horizontal"

android:visibility="gone">

android:layout_width="match_parent"

android:layout_height="200dp"

android:orientation="vertical">

android:id="@+id/mLineChart"

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1" />

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="horizontal">

android:id="@+id/detailMinTimeTv"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="50px"

android:layout_weight="1"

android:textColor="#B5B5B5"

android:textSize="24px" />

android:id="@+id/detailMaxTimeTv"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginRight="30px"

android:layout_weight="1"

android:gravity="right"

android:textColor="#B5B5B5"

android:textSize="24px" />

这里主要是添加以一个RadioGroup和一个LineChart

接下来是MainActivity.class

private void addViewForGroup(final List list) {

for (int i = 0; i < list.size(); i++) {

final RadioButton view = (RadioButton) LayoutInflater.from(MainActivity.this)

.inflate(R.layout.item_gr_add_but_layout, mRadioGroup, false);

view.setId(i);

view.setText(list.get(i).getTitle());

if (i==0){

view.performClick();

radioGroupTextChange(list.get(0).getData(), list.get(0).getTitle());

mLineCharWidget = new LineChartWidget(MainActivity.this,

list.get(0).getData(), mLineChart, setMinPrice(list.get(0).getData()));

}

mRadioGroup.addView(view);

}

mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {

@Override

public void onCheckedChanged(RadioGroup group, int checkedId) {

RadioButton button = (RadioButton) findViewById(checkedId);

button.setText(list.get(checkedId).getTitle());

for (int i = 0; i < list.size(); i++) {

if (button.getText().toString().equals(list.get(i).getTitle())) {

radioGroupTextChange(list.get(i).getData(), list.get(i).getTitle());

if (mLineCharWidget == null) {

mLineCharWidget = new LineChartWidget(MainActivity.this,

list.get(i).getData(), mLineChart, setMinPrice(list.get(i).getData()));

} else {

mLineCharWidget.updateLineChar(list.get(i).getData(), setMinPrice(list.get(i).getData()));

}

}

}

}

});

}

注意:这里的LineChartWidget是我自己封装的一个LineChart,包括LineChart初始化,数据的处理,已经手势的一些操作

简单的说一下思路,因为 Linechart的x,y都是自定义的,但是我这里只自定义的y轴,是把x隐藏起来的,x轴只显示最开始的点和结束的点,所以我这里有点投机,自己设置点两个textview来显示的

Linechart的点一设置都是统一所有点都设置的,但是需求上是得只在最低点显示,并还要绘制一个view先初始化 View,然后解析数据,

JsonData jsonDetail = new Gson().fromJson(jsonStr.toString(), new TypeToken() {

}.getType());

if (jsonDetail.getHistorical_price() != null && jsonDetail.getHistorical_price().size() > 0) {

setGroupLay(jsonDetail.getHistorical_price());

}

再根据解析的数据动态添加RadioButton

初始化LineChart

private void initLineChar() {

List datalist

= removeDuplicteData(mHistoricalPrice.getData_list());

//设置手势滑动事件

mLineChar.setOnChartGestureListener(this);

//设置数值选择监听

mLineChar.setOnChartValueSelectedListener(this);

//后台绘制

mLineChar.setDrawGridBackground(false);

//设置描述文本

mLineChar.getDescription().setEnabled(false);

mLineChar.setTouchEnabled(true); // 设置是否可以触摸

mLineChar.setDragEnabled(true);// 是否可以拖拽

mLineChar.setScaleXEnabled(true); //是否可以缩放 仅x轴

mLineChar.setScaleYEnabled(true); //是否可以缩放 仅y轴

mLineChar.setPinchZoom(true); //设置x轴和y轴能否同时缩放。默认是否

mLineChar.setDragDecelerationFrictionCoef(0.99f);

mLineChar.getAxisRight().setEnabled(false);

// 默认动画

mLineChar.animateX(2500);

setMakeList(removeDuplicteData(datalist));

initMark(makeList, Long.valueOf(mHistoricalPrice.getStart_time()));

initXAxis(datalist.size(), xAxisValuesStr);

initYAxis();

initLegend();

setLineCharData(makeList);

}

设置markView

private void setMakeList(List datalist) {

try {

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

Date dBegin = format.parse(format.format(Long.valueOf(mHistoricalPrice.getStart_time()) * 1000));

Date dEnd = format.parse(format.format(Long.valueOf(mHistoricalPrice.getEnd_time()) * 1000));

float prices = 0;

List listDate = getDatesBetweenTwoDate(dBegin, dEnd);

if (datalist.size() >= listDate.size()) {

makeList.clear();

makeList.addAll(datalist);

} else {

for (int i = 0; i < listDate.size(); i++) {

JsonData.HistoricalPrice.HistoricalPriceData.DataList data

= new JsonData.HistoricalPrice.HistoricalPriceData.DataList();

for (int j = 0; j < datalist.size(); j++) {

if (TimeToString(DateToTimestamp(listDate.get(i))).equals(TimeToString(Long.valueOf(datalist.get(j).getPrice_drop_time())))) {

data.setPrice_drop_time(datalist.get(j).getPrice_drop_time());

data.setPrice_new(datalist.get(j).getPrice_new());

prices = (datalist.get(j).getPrice_new());

} else {

data.setPrice_drop_time(DateToTimestamp(listDate.get(i)) + "");

data.setPrice_new(prices);

}

}

makeList.add(data);

}

}

} catch (ParseException e) {

e.printStackTrace();

}

}

这里是设置LineChart里面的数据

private void setData(ArrayList values) {

LineDataSet set1 = null;

if (mLineChar.getData() != null && mLineChar.getData().getDataSetCount() > 0) {

set1 = (LineDataSet) mLineChar.getData().getDataSetByIndex(0);

set1.setValues(values);

mLineChar.getData().notifyDataChanged();

mLineChar.notifyDataSetChanged();

} else {

// 创建一个数据集,并给它一个类型

if (set1 == null) {

set1 = new LineDataSet(values, "价格曲线图");

set1.setColor(Color.rgb(27, 198, 181));

set1.setCircleColor(Color.BLACK);

set1.setLineWidth(1f);

set1.setCircleRadius(3f);

set1.setDrawCircleHole(false);

set1.setValueTextSize(9f);

set1.setDrawFilled(true);

set1.setFormLineWidth(1f);

set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f));

set1.setHighlightEnabled(true); //允许突出显示DataSet

set1.setDrawHighlightIndicators(false); // 取消点击线上的点展示十字标识

set1.setDrawValues(true); // 不展示线上面点的值

//是否显示小圆点

set1.setDrawCircles(false);

//修改源码 自定义的参数,可以显示最低点的View

set1.setLowDrawCircles(true);

set1.setCircleColors(Color.rgb(27, 198, 181));//27, 198, 181

//顶点设置值

set1.setDrawValues(false);

set1.setFillColor(Color.rgb(203, 242, 238));

}

//修改源码 自定义的参数,可以显示最低点的View

set1.setLowNumbers(minData);

ArrayList dataSets = new ArrayList();

//添加数据集

dataSets.add(set1);

//创建一个数据集的数据对象

LineData data = new LineData(dataSets);

//设置数据

mLineChar.setData(data);

}

}

这里是在源码里新加的地方

//修改源码 自定义的参数,可以显示最低点的View

set1.setLowDrawCircles(true);

set1.setLowNumbers(minData);

源码修改部分:

1.在LineDataSet添加2个参数,复写ILineDataSet新加的方法

//是否显示最低点的小圆点

private boolean mDrawLowCircle = false;

//最低点对应的具体值

private float mLowNumbers = 100f;

2.在ILineDataSet接口中添加2个方法

boolean isLowDrawCirclesEnabled();

float getLowNumbers();

3.修改源码LineChartRenderer这个类的 drawValues(Canvas c)方法中,这里是设置最低点显示的View,这个方法中添加判断:

//设置最低点显示的自定义view

if (dataSet.isLowDrawCirclesEnabled()) {

if (entry.getY() == dataSet.getYMin()) {

//设置在左边

if (x < 100) {

locationcode = 1;

} else { // 默认在右边

locationcode = 0;

}

appCustomDrawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x,

y - valOffset, Color.WHITE);

break;

}

}

private int locationcode = 0;

//设置最低点显示的text和text的背景框

private void appCustomDrawValue(Canvas c, IValueFormatter formatter, float value, Entry entry, int dataSetIndex, float x, float y, int color) {

// Paint.FontMetrics fm = new Paint.FontMetrics();

mValuePaint.setColor(Color.rgb(27, 198, 181));

// mValuePaint.getFontMetrics(fm);

y = (y + Utils.convertDpToPixel(30));

switch (locationcode) {

case 0:

RectF rectF = new RectF((x - Utils.convertDpToPixel(35)), (y - Utils.convertDpToPixel(23)),

(x + Utils.convertDpToPixel(5)), y);

c.drawRoundRect(rectF, 10, 10, mValuePaint);

mValuePaint.setColor(color);

c.drawText("¥" + formatter.getFormattedValue(value, entry, dataSetIndex, mViewPortHandler), x - Utils.convertDpToPixel(15), y - Utils.convertDpToPixel(10), mValuePaint);

break;

case 1:

RectF rectF1 = new RectF(x + Utils.convertDpToPixel(5), (y - Utils.convertDpToPixel(23)), x + Utils.convertDpToPixel(45), y);

c.drawRoundRect(rectF1, 10, 10, mValuePaint);

mValuePaint.setColor(color);

c.drawText("¥" + formatter.getFormattedValue(value, entry, dataSetIndex, mViewPortHandler), x + Utils.convertDpToPixel(27), y - Utils.convertDpToPixel(10), mValuePaint);

break;

}

}

在drawCircles(Canvas c)方法中添加判断:则可以显示最低点的小圆点了。

//显示最低点的小圆点

if (dataSet.isLowDrawCirclesEnabled()) {

if (e.getY() == dataSet.getYMin()) {

Bitmap circleBitmap = imageCache.getBitmap(j);

c.drawBitmap(circleBitmap, mCirclesBuffer[0] - circleRadius, mCirclesBuffer[1] - circleRadius, null);

break;

}

}

好了,所有功能的关键部分已经讲完了。大家不懂的可以留言提问,或者自己下载源码看看:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

Android实现自定义曲线截屏,Android实现价格走势自定义曲线图相关推荐

  1. Android实现自定义曲线截屏,Android实现截屏和截长图功能的各种方法

    /** * 截屏 * * @param activity * @return */ public static Bitmap activityShot(Activity activity) { /*获 ...

  2. flutter添加水印、添加自定义水印、禁止截屏(Android)

    一.前言 现实生活中,我们想要对应用的开发程序内容进行管控,避免暴露出敏感信息.因此,在很多的pc端的开发页面上,经常能看见水印,这种水印的实现,在html.vue等技术上对于开发过的人来说十分的简单 ...

  3. 手把手教你实现Android真机远程截屏

    先看效果演示 接下来手把手教你实现这样的效果. minicap简介 minicap是一个可以远程获取android屏幕画面的开源库,它在低版本的Android系统上采用截屏的方式获取画面,在Andro ...

  4. ddms java 截图_从Android设备获取实时截屏

    从Android设备获取实时截屏(adb) 前两篇文章已经把如何控制android设备的输入讲了,这一篇就是如何获取输出,通过adb的方式 原理 framebuffer获取流程 AdbClient和A ...

  5. android获取activity截图,Android Activity 不能被截屏的解决方法

    Android Activity 不能被截屏的解决方法 在Activity 添加即可 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECU ...

  6. shell 截屏 android,Android 使用Shell脚本截屏并自动传到电脑上

    Android 使用Shell脚本截屏并自动传到电脑上 Android设备用久了,截屏是个麻烦事.更麻烦的是通过qq传到电脑上,倒腾半天.其实用adb命令就可以截屏,然后写个pull的语句就可以拉到电 ...

  7. Android Studio实现设备截屏

    通过Android Studio可以实现对虚拟器和真机的截屏. 1 对模拟器的截屏 可以通过虚拟器的"Take screenshot"实现截屏 1.1默认方式截屏 Android ...

  8. android实现长截屏,Android实现全屏截图或长截屏功能

    本文实例为大家分享了Android实现全屏截图或长截屏功能的具体代码,供大家参考,具体内容如下 全屏截图: /** * 传入的activity是要截屏的activity */ public stati ...

  9. android利用反射调用截屏api,Android利用反射机制调用截屏方法和获取屏幕宽高的方法...

    想要在应用中进行截屏,可以直接调用 View 的 getDrawingCache 方法,但是这个方法截图的话是没有状态栏的,想要整屏截图就要自己来实现了. 还有一个方法可以调用系统隐藏的 screen ...

最新文章

  1. R语言绘制环形树状图
  2. C#windows向窗体传递泛型类
  3. 前端学习(1676):前端系列实战课程之贪吃蛇游戏设计
  4. 4固定在底部_有线鼠标之灵魂伴侣,火线竞技4号RGB鼠标线夹
  5. linux文件类型为目录,在Linux系统中,基本的文件类型分为()文件,目录文件和文件, 所有的I/..._考试资料网...
  6. protobuf java linux_linux下安装protobuf及其使用
  7. python2.7对DICOM图像的读取
  8. 极品菜系列3 [图]
  9. 详细配置swagger2
  10. python 将图片旋转多个角度_用Python玩转PDF的各种骚操作
  11. 为什么电脑屏幕会横过来_笔记本电脑屏幕横过来了怎么办?笔记本电脑屏幕倒过来了恢复方法...
  12. 华为android界面强刷救砖教程,华为手机救砖教程 华为手机开不了机变砖自救
  13. qq音乐 android pad版,QQ音乐HD版
  14. 隐匿在数据结构背后的原理
  15. 达芬奇密码 第三十章
  16. ORACLE 仿照原表建表语法
  17. 【数据结构与算法】迪杰斯特拉算法的介绍和最短路径问题程序实现
  18. IOS仿[自选股]项目开发
  19. GMSK调制解调(二)
  20. 修改android 开机画面

热门文章

  1. openfire+elipse的导入配置
  2. Symbian手记【三】 —— Symbian的描述符
  3. 哈希表存在的问题及解决方案
  4. Bulk异常引发的Elasticsearch内存泄漏
  5. leetcode547. 省份数量
  6. SpringCloud Hystrix的超时时间配置以及监控平台搭建
  7. 华为手机连接电脑用什么软件_屏幕镜像怎么连接电脑?使用这款软件,轻松投屏苹果手机到电脑...
  8. Go语言基础之结构体
  9. 小程序突破五层限制的方法
  10. laravel的安装