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í)慣來(lái),我習(xí)慣用view的尺寸當(dāng)做參照,來(lái)約束界面的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的使用,沒(méi)有什么技術(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來(lái)個(gè)star就更好了謝謝!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android利用Intent.ACTION_SEND進(jìn)行分享
這篇文章主要介紹了Android利用Intent.ACTION_SEND進(jìn)行分享,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05
Android 個(gè)人理財(cái)工具一:項(xiàng)目概述與啟動(dòng)界面的實(shí)現(xiàn)
本文主要介紹Android 開(kāi)發(fā)個(gè)人理財(cái)工具項(xiàng)目概述與啟動(dòng)界面的實(shí)現(xiàn),這里主要對(duì)實(shí)現(xiàn)項(xiàng)目的流程做了詳細(xì)概述,并對(duì)啟動(dòng)界面簡(jiǎn)單實(shí)現(xiàn),有需要的小伙伴可以參考下2016-08-08
Fiddler實(shí)現(xiàn)手機(jī)抓包之小白入門必看
這篇文章主要介紹了Fiddler實(shí)現(xiàn)手機(jī)抓包之小白入門必看篇,需要的朋友可以參考下2018-03-03
Android重復(fù)引用多個(gè)場(chǎng)景報(bào)錯(cuò)的問(wèn)題解決
本文主要介紹了Android重復(fù)引用多個(gè)場(chǎng)景報(bào)錯(cuò)的問(wèn)題解決,主要介紹了5種情況,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03
PagerSlidingTabStrip制作Android帶標(biāo)簽的多界面滑動(dòng)切換
這篇文章主要介紹了使用PagerSlidingTabStrip制作Android帶標(biāo)簽的多界面滑動(dòng)切換效果的方法,PagerSlidingTabStrip是GitHub上的一個(gè)開(kāi)源項(xiàng)目,調(diào)用這個(gè)庫(kù)可以少寫不少代碼XD 需要的朋友可以參考下2016-04-04
android自定義ListView實(shí)現(xiàn)底部View自動(dòng)隱藏和消失的功能
本篇文章主要介紹了android自定義ListView實(shí)現(xiàn)底部View自動(dòng)隱藏和消失的功能 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03
Android基于socket實(shí)現(xiàn)的簡(jiǎn)單C/S聊天通信功能
這篇文章主要介紹了Android基于socket實(shí)現(xiàn)的簡(jiǎn)單C/S聊天通信功能,結(jié)合實(shí)例形式分析了Android使用socket實(shí)現(xiàn)客服端與服務(wù)器端數(shù)據(jù)的發(fā)送與接收處理技巧,需要的朋友可以參考下2016-10-10

