Android view自定義帶文字帶進(jìn)度的控件
目標(biāo):自定義一個(gè)帶文字帶進(jìn)度的控件,具體內(nèi)容如下
效果圖:
不啰嗦先看東西:
步驟分析
提取自定義屬性
//提供對(duì)外暴露的屬性,如有不夠自己擴(kuò)展 <declare-styleable name="DescProgressView"> <attr name="dpv_text_normal_color" format="color" /> <attr name="dpv_text_seleced_color" format="color" /> <attr name="dpv_text_size" format="dimension" /> <attr name="dev_progress_bg_color" format="color" /> <attr name="dev_progress_small_circle_color" format="color" /> <attr name="dev_progress_big_circle_color" format="color" /> </declare-styleable>
解析自定義屬性
private void initAttrs(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DescProgressView, defStyleAttr, R.style.Def_DescProgressViewStyle); int indexCount = typedArray.getIndexCount(); for (int i = 0; i < indexCount; i++) { int attr = typedArray.getIndex(i); switch (attr) { case R.styleable.DescProgressView_dpv_text_normal_color: textNormalColor = typedArray.getColor(attr, Color.BLACK); break; case R.styleable.DescProgressView_dpv_text_seleced_color: textSelectedColor = typedArray.getColor(attr, Color.BLACK); break; case R.styleable.DescProgressView_dpv_text_size: dpvTextSize = typedArray.getDimensionPixelSize(attr, 0); break; case R.styleable.DescProgressView_dev_progress_bg_color: dpvProgressBgColor = typedArray.getColor(attr, Color.BLACK); break; case R.styleable.DescProgressView_dev_progress_small_circle_color: dpvSmallCicleColor = typedArray.getColor(attr, Color.BLACK); break; case R.styleable.DescProgressView_dev_progress_big_circle_color: dpvBigCircleColor = typedArray.getColor(attr, Color.BLACK); break; } } typedArray.recycle(); }
測(cè)量UI圖的比例(包含圖標(biāo)大小比例,位置比例)
//這里大家可以根據(jù)自己的習(xí)慣來,我習(xí)慣用view的尺寸當(dāng)做參照,來約束界面的view,各有利弊,也可以暴露出屬性設(shè)置具體的dp值,根據(jù)比例的話,調(diào)整好比例后,所有的繪制內(nèi)容會(huì)統(tǒng)一約束 private static final float SCALE_OF_PROGRESS_HEIGHT = 70.F / 120; private static final float SCALE_OF_TOP_AND_BOTTOM_PADDING = 10.F / 120; private static final float SCALE_OF_LEFT_AND_RIGHT_PADDING = 20.F / 120; private static final float SCALE_OF_TEXT_DESC_CONTAINER = 50.F / 120; private static final float SCALE_OF_BIG_CIRCLE_HEIGHT = 22.F / 120; private static final float SCALE_OF_SMALL_CIRCLE_HEIGHT = 16.F / 120; private static final float SCALE_OF_LINE_HEIGHT = 4.F / 120; private static final float DEF_VIEW_HEIGHT = 120.F;
提取繪制的各個(gè)元素的位置屬性坐標(biāo)等
這個(gè)view的唯一要提前確定的就是文字的位置,文字的位置確定需要知道所有文字的長(zhǎng)度,左右間距,計(jì)算出中間的白色間隔
代碼如下
/** * 獲取文字在畫布中的位置 */ private void getDescTextRegonPoint() { for (int i = 0; i < descs.size(); i++) { Point textRegonPoint = new Point(); int sumX = 0; //非常重要:計(jì)算各個(gè)文字在view中的具體坐標(biāo),體會(huì)下這個(gè)二級(jí)for循環(huán),子循環(huán)是確定每個(gè)描述文本的位置 for (int j = 0; j < i; j++) { Point tempSum = allDescTextPoints.get(j); sumX += tempSum.x; } sumX += i * getTextDescSpace(); textRegonPoint.x = sumX + leftAndRightPadding; textRegonPoint.y = dpViewHeight - topAndBottomPadding - textDescContainerHeight / 2; textPoints4Draw.add(textRegonPoint); } }
/** * 獲取文字的間距 * * @return 獲取文字的間距 */ private float getTextDescSpace() { float allDescWith = 0; for (Point tempDesc : allDescTextPoints) { allDescWith += tempDesc.x; } int textContainerW = (int) (dpViewWidth - leftAndRightPadding * 2 - allDescWith); if (descs != null && descs.size() > 1) { int spaceCount = descs.size() - 1; return textContainerW * 1.F / spaceCount; } return 0; }
繪制
我們?cè)趘iew測(cè)量確定了尺寸完畢之后,直接繪制即可
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { // 確定各個(gè)比例的大小 super.onSizeChanged(w, h, oldw, oldh); dpViewHeight = h; dpViewWidth = w; progressContainerHeight = (int) (SCALE_OF_PROGRESS_HEIGHT * dpViewHeight); topAndBottomPadding = (int) (SCALE_OF_TOP_AND_BOTTOM_PADDING * dpViewHeight); leftAndRightPadding = (int) (SCALE_OF_LEFT_AND_RIGHT_PADDING * dpViewHeight); textDescContainerHeight = (int) (SCALE_OF_TEXT_DESC_CONTAINER * dpViewHeight); smallCircleRadio = (int) (SCALE_OF_SMALL_CIRCLE_HEIGHT * dpViewHeight / 2); bigCircleRadio = (int) (SCALE_OF_BIG_CIRCLE_HEIGHT * dpViewHeight / 2); lineHeight = (int) (SCALE_OF_LINE_HEIGHT * dpViewHeight); // 獲取各個(gè)部分所需要的約束坐標(biāo) getDescTextWidthAndHeight(); getDescTextRegonPoint(); getBgLineRectF(); getBgCirclePoints(); getSelectedRectF(); getColorFullRectF(); getGrayRectF(); }
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawDescText(canvas); drawBgLine(canvas); drawSelectedLine(canvas); drawGrayRectF(canvas); drawSelectedCircles(canvas); } //繪制部分的代碼就是canvas 的API的使用,沒有什么技術(shù)含量. //最后暴露給外面設(shè)置數(shù)據(jù)的接口 public void setProgressDescs(List<String> descs, int currentSelectPosition) { this.currentSelectPosition = currentSelectPosition; if (descs != null && descs.size() > 1) { this.descs.clear(); this.descs.addAll(descs); this.allDescTextPoints.clear(); invalidate(); } }
源代碼下載地址https://github.com/GuoFeilong/DescPbView來個(gè)star就更好了謝謝!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android SDK Manager更新、下載速度慢問題解決辦法
這篇文章主要介紹了Android SDK Manager更新、下載速度慢問題解決辦法的相關(guān)資料,需要的朋友可以參考下2017-05-05使用Jetpack Compose實(shí)現(xiàn)翻轉(zhuǎn)卡片效果流程詳解
Jetpack Compose 是一款基于 Kotlin 的聲明式 UI 工具包,可以方便地創(chuàng)建漂亮的用戶界面。使用 Compose 的動(dòng)畫 API 和可繪制 API,可以輕松實(shí)現(xiàn)翻轉(zhuǎn)卡片效果。通過設(shè)置旋轉(zhuǎn)角度和透明度等屬性,可以使卡片沿著 Y 軸翻轉(zhuǎn),并實(shí)現(xiàn)翻頁效果2023-05-05Android Mms之:對(duì)話與聯(lián)系人關(guān)聯(lián)的總結(jié)詳解
本篇文章是對(duì)Android中對(duì)話與聯(lián)系人的關(guān)聯(lián)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05Android Service服務(wù)詳細(xì)介紹及使用總結(jié)
這篇文章主要介紹了Android Service 服務(wù)的詳細(xì)資料,網(wǎng)上關(guān)于Android Service 服務(wù)的文章比較多,但是不是很全面,不夠細(xì)致,畢竟是Android 四大組件之一,重要性不用說,這里總結(jié)下,需要的朋友可以參考下2016-12-12Android沉浸式狀態(tài)欄設(shè)計(jì)的實(shí)例代碼
本篇文章主要介紹了Android沉浸式狀態(tài)欄設(shè)計(jì)的實(shí)例代碼,整理了詳細(xì)的代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07android獲取相冊(cè)圖片和路徑的實(shí)現(xiàn)方法
這篇文章主要介紹了android獲取相冊(cè)圖片和路徑的實(shí)現(xiàn)方法,本文介紹的是Android4.4后的方法,感興趣的小伙伴們可以參考一下2016-04-04