日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Android開發自定義控件之折線圖實現方法詳解

瀏覽:60日期:2022-09-24 09:49:53

本文實例講述了Android開發自定義控件之折線圖實現方法。分享給大家供大家參考,具體如下:

前言

折線圖是Android開發中經常會碰到的效果,但由于涉及自定義View的知識,對許多剛入門的小白來說會覺得很高深。其實不然,接下來我就以盡量通俗的語言來說明下圖折線圖效果的實現過程。

效果圖

Android開發自定義控件之折線圖實現方法詳解

實現過程

首先,選擇自定義控件的方式。

自定義控件的實現有四種方式:

1.繼承View,重寫onDraw、onMeasure等方法。2.繼承已有的View(比如TextView)。3.繼承ViewGroup實現自定義布局。4.繼承已有的ViewGroup(比如LinearLayout)。

由于我們不需要多個控件進行組合,也不需要在原有控件基礎上改造,故我們采用第1種方式即繼承View來實現。代碼如下,新建一個ChartView類繼承自View,并實現他的幾個構造方法,并重寫onDraw和onMeasure方法,因為我們要在onDraw方法里面進行繪制工作,并且我希望這個控件的長寬是相等的,所以在onMeasure方法設置寬高相等。設置長寬相等的方式很簡單,我們不需要自己去測量實現,只需要調用父類的onMeasure方法,傳參數(寬高值)時將都傳入寬度(或者高度)即可。

public class ChartView extends View { public ChartView(Context context) { super(context); } public ChartView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public ChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, widthMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); }}

其次,繪制簡單圖形并顯示出來。

在進行繪制之前,我們要進行若干初始化工作,其中就包括畫筆的初始化。然后就可以進行繪制了,我們先繪制一個簡單的圓圈,然后將控件放到布局文件中,運行看看效果。

ChartView代碼

public class ChartView extends View { // 畫筆 private Paint paint; /** * 構造函數 */ public ChartView(Context context) { super(context); initWork(); } /** * 構造函數 */ public ChartView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); initWork(); } /** * 構造函數 */ public ChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initWork(); } /** * 初始化工作 */ private void initWork() { initPaint(); } /** * 畫筆設置 */ private void initPaint() { paint = new Paint(Paint.ANTI_ALIAS_FLAG); // 畫筆樣式為填充 paint.setStyle(Paint.Style.FILL); // 顏色設為紅色 paint.setColor(Color.RED); // 寬度為3像素 paint.setStrokeWidth(3); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, widthMeasureSpec); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 畫圓 canvas.drawCircle(300,300,100,paint); }}

activity_main.xml

<?xml version='1.0' encoding='utf-8'?><android.support.constraint.ConstraintLayout xmlns:android='http://schemas.android.com/apk/res/android' android:layout_width='match_parent' android:layout_height='match_parent' <com.toprs.linechart.ChartView android:layout_width='match_parent' android:layout_height='match_parent'/></android.support.constraint.ConstraintLayout>

效果:

Android開發自定義控件之折線圖實現方法詳解

然后,繪制圖表。

到目前為止,已經實現了最簡單的一個自定義控件,雖然它什么功能都沒有,只是簡單顯示一個紅色圓圈,但本質都是一樣的。接下來就開始圖表的繪制。

1.初始化一些需要使用的值。

// 刻度之間的距離 private int degreeSpace;

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 控件上下左右邊界四至及控件的寬度(同時也是高度!) int left = getLeft(); int right = getRight(); int top = getTop(); int bottom = getBottom(); int w = getWidth(); // 圖表距離控件邊緣的距離 int graphPadding = w / 10; // 圖表上下左右四至 int graphLeft = left + graphPadding; int graphBottom = bottom - graphPadding; int graphRight = right - graphPadding; int graphTop = top + graphPadding; // 圖表寬度(也等同高度奧~) int graphW = graphRight - graphLeft; // 刻度之間的距離 degreeSpace = graphW / 8; }

2.灰色背景

// 背景 canvas.drawColor(Color.LTGRAY);

3.坐標系

// 畫筆設置樣式為STROKE樣式,即只劃線不填充 paint.setStyle(Paint.Style.STROKE); // 坐標系繪制 Path pivotPath = new Path(); //Y軸 pivotPath.moveTo(graphLeft, graphBottom); pivotPath.lineTo(graphLeft, graphTop); //Y軸箭頭 pivotPath.lineTo(graphLeft - 12, graphTop + 20); pivotPath.moveTo(graphLeft, graphTop); pivotPath.lineTo(graphLeft + 12, graphTop + 20); //X軸 pivotPath.moveTo(graphLeft, graphBottom); pivotPath.lineTo(graphRight, graphBottom); //X軸箭頭 pivotPath.lineTo(graphRight - 20, graphBottom + 12); pivotPath.moveTo(graphRight, graphBottom); pivotPath.lineTo(graphRight - 20, graphBottom - 12); canvas.drawPath(pivotPath, paint);

4.刻度虛線及數字

// Y軸刻度虛線 for (int i = 1; i < 8; i++) { Path yKeduPath = new Path(); // 線 paint.setColor(Color.WHITE); paint.setStrokeWidth(1); paint.setStyle(Paint.Style.STROKE); paint.setPathEffect(new DashPathEffect(new float[]{5,5},0)); yKeduPath.moveTo(graphLeft, graphBottom - i * degreeSpace); yKeduPath.lineTo(graphRight, graphBottom - i * degreeSpace); canvas.drawPath(yKeduPath, paint); // 數字 paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.FILL); paint.setTextSize(25); paint.setPathEffect(null); canvas.drawText(i + '', graphPadding / 2, graphBottom - i * degreeSpace, paint); } // X軸刻度虛線 for (int i = 1; i < 8; i++) { Path xKeduPath = new Path(); // 線 paint.setColor(Color.WHITE); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(1); paint.setPathEffect(new DashPathEffect(new float[]{5,5},0)); xKeduPath.moveTo(graphLeft + i * degreeSpace, graphBottom); xKeduPath.lineTo(graphLeft + i * degreeSpace, graphTop); canvas.drawPath(xKeduPath, paint); // 數字 paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.FILL); paint.setTextSize(25); paint.setPathEffect(null); canvas.drawText(i + '', graphLeft + i * degreeSpace, graphBottom + graphPadding / 2, paint); }

5.折線

在繪制折線之前,我們先要初始化幾個參數。

// 模擬數據 private float[] data = {3.2f, 4.3f, 2.5f, 3.2f, 3.8f, 7.1f, 1.3f, 5.6f}; // 當前顯示的數據數量 private int showNum=1;

// 折線 Path linePath = new Path(); for (int i = 0; i < showNum; i++) { int toPointX = graphLeft + i * degreeSpace; int toPointY = graphBottom - ((int) (data[i] * degreeSpace)); paint.setColor(Color.YELLOW); paint.setStyle(Paint.Style.STROKE); if (i==0){ linePath.moveTo(toPointX,toPointY); }else { linePath.lineTo(toPointX, toPointY); } // 節點圓圈 canvas.drawCircle(toPointX, toPointY,10,paint); paint.setColor(Color.WHITE); paint.setStyle(Paint.Style.FILL); canvas.drawCircle(toPointX,toPointY,7,paint); } paint.setColor(Color.YELLOW); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(3); canvas.drawPath(linePath, paint);

6.讓圖表動起來

為了實現數據依次顯現的動畫,我們開啟一個線程是當前顯示的數據數量即showNum變量不斷加一,并間隔時間0.5秒。然后postInvalidate()重繪即可。

private void initWork() { initPaint(); // 開啟線程,沒隔0.5秒showNum加一 new Thread(new Runnable() { @Override public void run() {while (true){ if (showNum<data.length){ showNum++; }else { showNum=1; } // 重繪 postInvalidate(); // 休眠0.5秒 try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }} } }).start(); }

好了,運行一下,便會實現上面的效果了。如果你覺得效果不夠炫酷或者功能太少,那就自己完善吧~~

結語

由于自定義控件是Android進階路上必然要碰到的知識,所以希望大家重視。其實自定義控件說難也難說簡單也簡單。實現一些普通的效果還是很方便的,像這次舉的例子,但如果要實現各種炫酷效果并且要完善各種功能的話,就需要各種知識的配合了,包括數學、物理、繪圖等知識。所以還是需要平時不斷積累的,看到別人的控件很棒的時候自己可以試著去實現一下,對自己的知識庫不斷進行補充,自然會嫻熟的運用。本人也是菜鳥一枚,望共勉!!

更多關于Android相關內容感興趣的讀者可查看本站專題:《Android控件用法總結》、《Android開發入門與進階教程》、《Android視圖View技巧總結》、《Android編程之activity操作技巧總結》、《Android數據庫操作技巧總結》及《Android資源操作技巧匯總》

希望本文所述對大家Android程序設計有所幫助。

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美搞黄网站| 成人午夜亚洲| 婷婷激情综合| 久久精品播放| 99久久久久久中文字幕一区| 欧美精品高清| 激情欧美国产欧美| 成人羞羞视频播放网站| 亚洲人成在线网站| 电影亚洲精品噜噜在线观看 | 久久亚洲精精品中文字幕| 国产精品九九| 伊人久久国产| 亚洲第一区色| 亚洲欧美激情诱惑| 亚洲va久久| 国产探花一区在线观看| 国产极品久久久久久久久波多结野| 国产精品色在线网站| 精品久久福利| 国产一区二区三区亚洲综合| 欧洲av一区二区| 国产农村妇女精品一二区| 午夜久久av | 蜜桃久久av一区| 天堂va在线高清一区| 欧美成人一二区| 日韩一区电影| 视频一区在线播放| 国产精品视频一区二区三区四蜜臂| 国产一区二区三区成人欧美日韩在线观看| 中文字幕人成乱码在线观看 | 欧美日韩日本国产亚洲在线| 蜜臀av在线播放一区二区三区| 青青伊人久久| а√在线中文在线新版| 91成人精品视频| 日本一区中文字幕| 麻豆久久久久久| 久久久一本精品| 中文字幕亚洲在线观看| 麻豆精品视频在线观看视频| 亚洲一级少妇| 中文字幕一区二区三区日韩精品 | 久久国产精品免费一区二区三区 | 91精品啪在线观看国产爱臀| 91亚洲国产高清| 国产亚洲一区在线| 国产精品第十页| 亚洲婷婷免费| 国产精品久久久亚洲一区| 成人羞羞视频播放网站| 亚洲91在线| 91欧美日韩| 视频一区免费在线观看| 国产精品一国产精品| 91成人精品| 国产精品久久久久久av公交车| 精品在线99| 国产精品一线天粉嫩av| 欧美日韩激情在线一区二区三区| 日韩综合小视频| 人人精品亚洲| 国产精品亚洲人成在99www| 蜜桃成人av| 久久99精品久久久久久园产越南| 亚洲激情中文| 国产一区二区亚洲| 四虎精品永久免费| 日本高清不卡一区二区三区视频| 日本中文字幕视频一区| 久久在线电影| 国产中文字幕一区二区三区| 日韩有码av| 国内精品福利| 国精品产品一区| 人人爱人人干婷婷丁香亚洲| 不卡中文字幕| 国内揄拍国内精品久久| 日韩国产欧美在线播放| 免费av一区二区三区四区| 九九99久久精品在免费线bt| 日韩中文av| 9国产精品视频| 国产一区二区视频在线看| 中文字幕日韩欧美精品高清在线| 天堂а√在线最新版中文在线| 日韩二区在线观看| 亚洲免费一区二区| 99精品网站| 国产成年精品| 国产精品一区二区精品视频观看| 蜜臀久久99精品久久久久久9| 精品捆绑调教一区二区三区 | 国产精品成人a在线观看| 日韩av午夜在线观看| 国产精品美女久久久| 在线手机中文字幕| 欧美a一区二区| 欧美色综合网| 中文字幕亚洲在线观看| 99视频精品| 免费国产自久久久久三四区久久| 色婷婷亚洲mv天堂mv在影片| 免费在线播放第一区高清av| 欧美精品观看| 日韩欧美美女在线观看| 免费观看在线色综合| 日韩视频在线一区二区三区| 91精品蜜臀一区二区三区在线| 91青青国产在线观看精品| 麻豆成人91精品二区三区| 日本精品久久| 日韩一区二区三区在线看| 亚洲一区二区成人| 最新亚洲激情| 亚州av乱码久久精品蜜桃| 99精品一区| 亚洲二区免费| 欧美亚洲国产精品久久| 国内精品99| 一区二区视频欧美| 中文亚洲免费| 视频一区免费在线观看| 日韩精品一二区| 视频一区视频二区在线观看| 石原莉奈在线亚洲三区| 首页国产欧美日韩丝袜| 蜜桃久久av| 亚洲一区二区小说| 免费久久99精品国产| 免费的成人av| 亚洲精品系列| 欧美一区激情| 久久av电影| 国产精品久久久久蜜臀| 亚洲精品.com| 亚洲福利精品| 99热精品在线| 蜜桃av一区二区| 日本一不卡视频| 国产日韩高清一区二区三区在线 | 嫩呦国产一区二区三区av| 国产精品任我爽爆在线播放| 麻豆视频久久| 在线精品亚洲欧美日韩国产| 久久久久久久久久久妇女| 欧美不卡视频| 在线综合亚洲| 日本在线不卡视频| 国产精品极品国产中出| 福利在线免费视频| 欧美日韩亚洲在线观看| 伊人久久亚洲美女图片| 亚洲伊人精品酒店| 国产精品久久久久久久久久妞妞| 国产成人免费| 欧美精品一区二区久久| 中文字幕日韩亚洲| 国产精品久久乐| 欧美精品高清| 蜜桃久久久久久久| 国产精品porn| 久久国产毛片| 日韩中文字幕| 国产黄大片在线观看| 中文日韩在线| 国产欧美精品| а√在线中文在线新版| 国产国产精品| 久久精品av麻豆的观看方式| 国产伦久视频在线观看| 亚洲一区二区三区免费在线观看| 欧美在线日韩| 午夜欧美巨大性欧美巨大| 首页亚洲欧美制服丝腿| 国产精久久久| 中文欧美日韩| 国产精品.xx视频.xxtv| 欧美不卡在线| 国产欧美视频在线| 久久青草久久| 日韩综合小视频| 在线天堂资源www在线污| 免费观看在线色综合| 精品国产亚洲一区二区在线观看| 九一成人免费视频| 97久久精品| 亚洲高清不卡| 国产精品免费大片| 亚洲激情欧美| 精品国产不卡| 免费在线欧美视频| 中文字幕成在线观看| 亚洲精品少妇| 亚洲手机视频| 麻豆国产欧美一区二区三区| 亚洲中字黄色| 国产在线日韩精品| 亚洲另类av|