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. MD5加密技术

    前几天,在看OpenVXI3.4的时候,偶然发现了几个奇怪的文件,那就是OpenVXI-3.4\src\cache下面的,base64.c,base64.h,md5.c,md5.h.既然有人把源代码给 ...

  2. ASP.NET-dropdownlist默认值

    可以在第三个选项中定义一个默认值,但是返回数据的时候就不需要这种类似"请选择名称"之类的提示了,所以在构造seleclt option的时候,要在option中的属性中加上sele ...

  3. 洛谷 P1825 [USACO11OPEN]玉米田迷宫Corn Maze

    P1825 [USACO11OPEN]玉米田迷宫Corn Maze 题目描述 This past fall, Farmer John took the cows to visit a corn maz ...

  4. 【转载】How to Reset USB Device in Linux

    USB devices are anywhere nowadays, even many embedded devices replace the traditional serial devices ...

  5. 拿到offer过后--大学最后时光最想做的那十件事

    昨天--2014.10.26,历史性的一刻,激动的签了欢聚时代(YY)的前端开发offer,工作地点是我喜欢的珠海(仅仅由于那边有我所向往的海还有自行车队,如今想想都乐开怀了,绕着海边骑单车的感觉真妙 ...

  6. 基于redis ae实现 Linux中的文件系统监控机制(inotify)

    (英文部分为转的.代码是个人代码) 1 What's inotify  The inotify API provides a mechanism for monitoring file system ...

  7. 【iOS开发-30】UITabBarController的几种代理方法以及结合NSUserDefaults还原上次退出时被选中视图控制器和视图控制器的顺序

    一.UITabBarController的几种代理方法 在AppDelegate.h中加入一个协议<UITabBarControllerDelegate>.然后再AppDelegate.m ...

  8. 继承QWidget的派生类控件不能设置QSS问题解决(使用style()->drawPrimitive(QStyle::PE_Widget,也就是画一个最简单最原始的QWidget,不要牵扯其它这么多东西)

    自定义控件时基类用了QWidget,发现qss设置不起作用,需要重载其paintEvent函数即可: 如下代码: void CCustomWidget::paintEvent(QPaintEvent* ...

  9. iOS:简单使用UIAlertVIew和UIActionSheet

    做iOS开发的同学想必都用过UIAlertVIew或者UIActionSheet.UIAlertVIew 可以弹出一个出现在屏幕中间的提示视图,给用户展示信息,并让用户自己选择操作,UIActionS ...

  10. ES transport client底层是netty实现,netty本质上是异步方式,但是netty自身可以使用sync或者await(future超时机制)来实现类似同步调用!因此,ES transport client可以同步调用也可以异步(不过底层的socket必然是异步实现)

    ES transport client底层是netty实现,netty本质上是异步方式,但是netty自身可以使用sync或者await(future超时机制)来实现类似同步调用! 因此,ES tra ...