Android 佈局優化 include+merge+ViewStub標籤詳解
include 、merge、ViewStub標籤詳解
一.include標籤
include標籤常用於將佈局中的公共部分提取出來供其他layout使用,以實現佈局模組化。
程式碼
1.1.公共Layout
<?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="80dp" android:background="@color/app_color" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_marginTop="20dp" android:layout_height="60dp"> <RelativeLayout android:id="@+id/apptoplayout_onlyback_backlayout" android:layout_width="60dp" android:layout_height="match_parent" android:layout_alignParentLeft="true"> <ImageView android:id="@+id/apptoplayout_onlyback_imageview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:scaleType="fitCenter" android:background="@mipmap/back" /> </RelativeLayout> <TextView android:id="@+id/apptoplayout_onlyback_titletextview" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_marginTop="20dp" android:layout_alignParentRight="true" android:layout_marginRight="60dp" android:layout_toRightOf="@+id/apptoplayout_onlyback_backlayout" android:gravity="center" android:singleLine="true" android:ellipsize="end" android:textColor="@color/whilecolor" android:textSize="16sp" /> </RelativeLayout> </LinearLayout>
1.2.引入使用頁面的Layout
<?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"> <include layout="@layout/apptoplayout_onlyback" /> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/appbackground_color" android:scrollbars="none"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> ...... </LinearLayout> </ScrollView> </LinearLayout>
即:
<include layout="@layout/apptoplayout_onlyback" />
1.3.引入使用的Activity
titletextview= (TextView) findViewById(R.id.apptoplayout_onlyback_titletextview);
這樣就可以了。
注意:被引入的模組佈局父佈局要確定寬高(尤其是高)然後直接引入即可。如果不確定寬高都是(match_parent)就要在引入的時候確定寬高
多個佈局
layout1
<?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"> <Button android:id="@+id/includelayout1_button" android:layout_width="match_parent" android:layout_height="100dp" android:layout_marginTop="10dp" android:background="@color/btn_answer_normal" android:text="佈局一按鈕" android:textColor="#FFFFFF" /> </LinearLayout>
layout2
<?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="100dp"
android:orientation="vertical">
<Button
android:id="@+id/includelayout2_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/btn_gray_pressed"
android:text="佈局二按鈕"
android:layout_marginTop="10dp"
android:textColor="#FFFFFF" />
</LinearLayout>
layout3
<?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="100dp"
android:orientation="vertical">
<Button
android:id="@+id/includelayout3_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/btn_logout_normal"
android:text="佈局三按鈕"
android:layout_marginTop="10dp"
android:textColor="#FFFFFF" />
</LinearLayout>
主頁面佈局
<?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">
<include
layout="@layout/includelayout1"
android:layout_width="match_parent"
android:layout_height="100dp" />
<include layout="@layout/includelayout2" />
<include layout="@layout/includelayout3" />
</LinearLayout>
主頁面效果
主頁面使用
package wjn.com.imwithdemo.activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import wjn.com.imwithdemo.R;
public class IncludeDemoActivity extends AppCompatActivity {
private Button button1;
private Button button2;
private Button button3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_includedemo);
button1=findViewById(R.id.includelayout1_button);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(IncludeDemoActivity.this,"按鈕一被點選!",Toast.LENGTH_LONG).show();
}
});
button2=findViewById(R.id.includelayout2_button);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(IncludeDemoActivity.this,"按鈕二被點選!",Toast.LENGTH_LONG).show();
}
});
button3=findViewById(R.id.includelayout3_button);
button3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(IncludeDemoActivity.this,"按鈕三被點選!",Toast.LENGTH_LONG).show();
}
});
}
}
附:include官方文件
二.merge標籤
merge用於消除檢視層次結構中的冗餘檢視,例如根佈局是Linearlayout,那麼我們又include一個LinerLayout佈局就沒意義了,反而會減慢UI載入速度。
又或者根佈局是FrameLayout且不需要設定background或padding等屬性,可以用merge代替,因為Activity的ContentView父元素就是FrameLayout,所以可以用merge消除只剩一個。
程式碼
被引入的佈局
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<Button
android:id="@+id/includelayout1_button1"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginTop="10dp"
android:background="@color/btn_answer_normal"
android:text="佈局一按鈕一"
android:textColor="#FFFFFF" />
<Button
android:id="@+id/includelayout1_button2"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginTop="10dp"
android:background="@color/btn_green_pressed"
android:text="佈局一按鈕二"/>
</merge>
主頁面layout
<?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">
<include
layout="@layout/includelayout1" />
</LinearLayout>
主頁面效果
主頁面程式碼
package wjn.com.imwithdemo.activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import wjn.com.imwithdemo.R;
public class IncludeDemoActivity extends AppCompatActivity {
private Button button1;
private Button button2;
private Button button3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_includedemo);
button1=findViewById(R.id.includelayout1_button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(IncludeDemoActivity.this,"按鈕一被點選!",Toast.LENGTH_LONG).show();
}
});
button2=findViewById(R.id.includelayout1_button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(IncludeDemoActivity.this,"按鈕二被點選!",Toast.LENGTH_LONG).show();
}
});
}
}
主頁面父佈局是LinearLayout且垂直排布,要引入的佈局父佈局也是LinearLayout且垂直排布。這樣的話被引入的佈局父佈局完全可以修改成merge。這樣系統忽略<merge />節點並且直接新增兩個Button。
附:merge官方文件
三.ViewStub標籤
ViewStub 標籤最大的優點是當你需要時才會載入,使用他並不會影響UI初始化時的效能。各種不常用的佈局比如進度條、顯示錯誤訊息等可以使用<ViewStub />標籤,以減少記憶體使用量,加快渲染速度。
程式碼
textview佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textview_layout_textview"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/btn_gray_pressed_status"
android:textColor="#FFFFFF"
android:gravity="center"
android:text="我是TextView"/>
</LinearLayout>
imageview佈局
<?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">
<ImageView
android:id="@+id/imageview_layout_imageview"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:background="@mipmap/ic_launcher"
android:scaleType="fitXY" />
</LinearLayout>
主頁面layout
<?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">
<Button
android:id="@+id/activity_viewstubdemo_button"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/btn_login_pressed"
android:text="顯示文字"/>
<ViewStub
android:id="@+id/activity_viewstubdemo_viewstub1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout="@layout/textview_layout"/>
<ViewStub
android:id="@+id/activity_viewstubdemo_viewstub2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout="@layout/imageview_layout"/>
</LinearLayout>
主頁面效果
主頁面程式碼
package wjn.com.imwithdemo.activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewStub;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import wjn.com.imwithdemo.R;
public class ViewStubDemoActivity extends AppCompatActivity {
private Button button;
private boolean showTextViewOrImageView=false;
private ViewStub viewstub1;
private View view1;
private TextView textview;
private ViewStub viewstub2;
private View view2;
private ImageView imageview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewstubdemo);
button=findViewById(R.id.activity_viewstubdemo_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(!showTextViewOrImageView){
viewstub1=findViewById(R.id.activity_viewstubdemo_viewstub1);
if(null==view1){
view1=viewstub1.inflate();
}
textview=findViewById(R.id.textview_layout_textview);
textview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(ViewStubDemoActivity.this,"文字點選!",Toast.LENGTH_LONG).show();
}
});
button.setText("顯示文字");
showTextViewOrImageView=true;
}else{
viewstub2=findViewById(R.id.activity_viewstubdemo_viewstub2);
if(null==view2){
view2=viewstub2.inflate();
}
imageview=findViewById(R.id.imageview_layout_imageview);
imageview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(ViewStubDemoActivity.this,"圖片點選!",Toast.LENGTH_LONG).show();
}
});
button.setText("顯示圖片");
showTextViewOrImageView=false;
}
}
});
}
}
注意:
1.由於ViewStub第一次inflate的時候,就已經將需要顯示的佈局替換掉自己了,所以第二次inflate的時候,getParent()是null,所以就會報異常。解決方法是inflate()的時候將view儲存起來,然後下次判斷這個View是否為NUll,如果是null就inflate().否則就直接使用這個view。
2.也可通過以下方式獲取
findViewById(R.id.activity_viewstubdemo_viewstub2).setVisibility(View.VISIBLE);