Space源碼分析
簡介
public final class Space extends View
Space是一個輕量的View,可以在布局中被用來創建間隙,常用于布局優化。
介于可能很多人根本不知道Space的存在!所以稍微提一下它的使用場景,比如以下場景的右側小三角,就可以使用Space:
在兩個三角之間放置一個 Space ,兩三角分別位于它的上下,控制它的高度就能控制三角之間的間隔。
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_marginRight="2dp"
>
<ImageView
android:id="@+id/iv_price_up"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/divider"
android:background="@drawable/price_up"
android:layout_marginBottom="1dp"
/>
<Space
android:layout_width="wrap_content"
android:layout_height="1dp"
android:id="@+id/divider"
android:layout_centerInParent="true"
/>
<ImageView
android:id="@+id/iv_price_down"
android:layout_marginTop="1dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/divider"
android:background="@drawable/price_down"
/>
</RelativeLayout>
</code></pre>
構造方法分析
看第一個構造方法即可。
// 最終都會調用這個構造方法
publicSpace(Context context, AttributeSet attrs,intdefStyleAttr,intdefStyleRes){
super(context, attrs, defStyleAttr, defStyleRes);
// 如果是VISIBLE 則改為 INVISIBLE
if (getVisibility() == VISIBLE) {
setVisibility(INVISIBLE);
}
}
publicSpace(Context context, AttributeSet attrs,intdefStyleAttr){
this(context, attrs, defStyleAttr, 0);
}
publicSpace(Context context, AttributeSet attrs){
this(context, attrs, 0);
}
publicSpace(Context context){
//noinspection NullableProblems
this(context, null);
}
```
跟ViewStub類似,Space在構造方法里做了一些操作:當可見性為VISIBLE的時候,把它改為INVISIBLE了。
由于Space方法非常少,接下去直接都分析了。
其余方法分析
</code></pre>
/**
- Draw nothing.
*
- @param canvas an unused parameter.
*/
@Override
public void draw(Canvas canvas) {
//空方法
}
/**
- Compare to: {@link View#getDefaultSize(int, int)}
- If mode is AT_MOST, return the child size instead of the parent size
-
(unless it is too big).
*/
private static int getDefaultSize2(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: //wrap_content 返回更小的值
result = Math.min(size, specSize);
break;
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
<p>@Override</p>
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// getSuggestedMinimumWidth() 根據minWidth以及背景的寬度來返回
setMeasuredDimension(
getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));
}
```
Space跟ViewStub一個套路, draw() 都為空方法,然后重寫 onMeasure ,相比ViewStub,Space代碼更加比較簡單。
另外一般我們使用Space都是會指定寬高,大部分走的是 EXACTLY的流程。
要點
- Space 用來做間隙非常有用
- Space 默認為不可見(invisible),但是有寬高,會占據空間。
- 布局文件中設置 VISIBLE 無效。
小結
ViewStub跟Space作為Android布局優化的常用手段,有著一些同樣的思路值得我們去學習:
- 不繪制(減少overDraw)
- 優化或者不參與測量與布局(提高整體布局的渲染速度)
來自:http://yifeiyuan.me/2016/12/29/analyze-space/