?html
1android
<progressbar android:id=
"@+id/progressbar"
style=
"@android:style/Widget.ProgressBar.Horizontal"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:secondaryprogress=
"50"
></progressbar>
ios
雖然沒有設置android:indeterminateDrawable,可是樣式Widget.ProgressBar.Horizontal已經幫咱們設置好了。查看源碼以下:express
?apache
1canvas
2緩存
3網絡
4app
5less
6
7
8
<style name=
"Widget.ProgressBar.Horizontal"
>
<item name=
"android:indeterminateOnly"
>
false
</item>
<item name=
"android:progressDrawable"
>
@android
:drawable/progress_horizontal</item>
<item name=
"android:indeterminateDrawable"
>
@android
:drawable/progress_indeterminate_horizontal</item>
<item name=
"android:minHeight"
>20dip</item>
<item name=
"android:maxHeight"
>20dip</item>
<item name=
"android:mirrorForRtl"
>
true
</item>
</style>
先看一下progress_horizontal,源碼以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!--?xml version=
"1.0"
encoding=
"utf-8"
?-->
<!-- Copyright (C)
2008
The Android Open Source Project
Licensed under the Apache License, Version
2.0
(the
"License"
);
you may not use
this
file except in compliance with the License.
You may obtain a copy of the License at
http:
//www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an
"AS IS"
BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License
for
the specific language governing permissions and
limitations under the License.
-->
<layer-list xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<item android:id=
"@android:id/background"
>
<shape>
<corners android:radius=
"5dip"
>
<gradient android:startcolor=
"#ff9d9e9d"
android:centercolor=
"#ff5a5d5a"
android:centery=
"0.75"
android:endcolor=
"#ff747674"
android:angle=
"270"
>
</gradient></corners></shape>
</item>
<item android:id=
"@android:id/secondaryProgress"
>
<clip>
<shape>
<corners android:radius=
"5dip"
>
<gradient android:startcolor=
"#80ffd300"
android:centercolor=
"#80ffb600"
android:centery=
"0.75"
android:endcolor=
"#a0ffcb00"
android:angle=
"270"
>
</gradient></corners></shape>
</clip>
</item>
<item android:id=
"@android:id/progress"
>
<clip>
<shape>
<corners android:radius=
"5dip"
>
<gradient android:startcolor=
"#ffffd300"
android:centercolor=
"#ffffb600"
android:centery=
"0.75"
android:endcolor=
"#ffffcb00"
android:angle=
"270"
>
</gradient></corners></shape>
</clip>
</item>
</layer-list>
能夠看到,系統使用的是圖層方式,以覆蓋的方式進行的。因此若是須要其餘的樣式的話,改變系統默認的值便可,或者參考一下系統自帶的樣式設置就好了。
緊接着,說一下ProgressBar的方法,整體來講,能夠分爲兩個部分。一是和自身屬性相關的,好比獲取進度、設置進度的最大值、設置插入器等等。二是和繪製相關的部分,如圖所示:
因此、因此咱們本次最重要的部分來了,那就是如何自定義一個漂亮ProgressBar。在自定義以前,先看一下系統是如何實現的。Android下ProgressBar的代碼量不算多,除去註釋估計也就是幾百行左右。首先從構造方法看是看,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
* Create a new progress bar with range 0...100 and initial progress of 0.
* @param context the application environment
*/
public
ProgressBar(Context context) {
this
(context,
null
);
}
public
ProgressBar(Context context, AttributeSet attrs) {
this
(context, attrs, com.android.internal.R.attr.progressBarStyle);
}
public
ProgressBar(Context context, AttributeSet attrs,
int
defStyle) {
this
(context, attrs, defStyle,
0
);
}
/**
* @hide
*/
public
ProgressBar(Context context, AttributeSet attrs,
int
defStyle,
int
styleRes) {
super
(context, attrs, defStyle);
mUiThreadId = Thread.currentThread().getId();
initProgressBar();
TypedArray a =
context.obtainStyledAttributes(attrs, R.styleable.ProgressBar, defStyle, styleRes);
mNoInvalidate =
true
;
Drawable drawable = a.getDrawable(R.styleable.ProgressBar_progressDrawable);
if
(drawable !=
null
) {
drawable = tileify(drawable,
false
);
// Calling this method can set mMaxHeight, make sure the corresponding
// XML attribute for mMaxHeight is read after calling this method
setProgressDrawable(drawable);
}
mDuration = a.getInt(R.styleable.ProgressBar_indeterminateDuration, mDuration);
mMinWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_minWidth, mMinWidth);
mMaxWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_maxWidth, mMaxWidth);
mMinHeight = a.getDimensionPixelSize(R.styleable.ProgressBar_minHeight, mMinHeight);
mMaxHeight = a.getDimensionPixelSize(R.styleable.ProgressBar_maxHeight, mMaxHeight);
mBehavior = a.getInt(R.styleable.ProgressBar_indeterminateBehavior, mBehavior);
final
int
resID = a.getResourceId(
com.android.internal.R.styleable.ProgressBar_interpolator,
android.R.anim. linear_interpolator);
// default to linear interpolator
if
(resID >
0
) {
setInterpolator(context, resID);
}
setMax(a.getInt(R.styleable.ProgressBar_max, mMax));
setProgress(a.getInt(R.styleable.ProgressBar_progress, mProgress));
setSecondaryProgress(
a.getInt(R.styleable.ProgressBar_secondaryProgress, mSecondaryProgress));
drawable = a.getDrawable(R.styleable.ProgressBar_indeterminateDrawable);
if
(drawable !=
null
) {
drawable = tileifyIndeterminate(drawable);
setIndeterminateDrawable(drawable);
}
mOnlyIndeterminate = a.getBoolean(
R.styleable.ProgressBar_indeterminateOnly, mOnlyIndeterminate);
mNoInvalidate =
false
;
setIndeterminate( mOnlyIndeterminate || a.getBoolean(
R.styleable.ProgressBar_indeterminate, mIndeterminate));
mMirrorForRtl = a.getBoolean(R.styleable.ProgressBar_mirrorForRtl, mMirrorForRtl);
a.recycle();
}
樣式文件以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
R.styleable.Progre:
<declare-styleable name=
"ProgressBar"
>
<!-- Defines the maximum value the progress can take. -->
<!-- Defines the
default
progress value, between
0
and max. -->
<!-- Defines the secondary progress value, between
0
and max. This progress is drawn between
the primary progress and the background. It can be ideal
for
media scenarios such as
showing the buffering progress
while
the
default
progress shows the play progress. -->
<!-- Allows to enable the indeterminate mode. In
this
mode the progress
bar plays an infinite looping animation. -->
<!-- Restricts to ONLY indeterminate mode (state-keeping progress mode will not work). -->
<!-- Drawable used
for
the indeterminate mode. -->
<!-- Drawable used
for
the progress mode. -->
<!-- Duration of the indeterminate animation. -->
<!-- Defines how the indeterminate mode should behave when the progress
reaches max. -->
<!-- Progress starts over from
0
. -->
<
enum
name=
"repeat"
value=
"1"
>
<!-- Progress keeps the current value and goes back to
0
. -->
<
enum
name=
"cycle"
value=
"2"
>
</
enum
></
enum
></attr>
<!-- Timeout between frames of animation in milliseconds
{
@deprecated
Not used by the framework.} -->
</attr></attr></attr></attr></attr></attr></attr></attr></attr></attr></attr></attr></attr></attr></declare-styleable>
ProgressBar把三個構造方法都列出來了,並使用了遞歸調用的方式,還有一個方式就是分別在每個構造方法中都調用初始化的代碼,我的以爲仍是此處比較正規。而後看一下第三個構造方法,在這裏主要作了兩件事情,一個是從attrs文件中讀取設置的屬性;一個是initProgressBar()方法,爲ProgressBar設置一些默認的屬性值。
1
2
3
4
5
6
7
8
9
10
11
12
13
private
void
initProgressBar() {
mMax =
100
;
mProgress =
0
;
mSecondaryProgress =
0
;
mIndeterminate =
false
;
mOnlyIndeterminate =
false
;
mDuration =
4000
;
mBehavior = AlphaAnimation.RESTART;
mMinWidth =
24
;
mMaxWidth =
48
;
mMinHeight =
24
;
mMaxHeight =
48
;
}
這就是默認的屬性值。這在自定義View中算是最基礎的了,很少說,不過在這裏須要注意兩個地方。一是mUiThreadId,他是幹嗎的呢,它獲取的是當前UI線程的id,而後在更新ProgressBar進度的時候進行一個判斷,若是是UI線程,那麼直接進行更新,若是不是就post出去,使用Handler等進行更新。二是tileify(drawable, false)方法和tileifyIndeterminate(drawable)方法。這兩個方法主要是對Drawable進行一個解析、轉換的過程。在這裏須要重點強調一下,在ProgressBar中,最重要的部分就是Drawable的使用了,由於不只是它的背景包括進度等都是使用Drawable來完成的,因此在源碼中也能夠看到基本上百分之七八十的代碼都是和Drawable有關的。由於這一部分篇幅較多,因此就不詳細介紹了,下面重點說一下如何繪製ProgressBar,首先看onMeasure()方法,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Override
protected
synchronized
void
onMeasure(
int
widthMeasureSpec,
int
heightMeasureSpec) {
Drawable d = mCurrentDrawable;
int
dw =
0
;
int
dh =
0
;
if
(d !=
null
) {
dw = Math. max(mMinWidth , Math.min( mMaxWidth, d.getIntrinsicWidth()));
dh = Math. max(mMinHeight , Math.min( mMaxHeight, d.getIntrinsicHeight()));
}
updateDrawableState();
dw += mPaddingLeft + mPaddingRight;
dh += mPaddingTop + mPaddingBottom;
setMeasuredDimension( resolveSizeAndState(dw, widthMeasureSpec,
0
),
resolveSizeAndState(dh, heightMeasureSpec,
0
));
}
這是測量View大小的方法,也就是ProgressBar的大小,由於每個ProgressBar默認都會使用Drawable。因此ProgressBar的大小便是Drawable的大小加上Padding的大小,若是沒有Padding,那很顯然就是Drawable的大小。最後使用setMeasuredDimension()方法設置ProgressBar的大小。 按照正常的流程,有些朋友可能會想到重寫onLayout()方法了,可是這裏ProgressBar只是一個View,不須要進行位置的處理。因此直接進入onDraw()方法,在
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@Override
protected
synchronized
void
onDraw(Canvas canvas) {
super
.onDraw(canvas);
Drawable d = mCurrentDrawable;
if
(d !=
null
) {
// Translate canvas so a indeterminate circular progress bar with padding
// rotates properly in its animation
canvas.save();
if
(isLayoutRtl() && mMirrorForRtl) {
canvas.translate(getWidth() - mPaddingRight, mPaddingTop);
canvas.scale(-
1
.0f,
1
.0f);
}
else
{
canvas.translate(mPaddingLeft, mPaddingTop);
}
long
time = getDrawingTime();
if
( mHasAnimation) {
mAnimation.getTransformation(time, mTransformation);
float
scale = mTransformation.getAlpha();
try
{
mInDrawing =
true
;
d.setLevel((
int
) (scale * MAX_LEVEL));
}
finally
{
mInDrawing =
false
;
}
postInvalidateOnAnimation();
}
d.draw(canvas);
canvas.restore();
if
( mShouldStartAnimationDrawable && d
instanceof
Animatable) {
((Animatable) d).start();
mShouldStartAnimationDrawable =
false
;
}
}
首先也是先獲取當前的Drawable對象,若是不爲空就開始繪圖,先是一個判斷,根據佈局的方向來轉移畫布,isLayoutRtl()是View類的方法,
1
2
3
public
boolean
isLayoutRtl() {
return
(getLayoutDirection() == LAYOUT_DIRECTION_RTL);
}
這個LAYOUT_DIRECTION_RTL是LayoutDirection的一個常量,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package
android.util;
/**
* A class for defining layout directions. A layout direction can be left-to-right (LTR)
* or right-to-left (RTL). It can also be inherited (from a parent) or deduced from the default
* language script of a locale.
*/
public
final
class
LayoutDirection {
// No instantiation
private
LayoutDirection() {}
/**
* Horizontal layout direction is from Left to Right.
*/
public
static
final
int
LTR =
0
;
/**
* Horizontal layout direction is from Right to Left.
*/
public
static
final
int
RTL =
1
;
/**
* Horizontal layout direction is inherited.
*/
public
static
final
int
INHERIT =
2
;
/**
* Horizontal layout direction is deduced from the default language script for the locale.
*/
public
static
final
int
LOCALE =
3
;
}
而後再判斷有沒有動畫,若是有的話,就調用View類的postInvalidateOnAnimation()方法去執行一個動畫。最後調用Drawable對象去畫出來d.draw(canvas)。 總的來講,系統的ProgressBar是和Drawable緊密相關的,因此說,若是咱們自定義的ProgressBar和Drawable有關,那麼徹底能夠繼承於系統的ProgressBar來開發便可。若是你的自定義ProgressBar和Drawable關係不大,好比是這樣的, 其實,就不須要Drawable了,徹底能夠直接繼承於View類開發。 那下面就從兩個方面來自定義ProgressBar,1、繼承於系統ProgressBar 首先看一下上面給出的進度條其中的一個, 思路: Mini ProgressBar在原生ProgressBar的基礎上加入了一個指示器,而且有文字顯示。實現的時候能夠這樣,也就是說,自定義的ProgressBar包含了兩個部分,一部分是默認的;另外一部分是新添加的指示器。其實指示器就是一個Drawable和文本的組合,並且直接畫在系統ProgressBar的上面便可。接着,關於自定義的ProgressBar的屬性也要定義一下,好比Drawable、好比文本、好比間隔等。因此attrs文件能夠這樣來寫了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!--?xml version=
"1.0"
encoding =
"utf-8"
?-->
<resources>
<declare-styleable>
</attr>
<!-- attr-->
<!-- attr-->
</attr>
<flag name=
"normal"
value=
"0"
>
<flag name=
"bold"
value=
"1"
>
<flag name=
"italic"
value=
"2"
>
</flag></flag></flag></attr>
<flag name=
"left"
value=
"0"
>
<flag name=
"center"
value=
"1"
>
<flag name=
"right"
value=
"2"
>
</flag></flag></flag></attr>
</attr></attr></declare-styleable>
</resources>
ps:我發現eclipse在寫declare-styleable不會自動提示,不清楚什麼緣由,知道的朋友望告知。 以後咱們新建一個類繼承於ProgressBar,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* @author kince
*
*/
public
class
IndicatorProgressBar
extends
ProgressBar {
public
IndicatorProgressBar(Context context) {
this
(context,
null
);
}
public
IndicatorProgressBar(Context context, AttributeSet attrs) {
this
(context, attrs,
0
);
}
public
IndicatorProgressBar(Context context, AttributeSet attrs,
int
defStyle) {
super
(context, attrs, defStyle);
}
}
而後在第三個構造方法中初始化數據,由於用到了文本以及Drawable,因此還須要聲明全局變量,初始化完畢後代碼以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
*
*/
package
com.example.indicatorprogressbar.widget;
import
com.example.indicatorprogressbar.R;
import
android.content.Context;
import
android.content.res.TypedArray;
import
android.graphics.Color;
import
android.graphics.Paint;
import
android.graphics.Paint.Align;
import
android.graphics.drawable.Drawable;
import
android.text.TextPaint;
import
android.util.AttributeSet;
import
android.widget.ProgressBar;
/**
* @author kince
*
*/
public
class
IndicatorProgressBar
extends
ProgressBar {
private
TextPaint mTextPaint;
private
Drawable mDrawableIndicator;
private
int
offset=
5
;
public
IndicatorProgressBar(Context context) {
this
(context,
null
);
}
public
IndicatorProgressBar(Context context, AttributeSet attrs) {
this
(context, attrs,
0
);
mTextPaint=
new
TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.density=getResources().getDisplayMetrics().density;
mTextPaint.setColor(Color.WHITE);
mTextPaint.setTextSize(
10
);
mTextPaint.setTextAlign(Align.CENTER);
mTextPaint.setFakeBoldText(
true
);
}
public
IndicatorProgressBar(Context context, AttributeSet attrs,
int
defStyle) {
super
(context, attrs, defStyle);
TypedArray array=context.obtainStyledAttributes(attrs, R.styleable.IndicatorProgressBar, defStyle,
0
);
if
(array!=
null
){
mDrawableIndicator=array.getDrawable(R.styleable.IndicatorProgressBar_progressIndicator);
offset=array.getInt(R.styleable.IndicatorProgressBar_offset,
0
);
array.recycle();
}
}
}
而後,爲全局變量設置set、get方法,方便在程序中調用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public
Drawable getmDrawableIndicator() {
return
mDrawableIndicator ;
}
public
void
setmDrawableIndicator(Drawable mDrawableIndicator) {
this
.mDrawableIndicator = mDrawableIndicator;
}
public
int
getOffset() {
return
offset ;
}
public
void
setOffset(
int
offset) {
this
.offset = offset;
}
接下來,就是重寫onMeasure()、onDraw()方法了。在onMeasure()中,須要對進度條計算好具體大小,那根據上面的圖示,這個進度條的寬度和系統進度條的寬度是同樣的,也就是getMeasuredWidth();高度的話,由於加了一個指示器,因此高度是指示器的高度加上系統進度條的高度。所以在onMeasure()方法中就能夠這樣來寫:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Override
protected
synchronized
void
onMeasure(
int
widthMeasureSpec,
int
heightMeasureSpec) {
// TODO Auto-generated method stub
super
.onMeasure(widthMeasureSpec, heightMeasureSpec);
if
(mDrawableIndicator!=
null
){
//獲取系統進度條的寬度 這個寬度也是自定義進度條的寬度 因此在這裏直接賦值
final
int
width=getMeasuredWidth();
final
int
height=getMeasuredHeight()+getIndicatorHeight();
setMeasuredDimension(width, height);
}
}
/**
* @category 獲取指示器的高度
* @return
*/
private
int
getIndicatorHeight(){
if
(mDrawableIndicator==
null
){
return
0
;
}
Rect r=mDrawableIndicator.copyBounds();
int
height=r.height();
return
height;
}
而後是onDraw()方法,由於在onMeasure()方法中增長了進度條的高度,因此在畫的時候須要將系統進度條與指示器分隔開來。在進度條的樣式文件中,咱們是這樣配置的:
1
2
3
4
5
6
7
<style name=
"Widget.ProgressBar.RegularProgressBar"
>
<item name=
"android:indeterminateOnly"
>
false
</item>
<item name=
"android:progressDrawable"
>
@drawable
/progressbar </item>
<item name=
"android:indeterminateDrawable"
>
@android
:drawable/progress_indeterminate_horizontal </item>
<item name=
"android:minHeight"
>1dip</item >
<item name=
"android:maxHeight"
>10dip</item >
</style>
在android:progressDrawable的屬性中,使用的drawable是這樣的:
1
2
3
4
5
6
7
8
9
10
<layer-list xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<item android:id=
"@android:id/background"
android:drawable=
"@drawable/progressbar_bg"
>
<item android:id=
"@+id/progress"
android:drawable=
"@drawable/progressbar_bar"
>
</item>
<item android:id=
"@+id/pattern"
>
<bitmap android:src=
"@drawable/progressbar_pattern"
android:tilemode=
"repeat"
>
</bitmap></item>
</item></layer-list>
能夠發現,是一個layer類型的drawable,因此在計算大小的時候,須要特別考慮這個狀況。代碼以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if
(m_indicator !=
null
) {
if
(progressDrawable !=
null
&& progressDrawable
instanceof
LayerDrawable) {
LayerDrawable d = (LayerDrawable) progressDrawable;
for
(
int
i =
0
; i < d.getNumberOfLayers(); i++) {
d.getDrawable(i).getBounds(). top = getIndicatorHeight();
d.getDrawable(i).getBounds(). bottom = d.getDrawable(i)
.getBounds().height()
+ getIndicatorHeight();
}
}
else
if
(progressDrawable !=
null
) {
progressDrawable.getBounds(). top = m_indicator
.getIntrinsicHeight();
progressDrawable.getBounds(). bottom = progressDrawable
.getBounds().height() + getIndicatorHeight();
}
}
而後須要更新進度條的位置,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
private
void
updateProgressBar () {
Drawable progressDrawable = getProgressDrawable();
if
(progressDrawable !=
null
&& progressDrawable
instanceof
LayerDrawable) {
LayerDrawable d = (LayerDrawable) progressDrawable;
final
float
scale = getScale(getProgress());
// 獲取進度條 更新它的大小
Drawable progressBar = d.findDrawableByLayerId(R.id.progress );
final
int
width = d.getBounds(). right - d.getBounds().left ;
if
(progressBar !=
null
) {
Rect progressBarBounds = progressBar.getBounds();
progressBarBounds. right = progressBarBounds.left
+ (
int
) (width * scale +
0
.5f);
progressBar.setBounds(progressBarBounds);
}
// 獲取疊加的圖層
Drawable patternOverlay = d.findDrawableByLayerId(R.id.pattern );
if
(patternOverlay !=
null
) {
if
(progressBar !=
null
) {
// 使疊加圖層適應進度條大小
Rect patternOverlayBounds = progressBar.copyBounds();
final
int
left = patternOverlayBounds.left ;
final
int
right = patternOverlayBounds.right ;
patternOverlayBounds. left = (left +
1
> right) ? left
: left +
1
;
patternOverlayBounds. right = (right >
0
) ? right -
1
: right;
patternOverlay.setBounds(patternOverlayBounds);
}
else
{
// 沒有疊加圖層
Rect patternOverlayBounds = patternOverlay.getBounds();
patternOverlayBounds. right = patternOverlayBounds.left
+ (
int
) (width * scale +
0
.5f);
patternOverlay.setBounds(patternOverlayBounds);
}
}
}
}
最後,須要把指示器畫出來,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
if
(m_indicator !=
null
) {
canvas.save();
int
dx =
0
;
// 獲取系統進度條最右邊的位置 也就是頭部的位置
if
(progressDrawable !=
null
&& progressDrawable
instanceof
LayerDrawable) {
LayerDrawable d = (LayerDrawable) progressDrawable;
Drawable progressBar = d.findDrawableByLayerId(R.id.progress );
dx = progressBar.getBounds(). right;
}
else
if
(progressDrawable !=
null
) {
dx = progressDrawable.getBounds().right ;
}
//加入offset
dx = dx - getIndicatorWidth() /
2
- m_offset + getPaddingLeft();
// 移動畫筆位置
canvas.translate(dx,
0
);
// 畫出指示器
m_indicator .draw(canvas);
// 畫出進度數字
canvas.drawText(
m_formatter !=
null
? m_formatter .getText(getProgress())
: Math.round(getScale(getProgress()) *
100
.0f)
+
"%"
, getIndicatorWidth() /
2
,
getIndicatorHeight() /
2
+
1
, m_textPaint );
// restore canvas to original
canvas.restore();
}
源碼下載: