APP优化 布局优化

本章节讲述布局优化时三种标签的详解

 

 

一.include标签

include标签常用于将布局中的公共部分提取出来供其他layout使用,以实现布局模块化。

 

 

代码

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>

 

 

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" />

 

 

3.引入使用的Activity

titletextview= (TextView) findViewById(R.id.apptoplayout_onlyback_titletextview);

这样就可以了。

 

注意:被引入的模块布局父布局要确定宽高(尤其是高)然后直接引入即可。如果不确定宽高都是(match_parent)就要在引入的时候确定宽高

 

 

 

多个布局

4.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>

 

 

5.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>

 

 

6.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>

 

 

7.主页面布局

<?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>

 

 

8.主页面效果

 

 

9.主页面使用

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官方文档

https://developer.android.google.cn/training/improving-layouts/reusing-layouts

 

 

 

 

 

二.merge标签

merge用于消除视图层次结构中的冗余视图,例如根布局是Linearlayout,那么我们又include一个LinerLayout布局就没意义了,反而会减慢UI加载速度。又或者根布局是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity的ContentView父元素就是FrameLayout,所以可以用merge消除只剩一个。

 

 

代码

1.被引入的布局

<?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>

 

 

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/includelayout1" />

</LinearLayout>

 

 

3.主页面效果

 

 

4.主页面代码

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官方文档

https://developer.android.google.cn/training/improving-layouts/reusing-layouts

 

 

 

 

 

三.ViewStub标签

ViewStub 标签最大的优点是当你需要时才会加载,使用他并不会影响UI初始化时的性能。各种不常用的布局比如进度条、显示错误消息等可以使用<ViewStub />标签,以减少内存使用量,加快渲染速度

 

ViewStub的使用有几个注意事项。

<1> ViewStub对象只可以inflate一次,之后ViewStub对象会被置为空。

 

<2> ViewStub不支持merge,不能引入包含merge标签的布局到ViewStub中。否则会报错

can be used only with a valid ViewGroup root and attachToRoot=true

 

 

代码

1.要引入的textview布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textview_layout_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textview_layout_textview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:text="我是TextView"
        android:textColor="#FFFFFF"
        android:textSize="25dp" />


</LinearLayout>

 

 

2.主页面layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimary"
    tools:context=".MainActivity">


    <ViewStub
        android:id="@+id/activity_main_viewstub"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:inflatedId="@+id/textview_layout_layout"
        android:layout="@layout/textview_layout">

    </ViewStub>

</androidx.constraintlayout.widget.ConstraintLayout>

注意:

<1> 使用id activity_main_viewstub获取ViewStub,ViewStub在加载布局之后,ViewStub本身消失。其中设置的

android:inflatedId="@+id/textview_layout_layout"

指定加载后布局ID,这里加载后是要引入的textview布局,其父布局id

android:id="@+id/textview_layout_layout"

两者一致。

 

 

3.主页面代码

package com.example.test;

import android.os.Bundle;
import android.view.View;
import android.view.ViewStub;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private ViewStub viewStub;
    private View view;
    private TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewStub = findViewById(R.id.activity_main_viewstub);
        if (null == view) {
            if (viewStub != null) {
                view = viewStub.inflate();
            }
        }

        //执行了viewStub.inflate();之后 布局就引入成功,要引入的布局中的View使用和普通ViewfindViewById一样

        textView = findViewById(R.id.textview_layout_textview);
        textView.setText("引入后动态设置TextView字符串");
    }

}

 

注意:

<1> 由于ViewStub第一次inflate的时候,就已经将需要显示的布局替换掉自己了,所以第二次inflate的时候,getParent()是null,所以就会报异常。解决方法是inflate()的时候将view保存起来,然后下次判断这个View是否为null,如果是null就inflate()。否则就直接使用这个view。

 

<2> 也可通过以下方式获取

findViewById(R.id.activity_viewstubdemo_viewstub2).setVisibility(View.VISIBLE);

 

 

 

附:ViewStub官方文档

https://developer.android.google.cn/training/improving-layouts/loading-ondemand

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值