MPAndroidChart是实现图表功能的优秀控件, 能够完毕大多数绘制需求. 对于改动第三方库而言, 优秀的架构是继承开发, 而不是把源代码拆分出去. MP在显示标记控件(MarkView)时, 会有异常, 导致标志在图表边缘显示不全, 则须要重写控件解决这个问题.

继承LineChart, 提取高亮位置坐标getHighLightPos, 重绘标记drawMarkers.

/**
* 数据中心的图表折线图, 继承MPChart的折线图
* <p>
* Created by wangchenlong on 15/10/13.
*/
public class CYDataLineChart extends LineChart { @SuppressWarnings("unused")
private static final String TAG = "DEBUG-WCL: " + CYDataLineChart.class.getSimpleName(); // 默认构造器
public CYDataLineChart(Context context) {
super(context);
} public CYDataLineChart(Context context, AttributeSet attrs) {
super(context, attrs);
} public CYDataLineChart(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} // 获取高亮点坐标
public float[] getHighLightPos(Entry e, Highlight highlight) {
return getMarkerPosition(e, highlight);
} // 重写这种方法, 修复Bug
@Override
protected void drawMarkers(Canvas canvas) { // if there is no marker view or drawing marker is disabled
if (mMarkerView == null || !mDrawMarkerViews || !valuesToHighlight())
return; Rect newRect = canvas.getClipBounds();
newRect.inset(-80, 0); //make the rect larger canvas.clipRect(newRect, Region.Op.REPLACE); //noinspection ForLoopReplaceableByForEach
for (int i = 0; i < mIndicesToHighlight.length; i++) { Highlight highlight = mIndicesToHighlight[i];
int xIndex = highlight.getXIndex(); if (xIndex <= mDeltaX && xIndex <= mDeltaX * mAnimator.getPhaseX()) { Entry e = mData.getEntryForHighlight(mIndicesToHighlight[i]); // make sure entry not null
if (e == null || e.getXIndex() != mIndicesToHighlight[i].getXIndex())
continue; float[] pos = getMarkerPosition(e, highlight); // Marker偏移
float tmpY = pos[1] - 8 * AppUtils.getPerDp(); Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
paint.setStrokeWidth(5); // noinspection deprecation
paint.setColor(getResources().getColor(R.color.chart_circle));
canvas.drawCircle(pos[0], pos[1], 2 * AppUtils.getPerDp(), paint); // check bounds
if (!mViewPortHandler.isInBounds(pos[0], tmpY))
continue; mMarkerView.refreshContent(e, highlight); mMarkerView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
mMarkerView.layout(0, 0, mMarkerView.getMeasuredWidth(),
mMarkerView.getMeasuredHeight()); if (tmpY - mMarkerView.getHeight() <= 0) {
float y = mMarkerView.getHeight() - tmpY;
mMarkerView.draw(canvas, pos[0], tmpY + y);
} else {
mMarkerView.draw(canvas, pos[0], tmpY);
}
}
}
}
}

getMarkerPosition是LineChart类中的protected方法, 继承类, 使用public方法导出.

float tmpY = pos[1] - 8 * AppUtils.getPerDp();, 又一次计算Y坐标, 偏离原始画布.

可是这样做有一个问题, 在移动MarkView时, 父控件会有残留. 怎样解决呢?

办法就是在移动时, 重绘父控件的canvas, 使用invalidate()函数.

        // 设置图表点击事件, 监听高亮位置
mLcChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry e, int dataSetIndex, Highlight h) {
int index = e.getXIndex();
Log.e(TAG, "index = " + index);
setChartIndex(index);
mCallback.setCurIndex(index);
mIndex = index; float[] pos = mLcChart.getHighLightPos(e, h);
Log.e(TAG, "x: " + pos[0] + ", y: " + pos[1]); mLlContainer.invalidate(); // 重绘父控件, 避免残留
} @Override
public void onNothingSelected() {
// 再次点击时调用这个, 要不非高亮
mLcChart.highlightValue(mIndex, 0);
}
});
    // 外部设置图表高亮
private void setChartHighlight(int index) {
if (mLcChart.getData() == null) return; mMarkerView.setDateText(mMarkers.get(index));
mLcChart.highlightValue(index, 0); mLlContainer.invalidate(); // 重绘父控件, 避免残留
}

在图表控件中, 内部外部都会触发高亮位置.

OK, Enjoy It!

重写MPAndroidChart显示标记的更多相关文章

  1. 2019.03.20 读书笔记 as is 以及重写隐式/显示

    强转.as is 的用法 强制转换类型有两种:子类转基类,重写隐式(implicit )\显示(explicit) 转换操作符 class myclass { private int value; p ...

  2. IIS-URL重写模块配置参考

    本文提供了URL重写模块的概述,并解释了该模块使用的配置概念. 功能概述URL重写模块将请求URL重写为显示给用户或Web应用程序的简单,用户友好和搜索引擎友好的地址.URL重写使用定义的规则进行评估 ...

  3. 【MyLocations】标记位置App开发体会

    实现功能: 1.能通过Cora Location获取地址信息 2.用户获取地址信息后能编辑相关信息 3.使用Core Data保存数据 4.使用MapKit,在Map上显示标记的位置,并可以编辑位置信 ...

  4. jquery.validate 以alert方式显示错误方法

    $.validator.setDefaults({ submitHandler: function() { alert("submitted!");return false; } ...

  5. html标记语言 --格式标记

    html标记语言 --格式标记 一.格式标记 1.<br>单标记,强制换行标记,让后面的文字.图片.表格等显示在下一行 2.<p>换段落标记 3.<center>居 ...

  6. android scrollview listview显示不全

    原来处理方法是重写ListView import android.content.Context; import android.util.AttributeSet; import android.v ...

  7. Html常用标记总结

    超文本标记语言的结构包括“头”部分(英语:Head).和“主体”部分(英语:body),其中“头”部提供关于网页的信息,“主体”部分提供网页的具体内容. Web页面绝大多数都是由html所编写的. 一 ...

  8. opencv+python视频实时质心显示

    利用opencv+python实现以下功能: 1)获取实时视频,分解帧频: 2)将视频做二值化处理: 3) 将视频做滤波处理(去除噪点,获取准确轮廓个数): 4)识别图像轮廓: 5)计算质心: 6)描 ...

  9. html相关标记的含义

    HTML标记含义1.<html>...</html> :html 文档标记2.<head>...</head> :文档头标记3.<title> ...

随机推荐

  1. STM32 IIC双机通信—— HAL库硬件IIC版

    参考传送门 关于IIC的原理这里我就不多说了,网上有很多很好的解析,如果要看我个人对IIC的理解的话,可以点击查看,这里主要讲一下怎样利用STM32CubeMx实现IIC的通讯,经过个人实践,感觉HA ...

  2. 极路由4pro(HC5962)设置阿里云DDNS

    v2ex有个帖子说用Dnspod的API可以一行搞定,不过我既然买的是阿里云的域名还是想尽量用阿里云的API,感觉比较安全,另外修改解析记录后也会自动发邮件通知,所以还是调用阿里云的API吧.阿里云的 ...

  3. 代理模式之cglib动态代理

    上一篇博客说了实现InvocationHandler接口的jdk动态代理,还有一种实现动态代理的方式则是:通过继承的方式实现的cglib动态代理. 先在程序中导入cglib的包,cglib-nodep ...

  4. 自己主动化測试程序之中的一个自己定义键盘的模拟測试程序(C语言)

    一.測试程序编写说明 我们做的终端设备上运行的是QT应用程序.使用自己定义的键盘接口.经过測试人员长时间的人机交互測试,来确认系统的功能是否满足需求. 如今须要编写一个自己主动化的測试程序,能够依照预 ...

  5. 非典型的scala程序及其编译后的结果

    初学Scala Folder structure以及部分代码 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2xldmVyd3lx/font/5a6L5L ...

  6. iOS开发UI调试神器----Reveal

    做iOS的开发,UI是非常非常重要的一环.调试时我们一般用模拟器,提交前用真机做測试.用模拟器来调试UI效果尽管快捷方便,但有时仍然希望有更强大的工具来帮助分析UI,尤其是专注在UI的效果调试时.近期 ...

  7. DICOM医学图像处理:fo-dicom网络传输之 C-Echo and C-Store

    背景: 上一篇博文对DICOM中的网络传输进行了介绍.主要參照DCMTK Wiki中的英文原文.通过对照DCMTK与fo-dicom两个开源库对DICOM标准的详细实现,对理解DICOM标准有一个更直 ...

  8. android官网被封掉了,仅仅好用这个站点进谷歌了!嘎嘎

         http://developer.android.com/sdk/index.html    这个能够进去.可是必须是搜狐 .360,uc都不用特意FQ     http://173.1 ...

  9. UVA - 10689 Yet another Number Sequence 矩阵快速幂

                      Yet another Number Sequence Let’s define another number sequence, given by the foll ...

  10. swoole-简单的异步执行

    swoole-简单的异步执行 标签(空格分隔): php 理解 一个IO操作其实分成了两个步骤:发起IO请求和实际的IO操作. 阻塞IO和非阻塞IO的区别在于第一步,发起IO请求是否会被阻塞,如果阻塞 ...