Android實(shí)現(xiàn)折線走勢圖
本文實(shí)例為大家分享了Android折線走勢圖的具體代碼,供大家參考,具體內(nèi)容如下
先來看看效果圖
可以根據(jù)球的數(shù)量動態(tài)的改變自己的球半徑,以及線寬
代碼實(shí)現(xiàn)也是超級簡單
//獲取自定義屬性 private void obtainStyledAttrs(AttributeSet attrs) { TypedArray typedArray = getContext().obtainStyledAttributes(attrs,R.styleable.High_LowChartView); mTextSize = (int)typedArray.getDimension(R.styleable.High_LowChartView_hl_chart_textsize,mTextSize); mTextColor = typedArray.getColor(R.styleable.High_LowChartView_hl_chart_textcolor,mTextColor); if (typedArray.getString(R.styleable.High_LowChartView_hl_hchart_text)!=null){ mHighText = typedArray.getString(R.styleable.High_LowChartView_hl_hchart_text); } if(typedArray.getString(R.styleable.High_LowChartView_hl_hchart_text)!=null){ mLowText = typedArray.getString(R.styleable.High_LowChartView_hl_hchart_text); } mHighPointColor = typedArray.getColor(R.styleable.High_LowChartView_hl_chart_high_pointcolor,mHighPointColor); mLowPointColor = typedArray.getColor(R.styleable.High_LowChartView_hl_chart_low_pointcolor,mLowPointColor); mMainLineColor = typedArray.getColor(R.styleable.High_LowChartView_hl_chart_mianlinecolor,mMainLineColor); mChartLineColor = typedArray.getColor(R.styleable.High_LowChartView_hl_chart_chartlinecolor,mChartLineColor); mChartDistance = (int) typedArray.getDimension(R.styleable.High_LowChartView_hl_chart_distance,mChartDistance); init(); typedArray.recycle(); } //重寫onMeasure @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = measureHeight(heightMeasureSpec); setMeasuredDimension(width,height); } //計(jì)算view需要的高度 private int measureHeight(int heightMeasureSpec) { int result = 0; int mode = MeasureSpec.getMode(heightMeasureSpec); int size = MeasureSpec.getSize(heightMeasureSpec); if(mode == MeasureSpec.EXACTLY){//如果給了具體值則直接用 result=size; }else { //否則高度等于字高與球直徑的最大值 textHeight = (mPaint.descent()-mPaint.ascent()); float halfHeight = Math.max(textHeight, mPointMaxHeight) / 2; result = (int) (halfHeight+mChartDistance); //如果模式為AT_MOST即:測量高度不能超過父類給定的高度則取測量結(jié)果與size的最小值 if(mode==MeasureSpec.AT_MOST){ result = Math.min(result,size); } } return result; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(!initMeasure()) return; canvas.save(); //1先畫兩條主線 mPaint.setColor(mMainLineColor); mPaint.setStrokeWidth(mainLineHeight); //high Line canvas.drawLine(textWidth+DEFAULT_OFFSETTING,mainLinePosition,w,mainLinePosition,mPaint); //low Line canvas.drawLine(textWidth+DEFAULT_OFFSETTING,mainLinePosition+mChartDistance,w,mainLinePosition+mChartDistance,mPaint); //2再畫文字 mPaint.setColor(mTextColor); mPaint.setTextAlign(Paint.Align.LEFT); Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); RectF rt1=new RectF(0,mainLinePosition-textHeight/2,w,mainLinePosition+textHeight/2); int baseline = (int) ((rt1.bottom + rt1.top - fontMetrics.bottom - fontMetrics.top) / 2); canvas.drawText(mHighText,0,baseline,mPaint); canvas.drawText(mLowText,0,baseline+mChartDistance,mPaint); //3初始化小球圓心 canvas.translate(textWidth+DEFAULT_OFFSETTING,0); for (int i=0;i<mPointNum;i++){ //high point if (mList.get(i).isHighPoint){ // mPaint.setColor(mHighPointColor); // canvas.drawCircle((pointHeight/2+offsetX)+i*(pointHeight+offsetX), mainLinePosition, pointHeight/2, mPaint); //存入小球的圓心坐標(biāo) mList.get(i).setXY((pointHeight/2+offsetX)+i*(pointHeight+offsetX),mainLinePosition); }else { //low point // mPaint.setColor(mLowPointColor); // canvas.drawCircle((pointHeight/2+offsetX)+i*(pointHeight+offsetX), mainLinePosition+mChartDistance, pointHeight/2, mPaint); mList.get(i).setXY((pointHeight/2+offsetX)+i*(pointHeight+offsetX),mainLinePosition+mChartDistance); } } //4連接小球 if(mList.size()>=2){ mPaint.setColor(mChartLineColor); mPaint.setStrokeWidth(chartLineWidth); for (int i=0;i<mPointNum-1;i++){ canvas.drawLine(mList.get(i).cx,mList.get(i).cy,mList.get(i+1).cx,mList.get(i+1).cy,mPaint); } } //5繪制小球(為了不讓線遮蓋小球) for (int i=0;i<mPointNum;i++){ //high point if (mList.get(i).isHighPoint){ mPaint.setColor(mHighPointColor); //low point }else { mPaint.setColor(mLowPointColor); } canvas.drawCircle(mList.get(i).cx, mList.get(i).cy, pointHeight/2, mPaint); } canvas.restore(); } /** * 根據(jù)小球數(shù)量去動態(tài)測量一些屬性 * @return */ private boolean initMeasure() { //根據(jù)傳進(jìn)來的point數(shù)量計(jì)算小點(diǎn)的大小,MainLine的線寬,折線的線寬 /* 如果小球數(shù)量在1-10個,主線高度為3dip * 如果小球數(shù)量在10-20個,主線高度設(shè)置為2dip * 如果小球數(shù)量超過20個,主線高度設(shè)置為1dp */ mPointNum=mList.size(); // if(mPointNum==0) return false; if(10>mPointNum){ mainLineHeight=dp2px(3); }else if(10<=mPointNum&&20>mPointNum){ mainLineHeight = dp2px(2); }else { mainLineHeight = dp2px(1); } //主線長度等于總寬度-(文字寬度+30px) textWidth=Math.max(mPaint.measureText(mHighText),mPaint.measureText(mLowText)); mainLineWidth = (int) (w-(textWidth+DEFAULT_OFFSETTING)); /*小球直徑應(yīng)該由主線長度與小球數(shù)量決定*/ //理想直徑 float ideaDia = mainLineWidth / (mPointNum + (mPointNum + 1)); //小球直徑不能大于最大直徑 if(ideaDia>mPointMaxHeight){ // Log.i("TTT","ideaDia>mPointMaxHeight"); pointHeight = mPointMaxHeight; offsetX=(mainLineWidth-mPointNum*pointHeight)/(mPointNum+1); //(極端情況)如果小球直徑小于線高,為小球直徑+2px }else if(ideaDia<=mainLineHeight){ // Log.i("TTT","ideaDia<=mPointMaxHeight"); pointHeight = mainLineHeight+2; offsetX=(mainLineWidth-mPointNum*pointHeight)/(mPointNum+1); }else { // Log.i("TTT"," pointHeight=offsetX=ideaDia"); pointHeight=offsetX=ideaDia; } //主線位置 mainLinePosition = (h-mChartDistance)/2; //折線寬度 chartLineWidth = mainLineHeight/2; return true; } //刷新小球集合 public void setPointList(List<AiyingPoint> list){ if (list==null&&list.size()==0) return; mList.clear(); if (list.size()>150) { mList.addAll(list.subList(0,150)); } else { mList.addAll(list); } invalidate(); }
使用示例
<com.android.view.High_LowChartView android:id="@+id/hl_chart" android:layout_below="@+id/tv_state" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:layout_width="match_parent" android:layout_height="70dp" app:hl_chart_mianlinecolor="#CDCDCD" app:hl_chart_distance="55dp" app:hl_chart_low_pointcolor="#999999" app:hl_chart_high_pointcolor="#F70919" app:hl_chart_textsize="13sp" app:hl_chart_textcolor="#2f2f2f" app:hl_chart_chartlinecolor="#999999" />
好了這樣折線圖就繪制完成了,是不是很簡單呢?
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android自定義可左右滑動和點(diǎn)擊的折線圖
- Android繪制動態(tài)折線圖
- Android自定義控件實(shí)現(xiàn)折線圖
- Android HelloChart開源庫圖表之折線圖的實(shí)例代碼
- Android MPAndroidChart開源庫圖表之折線圖的實(shí)例代碼
- Android開發(fā)實(shí)現(xiàn)繪制淘寶收益圖折線效果示例
- Android自定義View簡易折線圖控件(二)
- 詳解Android圖表 MPAndroidChart折線圖
- Android自定義View實(shí)現(xiàn)折線圖效果
- Android開發(fā)之天氣趨勢折線圖
- MPAndroidChart開源圖表庫的使用介紹之餅狀圖、折線圖和柱狀圖
相關(guān)文章
Flutter實(shí)戰(zhàn)之自定義日志打印組件詳解
這篇文章主要介紹了Flutter實(shí)戰(zhàn)之自定義日志打印組件詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03Android持久化技術(shù)之文件的讀取與寫入實(shí)例詳解
這篇文章主要介紹了Android持久化技術(shù)之文件的讀取與寫入操作,結(jié)合實(shí)例形式較為詳細(xì)的分析講述了Android持久化操作的相關(guān)技巧與具體實(shí)現(xiàn)方法,需要的朋友可以參考下2016-01-01Android 動態(tài)菜單實(shí)現(xiàn)實(shí)例代碼
這篇文章主要介紹了Android 動態(tài)菜單實(shí)現(xiàn)實(shí)例代碼的相關(guān)資料,這里附有實(shí)例代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下2017-01-01Android 實(shí)現(xiàn)云知聲版離線語音合成
這篇文章主要介紹了Android 實(shí)現(xiàn)云知聲版離線語音合成,目前云知聲提供免費(fèi)的離線TTS,功能也比較簡單,合成的語音也比較生硬,如果對合成的語音要求不高的話可以考慮接入。具體合成需要的小伙伴可以參考下面文章內(nèi)容2022-06-06Flutter Widget移動UI框架使用Material和密匙Key實(shí)戰(zhàn)
這篇文章主要為大家介紹了Flutter Widget移動UI框架使用Material和密匙Key實(shí)戰(zhàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12揭秘雙十一手機(jī)淘寶圖標(biāo)如何被動態(tài)更換
這篇文章主要介紹了每到雙十一十二的時候Android手機(jī)動態(tài)更換手機(jī)圖標(biāo)的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08Android Canvas和Bitmap結(jié)合繪圖詳解流程
在 Android Canvas 上繪圖非常難,在繪圖時需要理解許多不同的類和概念。這篇文章中,將介紹 Android 框架中可用的一些類,它們可以讓畫布使用時更輕松2021-11-11