• Android 布局优化


    转载自stormzhang的博客:http://stormzhang.com/android/2014/04/10/android-optimize-layout/

    < include />的使用

    在实际开发中,我们经常会遇到一些共用的UI组件,比如带返回按钮的导航栏,如果为每一个xml文件都设置这部分布局,一是重复的工作量大,二是如果有变更,那么每一个xml文件都得修改。还好,Android为我们提供了include标签,顾名思义,通过它,我们可以将这些共用的组件抽取出来单独放到一个xml文件中,然后使用include标签导入共用布局,这样,前面提到的两个问题都解决了。下面以在一个布局main.xml中用include引入另一个布局header.xml为例。

    header.xml

    <?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" >
    
        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_40"
            android:layout_above="@id/text"/>
    
        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_40"
            android:layout_alignParentBottom="true"
            android:text="@string/app_name" />
    
    </RelativeLayout>

    然后我们在需要引入footer的布局xml中通过include导入这个共用布局。

    main.xml文件

    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="hello world" />
    
        <RelativeLayout 
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center" >
    
            <include layout="@layout/header" />
    
        </RelativeLayout>
    </FrameLayout>

    通过这种方式,我们既能提高UI的制作和复用效率,也能保证制作的UI布局更加规整和易维护。

    < merge />的使用

    merge标签的作用是合并UI布局,使用该标签能降低UI布局的嵌套层次。merge标签可用于两种典型情况:

    • 布局根结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容布局的parent view就是个FrameLayout,所以可以用merge消除只剩一个,这一点可以从上图中看到。

    • 某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中。

    以第一种情况为例,main.xml布局就可以优化如下:

    <merge xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <FrameLayout 
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="hello world" />
    
            <RelativeLayout 
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="center" >
    
                <include layout="@layout/header" />
    
            </RelativeLayout>
        </FrameLayout>
    </merge>

    以第二种情况为例,header.xml布局可以优化如下:

    <?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" >
     
        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_40"
            android:layout_above="@id/text"/>
     
        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="@dimen/dp_40"
            android:layout_alignParentBottom="true"
            android:text="@string/app_name" />
     
    </merge>

    这样就不会有多余的FrameLayout和RelativeLayout节点了。

    ViewStub标签

    viewstub标签同include标签一样可以用来引入一个外部布局,不同的是,viewstub引入的布局默认不会扩张,即既不会占用显示也不会占用位置,从而在解析layout时节省cpu和内存。 viewstub常用来引入那些默认不会显示,只在特殊情况下显示的布局,如进度布局、网络失败显示的刷新布局、信息出错出现的提示布局等。

    我们新建一个xml文件用来显示一个网络错误时提示信息error.xml:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >
    
       <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:background="@android:color/white"
            android:padding="10dip"
            android:text="Message"
            android:textColor="@android:color/black" />
    
    </RelativeLayout>

    然后在main.xml里面加入ViewStub的标签引入上面的布局:

    <merge xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:background="@android:color/darker_gray"
        android:layout_height="match_parent" >
    
        ...
    
        <ViewStub
            android:id="@+id/error_layout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout="@layout/error" />
    
    </merge>

    在java中通过(ViewStub)findViewById(id)找到ViewStub,通过stub.inflate()展开ViewStub,然后得到子View,如下:

    private View errorView;
     
    private void showError() {
        // not repeated infalte
        if (errorView != null) {
            errorView.setVisibility(View.VISIBLE);
            return;
        }
     
        ViewStub stub = (ViewStub)findViewById(R.id.error_layout);
        errorView = stub.inflate();
    }
     
    private void showContent() {
        if (errorView != null) {
            errorView.setVisibility(View.GONE);
        }
    }

    在上面showError()中展开了ViewStub,同时我们对errorView进行了保存,这样下次不用继续inflate。

    总结

    这篇Blog没有详细介绍HierarchyViewer工具的使用,相信如果对布局原则比较熟练之后,对工具的依赖大大减少,开发效率也会大大的提升。除这些布局原则之外,还需要大家对Android各个组件的属性很熟悉,比如如果要做这么一个布局, 一个图片和一个文本的布局,新手们往往会用一个Layout嵌套ImageView和TextView来做, 但是当我们知道TextView有drawableLeft, drawableRight等属性时,那么实现这样的一个布局是非常快速高效的。总之,且学且实践!

  • 相关阅读:
    奶酪工厂
    P1080 国王游戏(非高精版)
    【洛谷P2150】[NOI2015] 寿司晚宴
    【洛谷P3349】[ZJOI2016]小星星
    【洛谷P5785】[SDOI2012]任务安排
    【模板】严格次短路
    【洛谷P3647】[APIO2014]连珠线
    2021.10.27NOIP模拟总结
    【树形DP】CF1016F Road Projects
    2021CSP-S 总结
  • 原文地址:https://www.cnblogs.com/yjpjy/p/5339906.html
Copyright © 2020-2023  润新知