MPAndroidChart系列源码解读(四)
来源:互联网 发布:php date 取小时分钟 编辑:程序博客网 时间:2024/05/16 05:07
由于个人能力有限,不能再跟着仔细看源码了,感觉每个类关联甚多,决定直接从chart下手了
public abstract class Chart<T extends ChartData<? extends IDataSet<? extends Entry>>> extends ViewGroup implements ChartInterface { public Chart(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } protected void init() { setWillNotDraw(false);//如果自定义View重新onDraw方法不执行,调用该方法可以解决问题 // setLayerType(View.LAYER_TYPE_HARDWARE, null); if (android.os.Build.VERSION.SDK_INT < 11)//图表的动画走版本分之 mAnimator = new ChartAnimator(); else mAnimator = new ChartAnimator(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { // ViewCompat.postInvalidateOnAnimation(Chart.this); postInvalidate(); } }); //下面这些相关类在前面两篇blog都或多或少的有提到 // initialize the utils Utils.init(getContext()); mDefaultFormatter = new DefaultValueFormatter(1); mViewPortHandler = new ViewPortHandler(); mLegend = new Legend(); mLegendRenderer = new LegendRenderer(mViewPortHandler, mLegend); mXAxis = new XAxis(); // 初始化画笔配置 mDescPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mDescPaint.setColor(Color.BLACK); mDescPaint.setTextAlign(Align.RIGHT); mDescPaint.setTextSize(Utils.convertDpToPixel(9f)); mInfoPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mInfoPaint.setColor(Color.rgb(247, 189, 51)); // orange mInfoPaint.setTextAlign(Align.CENTER); mInfoPaint.setTextSize(Utils.convertDpToPixel(12f)); mDrawPaint = new Paint(Paint.DITHER_FLAG); if (mLogEnabled) Log.i("", "Chart.init()"); }}
自定义ViewGroup,不同的Chart传入不同的数据Data,实现ChartInterface接口,在前面的博客有提到具体方法含义。setData方法调用更新数据集,刷新视图
public void setData(T data) { if (data == null) { Log.e(LOG_TAG, "Cannot set data for chart. Provided data object is null."); return; } // LET THE CHART KNOW THERE IS DATA mOffsetsCalculated = false; mData = data; // calculate how many digits are needed calculateFormatter(data.getYMin(), data.getYMax()); for (IDataSet set : mData.getDataSets()) { if (Utils.needsDefaultFormatter(set.getValueFormatter())) set.setValueFormatter(mDefaultFormatter); } // let the chart know there is new data notifyDataSetChanged(); if (mLogEnabled) Log.i(LOG_TAG, "Data is set."); }
setData的内部调用抽象方法notifyDataSetChanged方法,在具体的Chart类型具体实现,通过刷新引起onDraw方法的重绘,达到跟新视图的目的。clear方法清除数据,还定义了几个抽象方法,用于具体的Chart类型自己具体实现,比如calculateOffsets方法根据边界范围计算偏移量。
/** * calculates the offsets of the chart to the border depending on the * position of an eventual legend or depending on the length of the y-axis * and x-axis labels and their position */ protected abstract void calculateOffsets(); /** * calcualtes the y-min and y-max value and the y-delta and x-delta value */ protected abstract void calcMinMax(); /** * calculates the required number of digits for the values that might be * drawn in the chart (if enabled), and creates the default-value-formatter */ protected void calculateFormatter(float min, float max) { float reference = 0f; if (mData == null || mData.getXValCount() < 2) { reference = Math.max(Math.abs(min), Math.abs(max)); } else { reference = Math.abs(max - min); } int digits = Utils.getDecimals(reference); mDefaultFormatter = new DefaultValueFormatter(digits); }
如果mData数据集为空,会绘制相应的文字告知用户。
@Override protected void onDraw(Canvas canvas) { // super.onDraw(canvas); if (mData == null) { boolean hasText = !TextUtils.isEmpty(mNoDataText); boolean hasDescription = !TextUtils.isEmpty(mNoDataTextDescription); float line1height = hasText ? Utils.calcTextHeight(mInfoPaint, mNoDataText) : 0.f; float line2height = hasDescription ? Utils.calcTextHeight(mInfoPaint, mNoDataTextDescription) : 0.f; float lineSpacing = (hasText && hasDescription) ? (mInfoPaint.getFontSpacing() - line1height) : 0.f; // if no data, inform the user float y = (getHeight() - (line1height + lineSpacing + line2height)) / 2.f + line1height; if (hasText) { canvas.drawText(mNoDataText, getWidth() / 2, y, mInfoPaint); if (hasDescription) { y = y + line1height + lineSpacing; } } if (hasDescription) { canvas.drawText(mNoDataTextDescription, getWidth() / 2, y, mInfoPaint); } return; } //.................. }
drawMarkers方法是用于触摸弹出效果显示触摸区域的值,具体这块的View自定义控件在上篇有提到。saveToPath方法保存图表的截图到Sdcard(实例在Simple中有)同类型方法略,ViewGroup大小发生变化会引起onSizeChanged回调,这里面会调用notifyDataSetChanged方法刷新视图,setHardwareAccelerationEnabled设置硬件加速
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (mLogEnabled) Log.i(LOG_TAG, "OnSizeChanged()"); if (w > 0 && h > 0 && w < 10000 && h < 10000) { mViewPortHandler.setChartDimens(w, h); if (mLogEnabled) Log.i(LOG_TAG, "Setting chart dimens, width: " + w + ", height: " + h); for (Runnable r : mJobs) { post(r); } mJobs.clear(); } notifyDataSetChanged(); super.onSizeChanged(w, h, oldw, oldh); } /** * Setting this to true will set the layer-type HARDWARE for the view, false * will set layer-type SOFTWARE. * * @param enabled */ public void setHardwareAccelerationEnabled(boolean enabled) { if (android.os.Build.VERSION.SDK_INT >= 11) { if (enabled) setLayerType(View.LAYER_TYPE_HARDWARE, null); else setLayerType(View.LAYER_TYPE_SOFTWARE, null); } else { Log.e(LOG_TAG, "Cannot enable/disable hardware acceleration for devices below API level 11."); } }
onDetachedFromWindow方法调用unbindDrawables方法,取消View以及子View的所有监听,以免内存泄漏
private void unbindDrawables(View view) { if (view.getBackground() != null) { view.getBackground().setCallback(null); } if (view instanceof ViewGroup) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { unbindDrawables(((ViewGroup) view).getChildAt(i)); } ((ViewGroup) view).removeAllViews(); } }
以上几篇blog对于个人来说就是打基础,以便于得心应手的玩转Chart,如果在没看过该库的大体结构,个人感觉是蒙的,不知从何下手,只知道官方simple照着抄,以上相关blog有任何问题欢迎指教留言,我也是个逗比中的菜逼,千万跟我较真!!
- MPAndroidChart系列源码解读(四)
- MPAndroidChart系列源码解读(一)
- MPAndroidChart系列源码解读(二)
- MPAndroidChart系列源码解读(三)
- MPAndroidChart系列源码解读(五)
- Tomcat源码解读系列(四)——Tomcat类加载机制概述
- Tomcat源码解读系列(四)——Tomcat类加载机制概述
- py-faster-rcnn源码解读系列(四)——anchor_target_layer.py
- Tomcat源码解读系列(四)——Tomcat类加载机制概述
- Alamofire源码解读系列(四)之参数编码(ParameterEncoding)
- Alamofire源码解读系列(四)之参数编码(ParameterEncoding)
- Alamofire源码解读系列(四)之参数编码(ParameterEncoding)
- 深入理解JAVA集合系列四:ArrayList源码解读
- Alamofire源码解读系列(四)之参数编码(ParameterEncoding)
- AFNetwork 3.0 源码解读(四)AFURLResponseSerialization
- jquery3.0源码解读(四)Callbacks
- THUCTC源码解读(四)
- openlayers4源码解读系列
- Mybaits---关于关联表数据查询
- MPAndroidChart系列源码解读(二)
- React表单组建
- Android Studio上打的包在arm64位机器上找不到对应的so库
- MPAndroidChart系列源码解读(三)
- MPAndroidChart系列源码解读(四)
- Twemproxy安装使用
- 通过GeoIP2分析访问者IP获取地理位置信息
- MPAndroidChart系列源码解读(五)
- 利用JMX来监控大部分java应用
- Android 显示空页面工具类
- Android 智能问答机器人的实现
- CSS基础(六):浮动深入
- Oracle 11g 新特性数据库用户密码区分大小写参数sec_case_sensitive_logon对sys无效