1、重用< include/>
< include>標籤可以在一個佈局中引入另外一個佈局,做到佈局的重用
如下代碼是項目中的一個公共的標題欄佈局title_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:background="@color/common_title_background">
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:src="@drawable/ic_menu_back" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textColor="@color/white"
android:textSize="@dimen/common_text_size_36"
tools:text="@string/app_task_title" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:gravity="center"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:textColor="@color/white"
android:textSize="@dimen/common_text_size_32"
tools:text="@string/filter_title" />
</RelativeLayout>
Preview:
接下來就可以在其他佈局中重用這個佈局了,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="@layout/title_bar"/>
</Relativelayout>
2、合併
減少嵌套
-
在不影響層級深度的情況下,使用LinearLayout而不是RelativeLayout。因爲RelativeLayout會讓子View調用2次onMeasure,LinearLayout 在有weight時,纔會讓子View調用2次onMeasure。Measure的耗時越長那麼繪製效率就低。
-
如果非要是嵌套,那麼儘量避免RelativeLayout嵌套RelativeLayout。這將是惡性循環。
<merge/>
-
子視圖不需要指定任何針對父視圖的佈局屬性。
-
假如需要在LinearLayout裏面嵌入一個佈局,而這個佈局的根節點也是LinearLayout,這樣就多了一層沒有用的嵌套,無疑這樣只會拖慢程序速度。而這個時候如果我們使用merge根標籤就可以避免那樣的問題。
例如我們可以將之前的佈局替換成下面的:
<?xml version="1.0" encoding="utf-8"?>
<merge
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="@layout/title_bar"/>
</merge>
我們可以通過Android Studio的View Hierarchy工具來查看比較這兩個佈局文件的區別。
3、按需載入ViewStub
每天的開發過程中經常遇到這樣的情況,根據不同的條件來決定哪些View顯示以及隱藏,通常我們的做法是將其加入到佈局中設置其不可見,用的時候在設置可見,這樣的話是會創建view的,並無形中影響了性能。
其實我們可以用ViewStub來替換,他是一個輕量級的View,不佔佈局的位置,而且佔用的資源很小。
例如,我們有個重複的開關,默認進入是關閉的,打開後可以選擇開始時間和結束時間,佈局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Switch
android:id="@+id/switch_repeat"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:padding="@dimen/left_margin"
android:text="@string/repeat"
android:textSize="@dimen/common_text_size_36" />
<ViewStub
android:id="@+id/view_datetime_picker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:inflatedId="@+id/view_datetime_picker"
android:layout="@layout/view_datetime_picker" />
</LinearLayout>
在activity或者fragment中的用法:mSwitchButton.setOnCheckedChangeListener(
new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
if (datePickView == null) {
ViewStub viewStub = (ViewStub) ContactRemindSettingActivity.this
.findViewById(
R.id.view_datetime_picker);
datePickView = viewStub.inflate();
}
datePickView.setVisibility(View.VISIBLE);
} else {
if (datePickView != null) {
datePickView.setVisibility(View.GONE);
}
}
}
});
4、巧用LinearLayout自帶分割線
一般我們的設置頁面都會有很多條目,每個條目之間都是有一根分割線的,一般很多的人做法是用一個view來佔據空間,其實我們可以用LinearLayout的分割線,代碼如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@drawable/divider"
android:orientation="vertical"
android:showDividers="beginning|end|middle">
<TextView
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:background="@color/white"
android:drawableLeft="@drawable/ic_personal_invitation"
android:drawablePadding="@dimen/left_margin"
android:drawableRight="@drawable/icon_message_more"
android:gravity="center_vertical"
android:padding="@dimen/left_margin"
android:text="未完成事項"
android:textSize="@dimen/common_text_size_36" />
<TextView
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:background="@color/white"
android:drawableLeft="@drawable/ic_personal_notice"
android:drawablePadding="@dimen/left_margin"
android:drawableRight="@drawable/icon_message_more"
android:gravity="center_vertical"
android:padding="@dimen/left_margin"
android:text="未完成事項"
android:textSize="@dimen/common_text_size_36" />
<TextView
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:background="@color/white"
android:drawableLeft="@drawable/ic_personal_opinion"
android:drawablePadding="@dimen/left_margin"
android:drawableRight="@drawable/icon_message_more"
android:gravity="center_vertical"
android:padding="@dimen/left_margin"
android:text="檢查更新"
android:textSize="@dimen/common_text_size_36" />
</LinearLayout>
效果圖:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="1dp"
android:height="1dp" />
<solid android:color="@color/divider_color" />
</shape>
showDividers是設置分割線的位置,有三個選項,diverPadding是給divider設置padding的
5、Space控件
上面的頁面如果需要將檢查更新和其他的進行分離,另成一組怎麼辦,這時Space就起作用了,相信很多人會用view或者設置topMatgin來實現。Space源碼如下,其實它在draw中未繪製任何東西,所以性能是幾乎沒有影響的,大可放心使用。
/**
* Space is a lightweight View subclass that may be used to create gaps between components
* in general purpose layouts.
*/
public final class Space extends View {
/**
* {@inheritDoc}
*/
public Space(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
if (getVisibility() == VISIBLE) {
setVisibility(INVISIBLE);
}
}
/**
* {@inheritDoc}
*/
public Space(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
/**
* {@inheritDoc}
*/
public Space(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* {@inheritDoc}
*/
public Space(Context context) {
//noinspection NullableProblems
this(context, null);
}
/**
* 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:
result = Math.min(size, specSize);
break;
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(
getDefaultSize2(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize2(getSuggestedMinimumHeight(), heightMeasureSpec));
}
}
佈局文件如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/lightgray"
android:divider="@drawable/divider"
android:orientation="vertical"
android:showDividers="beginning|end|middle">
<TextView
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:background="@color/white"
android:drawableLeft="@drawable/ic_personal_invitation"
android:drawablePadding="@dimen/left_margin"
android:drawableRight="@drawable/icon_message_more"
android:gravity="center_vertical"
android:padding="@dimen/left_margin"
android:text="未完成事項"
android:textSize="@dimen/common_text_size_36" />
<TextView
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:background="@color/white"
android:drawableLeft="@drawable/ic_personal_notice"
android:drawablePadding="@dimen/left_margin"
android:drawableRight="@drawable/icon_message_more"
android:gravity="center_vertical"
android:padding="@dimen/left_margin"
android:text="未完成事項"
android:textSize="@dimen/common_text_size_36" />
<Space
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="@color/black" />
<TextView
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
android:background="@color/white"
android:drawableLeft="@drawable/ic_personal_opinion"
android:drawablePadding="@dimen/left_margin"
android:drawableRight="@drawable/icon_message_more"
android:gravity="center_vertical"
android:padding="@dimen/left_margin"
android:text="檢查更新"
android:textSize="@dimen/common_text_size_36" />
</LinearLayout>
效果: