zoukankan      html  css  js  c++  java
  • 浅谈Android样式开发之布局优化

    引言

      今天我们来谈一下Android中布局优化常用的一些手段。官方给出了3种优化方案,分别是</include>、</viewstub>、</merge>标签,下面我们就来介绍这些标签。

    include标签

      include标签能够重用布局文件,我们在开发中经常有一些布局是通用的,比如每一个页面的头部和尾部,我们可以将其分离到独立的文件中,然后在需要的界面使用include进行嵌入即可。下面我们通过一个示例来看一下include标签的使用。示例如下:  

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <RelativeLayout
     3     xmlns:android="http://schemas.android.com/apk/res/android"
     4     android:layout_width="match_parent"
     5     android:layout_height="match_parent"
     6     android:padding="12dp">
     7 
     8     <LinearLayout
     9         android:layout_width="match_parent"
    10         android:layout_height="wrap_content"
    11         android:orientation="vertical"
    12         android:id="@+id/line1">
    13 
    14         <Button
    15             android:layout_width="match_parent"
    16             android:layout_height="40dp"
    17             android:text="按钮"/>
    18 
    19         <TextView
    20             android:layout_width="match_parent"
    21             android:layout_height="40dp"
    22             android:text="文本"/>
    23 
    24     </LinearLayout>
    25 
    26     <LinearLayout
    27         android:layout_width="match_parent"
    28         android:layout_height="wrap_content"
    29         android:orientation="vertical"
    30         android:layout_marginTop="10dp"
    31         android:layout_below="@+id/line1">
    32 
    33         <Button
    34             android:layout_width="match_parent"
    35             android:layout_height="40dp"
    36             android:text="按钮2"/>
    37 
    38         <TextView
    39             android:layout_width="match_parent"
    40             android:layout_height="40dp"
    41             android:text="文本2"/>
    42 
    43     </LinearLayout>
    44 
    45 </RelativeLayout>

      在这个例子中我们把第二个Linearlayout独立出去写成额外的layout布局文件,然后使用include标签来嵌入。如下所示:

    1 <!--
    2     使用include标签嵌入第二个LinearLayout
    3 -->
    4 <include
    5         android:layout="@layout/partial_layout"/>

      这样我们就可以将第二个LinearLayout布局文件嵌入进来,效果和上面是一样的。但是使用include时有几个地方需要注意。具体如下:

      注意点:

        1、<include/>标签可以使用单独的layout属性,这个也是必须使用的。

        2、<include/>标签若指定了Id属性,而你的LinearLayout也定义了Id,那么你的LinearLayout的Id会被覆盖。

        3、在<include/>标签中所有的android:layout_*都是可用的,前提是必须要写layout_width和layout_height属性。

    merge标签

      <merge/>标签在UI的结构优化中起着非常重要的作用,它可以删减多余的层级,优化UI。<merge/>多用于替换FrameLayout或者当一个布局包含另一个时,<merge/>标签消除视图层次结构中多余的视图组。下面是<merge/>标签使用的两个经典场景。

      a.  布局顶结点是FrameLayout且不需要设置background或padding等属性,可以用merge代替,因为Activity内容试图的parent view就是个FrameLayout,所以可以用merge消除只剩一个。
      b.  某布局作为子布局被其他布局include时,使用merge当作该布局的顶节点,这样在被引入时顶结点会自动被忽略,而将其子节点全部合并到主布局中。

      下面我们来看一个示例:

      上面讲到我们把第二个LinearLayout分离出来单独写到一个partial_layout文件中了,下面我们来看一下这个分离出去的布局文件。如下所示:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <!--此处使用<merge/>标签替换-->
     3 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     4     android:orientation="vertical"
     5     android:layout_width="match_parent"
     6     android:layout_height="match_parent">
     7 
     8     <LinearLayout
     9         android:layout_width="match_parent"
    10         android:layout_height="wrap_content"
    11         android:orientation="vertical"
    12         android:layout_marginTop="10dp"
    13         android:layout_below="@+id/line1">
    14 
    15         <Button
    16             android:layout_width="match_parent"
    17             android:layout_height="40dp"
    18             android:text="按钮2"/>
    19 
    20         <TextView
    21             android:layout_width="match_parent"
    22             android:layout_height="40dp"
    23             android:text="文本2"/>
    24 
    25     </LinearLayout>
    26 
    27 </LinearLayout>

      我们看到这个子布局中距离嵌套了两层LinearLayout,这是很不合理的,在这里我们可以把根节点的LinearLayout替换成<merge/>标签。这样就相当于把最外层的LinearLayout给剥离了。一定程度上优化了布局的结构,这就是<merge/>标签的作用。

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

      下面以在一个布局main.xml中加入网络错误时的提示页面network_error.xml为例。main.mxl代码如下:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent" >
     5     ……
     6     <ViewStub
     7         android:id="@+id/network_error_layout"
     8         android:layout_width="match_parent"
     9         android:layout_height="match_parent"
    10         android:layout="@layout/network_error" />
    11  
    12 </RelativeLayout>

      其中network_error.xml为只有在网络错误时才需要显示的布局,默认不会被解析,示例代码如下:

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent" >
     5  
     6     <Button
     7         android:id="@+id/network_setting"
     8         android:layout_width="@dimen/dp_160"
     9         android:layout_height="wrap_content"
    10         android:layout_centerHorizontal="true"
    11         android:text="@string/network_setting" />
    12  
    13     <Button
    14         android:id="@+id/network_refresh"
    15         android:layout_width="@dimen/dp_160"
    16         android:layout_height="wrap_content"
    17         android:layout_below="@+id/network_setting"
    18         android:layout_centerHorizontal="true"
    19         android:layout_marginTop="@dimen/dp_10"
    20         android:text="@string/network_refresh" />
    21  
    22 </RelativeLayout>

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

     1 private View networkErrorView;
     2  
     3 private void showNetError() {
     4     // not repeated infalte
     5     if (networkErrorView != null) {
     6         networkErrorView.setVisibility(View.VISIBLE);
     7         return;
     8     }
     9  
    10     ViewStub stub = (ViewStub)findViewById(R.id.network_error_layout);
    11     networkErrorView = stub.inflate();
    12     Button networkSetting = (Button)networkErrorView.findViewById(R.id.network_setting);
    13     Button refresh = (Button)findViewById(R.id.network_refresh);
    14 }
    15  
    16 private void showNormal() {
    17     if (networkErrorView != null) {
    18         networkErrorView.setVisibility(View.GONE);
    19     }
    20 }

      在上面showNetError()中展开了ViewStub,同时我们对networkErrorView进行了保存,这样下次不用继续inflate。这就是后面第三部分提到的减少不必要的infalte。viewstub标签大部分属性同include标签类似。通过viewstub的原理我们可以知道将一个view设置为GONE不会被解析,从而提高layout解析速度,而VISIBLE和INVISIBLE这两个可见性属性会被正常解析。

  • 相关阅读:
    python中不可变数据类型和可变数据类型
    你分得清Python中:“索引和切片”吗?
    Python Django中一些少用却很实用的orm查询方法
    jQuery on()方法
    jquery.flexslider-min.js实现banner轮播图效果
    jQuery 树型菜单插件(Treeview)
    jQuery Growl 插件(消息提醒)
    jQuery Autocomplete 用户快速找到并从预设值列表中选择
    jQuery Accordion 插件用于创建折叠菜单
    jquery.validate.js 验证框架详解
  • 原文地址:https://www.cnblogs.com/dreamGong/p/6187107.html
Copyright © 2011-2022 走看看