@mSolo
2015-04-10T13:44:09.000000Z
字数 5391
阅读 1905
Android
Java
设计模式
参考资料:《Expert Android》 + 《Android Programming Pushing》
目的 -> 获取 View 的大小和位置。该阶段包含两个子过程:onMeasure() + onLayout()
在 View 类中 onMeasure() 的默认实现
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
另一种自定义实现
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
getImprovedDefaultWidth(widthMeasureSpec),
getImprovedDefaultHeight(heightMeasureSpec));
}
private int getImprovedDefaultHeight(int measureSpec) {
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
return hGetMaximumHeight();
case MeasureSpec.EXACTLY:
return specSize;
case MeasureSpec.AT_MOST:
return hGetMinimumHeight();
}
// shouldn't come here
Log.e(tag,"unknown specmode");
return specSize;
}
protected int hGetMinimumHeight() {
return this.getSuggestedMinimumHeight();
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
int w = this.getWidth();
int h = this.getHeight();
int t = this.getTop();
int l = this.getLeft();
int ox = w/2;
int oy = h/2;
int rad = Math.min(ox,oy)/2;
canvas.drawCircle(ox, oy, rad, getBrush());
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:circleViewPkg="http://schemas.android.com/apk/res/com.androidbook.custom"
....
<com.androidbook.custom.CircleView
android:id="@+id/circle_view_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
circleViewPkg:strokeWidth="5"
circleViewPkg:strokeColor="@android:color/holo_red_dark"
/>
</LinearLayout>
...
<resources>
<declare-styleable name="CircleView">
<attr name="strokeWidth" format="integer"/>
<attr name="strokeColor" format="color|reference" />
</declare-styleable>
</resources>
...
publicCircleView(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
//Use the array constant to read the bag once
TypedArray t = context.obtainStyledAttributes(attrs,
R.styleable.CircleView,
defStyle, 0);
strokeColor = t.getColor(R.styleable.CircleView_strokeColor, strokeColor);
strokeWidth = t.getInt(R.styleable.CircleView_strokeWidth, strokeWidth);
//Recycle the typed array
t.recycle();
initCircleView();
}
出处:https://github.com/mSoloYu/StyleNumberProgressBar
以桥接(Bridge)设计模式改造 NumberProgressbar 库文件;
在第 1 步基础上,实现更多 Progressbar 的定制;
attrs.xml 的改变
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="NumberProgressBar">
<attr name="progress" format="integer"/>
<attr name="progress_unreached_color" format="color"/>
<attr name="progress_reached_color" format="color"/>
<attr name="progress_reached_bar_size" format="dimension"/>
<attr name="progress_unreached_bar_size" format="dimension"/>
<attr name="progress_text_size" format="dimension"/>
<attr name="progress_text_color" format="color"/>
<attr name="progress_text_offset" format="dimension"/>
<attr name="progress_timeline" format="string" />
<attr name="progress_text" format="string" />
<attr name="progress_shape" format="enum">
<enum name="horizontal_default" value="0" />
<enum name="vertical_default" value="1" />
<enum name="horizontal_timeline" value="2" />
<enum name="vertical_timeline" value="3" />
<enum name="pie_default" value="4" />
</attr>
</declare-styleable>
</resources>
View.java(AOSP)
StyleNumberProgressBar.java
TemplateTextProgressShape.java
TextHoriTimelineProgressBar.java
TextHorizontalProgressBar.java
TextVerticalProgressBar.java
TextPieProgressBar.java