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. HTML---经常使用标签总结与实践

    什么是HTML? 超文本标记语言,标准通用标记语言下的一个应用.    "超文本"就是指页面内能够包括图片.链接,甚至音乐.程序等非文字元素. 超文本标记语言的结构包含" ...

  2. POJ 2154

    这题的时间卡的.... 必须用欧拉来优化,而且要加素数表.最重要是,因为最后结果要/n,而数据很大,所以,必须在之前就先/n了,否则会爆数据. #include <iostream> #i ...

  3. JVM的重排序

    重排序一般是编译器或执行时环境为了优化程序性能而採取的对指令进行又一次排序执行的一种手段.重排序分为两类:编译期重排序和执行期重排序,分别相应编译时和执行时环境. 在并发程序中,程序猿会特别关注不同进 ...

  4. Educational Codeforces Round 6 B. Grandfather Dovlet’s calculator 暴力

    B. Grandfather Dovlet’s calculator   Once Max found an electronic calculator from his grandfather Do ...

  5. JAVA设计模式之【建造者模式】

    建造者模式 建造者模式为客户端返回的不是一个简单的产品,而是一个由多个部件组成的复杂产品 角色 Builder抽象建造者 buildPartX getResult ConcreteBuilder具体建 ...

  6. nyoj--514--1的个数(贪心)

     1的个数 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 给你两个数a和b,你的任务是计算出1在a和b之间出现的次数,比如说,如果a=1024,b=1032,那么a ...

  7. Linux换行符相关

    Linux和windows中的换行符差异问题LINUX的换行符在Windows记事本打开不换行或出现黑点是由于Linux和windows中的换行符差异问题造成的. Unix系统里,每行结尾只有“< ...

  8. Gradle学习总结

    Gradle学习系列 (1). Gradle快速入门 (2). 创建Task的多种方法 (3). 读懂Gradle语法 (4). 增量式构建 (5). 自定义Property (6). 使用java ...

  9. CSS3的常用属性(二)

    边框 边框圆角 border-radius: 100px 每个角可以设置两个值,x和y 补充: 可分别设置长,短半径,以“/”进行分隔,遵循顺时针的顺序,“/”之前为横轴半径,“/”之后为纵轴半径,如 ...

  10. 问题集锦 ~ jQuery

    #addClass失败 $target.addClass('show'); show 这个单词可能和内部某处起冲突了吧,有时成功有时失败,只能换个class名了,难受……