您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關Android中怎么通過自定義View實現橫行時間軸效果,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
一、已經有很多 RecycleView 實現時間軸的例子,為何還要費勁的使用自定義 view 去實現時間軸?
根據上圖可以總結出以下幾點:
每個階段要顯示時間、階段名、狀態圖標、中間有虛線;文字上下交錯顯示;相鄰階段的文字在垂直方向上是可以相交的;時間軸的個數不確定,但是要鋪滿屏幕并且不可滑動; 如果只實現上兩點的效果,使用 RecycleView 無疑是最好的選擇,但是要同時實現以上整個效果目前想到的最好的辦法就是使用自定義 view。
二、如何開始?
相信也有人跟我一樣,對自定義的繪制過程 view、canvas、path、paint 的使用有了解,但是真的要去寫自定義 view 確不知道從何開始,不知道第一步如何下手。我個人的總結就是:想要的太多,遲遲不動手,所以有想法一定要去動手試驗! 不要想著寫完第一次運行就是最終想展示的完美效果,而是要抱著整體拆分成不重復的小塊,然后去繪制重復塊,然后去一點點實現一步步完美的心態才能做出來。
所以首先要把想實現的 view 拆分成一個個小的可繪制的并且沒有重復的塊,以目前想實現的時間軸效果來說,最小可繪制無重復塊也就是只包括一個時間結點的塊如圖:
它包括:
垂直居中的一條虛線;一個表示狀態的圖標;一個顯示時間的文本塊;一個顯示階段名的文本塊;
三、開始畫
有了上面的分析,接下來就要開始畫了。
1. 畫中間的線
首先畫虛線,如果虛線不知道怎么畫,可以先畫一條實線,然后再去找畫虛線的方法。
使用 canvas 中畫線的方法 drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint)
根據參數得知需知道線的起點與終點坐標以及一個 paint 對象,因為是垂直居中且橫穿整個控件的直線所以可以確定兩個點的 y 坐標是一樣的,也就是控件高的一半,起點的 x 坐標為0,終點的 x 坐標為控件的寬。也就是知道控件的寬和高之后就可以繪制出這條線。獲取控件的寬高,可以在 onMeasure 方法中獲取:
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mViewWidth = MeasureSpec.getSize(widthMeasureSpec) - dip2px(mContext, mSafeDistance * 2); mViewHeight = MeasureSpec.getSize(heightMeasureSpec);}
畫線的代碼(在 onDraw 方法中添加,下面其它的繪制方法同樣是在 onDraw 方法中添加):
// 定義畫筆,并設置相關屬性Paint mLinePaint = new Paint();mLinePaint.setColor(Color.parseColor("#999999"));mLinePaint.setStrokeWidth(1);mLinePaint.setStyle(Paint.Style.STROKE);// 畫虛線canvas.drawLine(0, mViewHeight / 2, mViewWidth, mViewHeight / 2, mLinePaint);
2. 畫圖標
canvas 畫圖標的方法:drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint),根據方法的參數去分析如何準備值,這里需要一個 bitmap 對象,起點坐標以及 paint。bitmap 對象可以將資源文件 drawable 轉為 bitmap 格式;坐標就是控件的中心點。畫圖標的代碼:
// 圖標 x,y 坐標Bitmap statusBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_no_pass);float bX = mViewWidth / 2;// 垂直的中心點在圖標的頂部,所以要減去 bitmap 高的一半float bY = mViewHeight / 2 - statusBitmap.getHeight() / 2f;Paint mBitmapPaint = new Paint();mBitmapPaint.setFilterBitmap(true);canvas.drawBitmap(statusBitmap, bX, bY, mBitmapPaint);
3. 畫文本
canvas 畫文本的方法:drawText(@NonNull String text, float x, float y, @NonNull Paint paint),依然是根據方法得知需要知道繪制的內容,開始的坐標點以及 paint。當文本在圖標上方時,文本的 y 坐標需要使用圖標的 y 坐標減去文本到圖標的距離,x 坐標同圖片的 x 坐標一樣;當文本在圖標下方時,文本的 y 坐標需要使用圖標的 y 坐標加上文本到圖標的距離。畫文本的代碼:
// 定義畫筆Paint mDatePaint = new Paint();mDatePaint.setColor(Color.parseColor("#666666"));mDatePaint.setTextSize(dip2px(mContext, 12));mDatePaint.setStyle(Paint.Style.FILL);mDatePaint.setTextAlign(Paint.Align.CENTER);mDatePaint.setAntiAlias(true);Paint mNamePain = new Paint();mNamePain.setColor(Color.parseColor("#666666"));mNamePain.setTextSize(dip2px(mContext, 13));mNamePain.setStyle(Paint.Style.FILL);mNamePain.setTextAlign(Paint.Align.CENTER);mNamePain.setAntiAlias(true);// 定義坐標變量float dateX = bX + statusBitmap.getWidth() / 2f;float dateY;dateY = mViewHeight / 2 - dip2px(mContext, 19);// 畫文字,在圖標上canvas.drawText("有效時間", dateX, dateY, mNamePain);canvas.drawText("09.27-09.29", dateX, dateY - dateTextHeight mDatePaint);// 畫文字,在圖標下dateY = mViewHeight / 2 + dip2px(mContext, 19);canvas.drawText("09.27-09.29", dateX, dateY, mDatePaint);canvas.drawText("有效時間", dateX, dateY + dateTextHeigh, mNamePain);
4. 由局部到整體
上面已經完成了只有一個時間點的繪制,接下來思考如果有多個時間點時如何繪制。只有一個時間點時計算坐標是以控件的寬高進行計算,那么當有兩個時間點的時候需要首先把控件均分成兩部分,然后在均分的部分中計算對應的坐標,完成繪制。當有三個時間點的時候需要均分為三部分,然后在各自的部分計算對應的坐標,完成繪制。所以得到不論時間點的個數有多少繪制的方法不會改變,需要改變的是繪制時候用到的點的坐標。其實已經可以看出,當多個點的時候需要循環一下,代碼如下:
// 得到多個點時,其中每個部分的寬,itevW 也就等同與上面只有一個時間點時控件的寬float itemW = mViewWidth / mDataList.size();for (int i = 0; i < mDataList.size(); i++) { // 完成相關計算、繪制}
看完上述內容,你們對Android中怎么通過自定義View實現橫行時間軸效果有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。