Android布局优化(一)

来源:互联网 发布:程序员入门知识 编辑:程序博客网 时间:2024/05/17 14:29

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/43376527
重用布局文件

Android系统中已经提供了非常多好用的控件,这让我们在编写布局的时候可以很轻松。但是有些时候我们可能需要反复利用某个已经写好的布局,如果你总是使用复制粘贴的方式来进行布局重用,这显然是一种很笨的做法。而Android当然也已经充分考虑到了布局重用的重要性,于是提供了和这两个非常有用的标签,下面我们就来逐个学习一下。

标签可以允许在一个布局当中引入另外一个布局,那么比如说我们程序的所有界面都有一个公共的部分,这个时候最好的做法就是将这个公共的部分提取到一个独立的布局文件当中,然后在每个界面的布局文件当中来引用这个公共的布局。

这里举个例子吧,我们应该都知道,目前几乎所有的软件都会有一个头布局,头布局中可以包含界面的标题、返回按钮、以及其它一些操作功能等。那这样的一个头布局,有些软件是使用ActionBar来实现的,但是由于ActionBar的灵活性不太好,因而也有很多软件会选择自己去编写实现。那如果自己去实现的话,由于这个头布局是在所有界面都要使用的,显然我们不可能在每个界面当中都去写一遍这个头布局的代码,因此这种情况下使用标签就非常合适了。这里为了给大家演示一下,我就编写一个非常简单的头布局,在res/layout文件夹中新建titlebar.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/back"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:layout_alignParentLeft="true"              android:layout_centerVertical="true"              android:text="Back" />          <TextView              android:id="@+id/title"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:layout_centerInParent="true"              android:text="Title"              android:textSize="20sp" />          <Button              android:id="@+id/done"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:layout_alignParentRight="true"              android:layout_centerVertical="true"              android:text="Done" />      </RelativeLayout>

可以看到,titlebar.xml中的布局非常简单,外层是一个RelativeLayout,里面只有两个Button和一个TextView,左边的Button用于实现返回功能,右边的Button用于实现完成功能,中间的TextView则可以用于显示当前界面的标题。我们可以来预览一下titlebar的样子,如下图所示:

这里写图片描述

好的,那titlebar作为一个独立的布局现在我们已经编写完了,接下来的工作就非常简单了,无论任何界面需要加入titlebar这个功能,只需要在布局文件中引入titlebar.xml就可以了。那么比如说我们的程序当中有一个activity_main.xml文件,现在想要引入titlebar只需要这样写:

<?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/titlebar" />      ......  </LinearLayout> 

非常简单吧,一行include语句就可以搞定了。标签当中可以指定一个layout属性,我们在这个layout属性中填写需要引入的布局名就可以了。而且使用这种引入的方式,以后如果titlebar的界面有所变更,我们只需要修改titlebar.xml这一个文件就可以了,而不是所有界面一个个地去修改。

等等!现在如果你运行一下程序会发现出大问题了,虽然titlebar是成功引入了,但是我们activity_main.xml中本来的界面全部都不见了!出现这个问题是原因是因为titlebar的最外层布局是一个宽高都是match_parent的RelativeLayout,它会将整个布局都填充满,因而我们原本的布局也就看不见了。那既然问题的原因清楚了,相信你立刻就想到应该怎么修改了,将RelativeLayout的layout_height属性修改成wrap_content不就可以了嘛。没错,这样修改当然是没问题的,不过这种修改方式会让所有引用titlebar的界面都受到影响,而如何你只希望让activity_main.xml这一个界面受影响的话,那么可以使用覆写属性的方式。

在标签当中,我们是可以覆写所有layout属性的,即include中指定的layout属性将会覆盖掉titlebar中指定的layout属性。因此,这里我们希望将titlebar的高度设置成wrap_content,就可以这样写:

    <?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              android:layout_width="match_parent"              android:layout_height="wrap_content"              layout="@layout/titlebar" />          ......      </LinearLayout>  

现在重新运行一下程序应该就可以一切正常了,如下图所示:

这里写图片描述

除了layout_height之外,我们还可以覆写titlebar中的任何一个layout属性,如layout_gravity、layout_margin等,而非layout属性则无法在标签当中进行覆写。另外需要注意的是,如果我们想要在标签当中覆写layout属性,必须要将layout_width和layout_height这两个属性也进行覆写,否则覆写效果将不会生效。

标签是作为标签的一种辅助扩展来使用的,它的主要作用是为了防止在引用布局文件时产生多余的布局嵌套。大家都知道,Android去解析和展示一个布局是需要消耗时间的,布局嵌套的越多,那么解析起来就越耗时,性能也就越差,因此我们在编写布局文件时应该让嵌套的层数越少越好。

在上面我们讲解标签的用法时主要介绍了它优点,但是它也存在着一个不好的地方,就是可能会导致产生多余的布局嵌套。这里还是通过举例的方式跟大家说明一下,比如说我们需要编写一个确定取消按钮的公共布局,这样任何一个界面需要确定和取消功能时就不用再单独编写了,新建ok_cancel_layout.xml,代码如下所示:

    <?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="wrap_content"          android:orientation="vertical" >          <Button              android:id="@+id/ok"              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:layout_marginLeft="20dp"              android:layout_marginRight="20dp"              android:text="OK" />          <Button              android:id="@+id/cancel"              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:layout_marginLeft="20dp"              android:layout_marginRight="20dp"              android:layout_marginTop="10dp"              android:text="Cancel" />      </LinearLayout>  

可以看到,这个界面也是非常简单,外层是一个垂直方向的LinearLayout,LinearLayout中包含了两个按钮,一个用于实现确定功能,一个用于实现取消功能。现在我们可以来预览一下这个界面,如下图所示:

这里写图片描述

好的,然后我们有一个profile.xml的界面需要编辑一些内容,那么这里就可以将ok_cancel_layout这个布局引入到profile.xml界面当中,如下所示:

    <?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" >          <EditText              android:id="@+id/edit"              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:layout_marginBottom="10dp"              android:layout_marginLeft="20dp"              android:layout_marginRight="20dp"              android:layout_marginTop="10dp"              android:hint="Edit something here" />          <include layout="@layout/ok_cancel_layout"/>      </LinearLayout>  

在profile.xml当中有一个EditText控件用于编辑内容,然后下面使用了标签来将ok_cancel_layout布局进行引入,现在重新运行一下程序,界面效果如下图所示:

这里写图片描述

看上去效果非常不错对吗?可是在你毫无察觉的情况下,目前profile.xml这个界面当中其实已经存在着多余的布局嵌套了!感觉还没写几行代码呢,怎么这就已经有多余的布局嵌套了?不信的话我们可以通过View Hierarchy工具来查看一下,如下图所示:

这里写图片描述

可以看到,最外层首先是一个FrameLayout,这个无可厚非。然后FrameLayout中包含的是一个LinearLayout,这个就是我们在profile.xml中定义的最外层布局。接下来的部分就有问题了,在最外层的LinearLayout当中包含了两个元素,一个是EditText,另一个又是一个LinearLayout,然后在这个内部的LinearLayout当中才包含了确定和取消这两个按钮。

相信大家已经可以看出来了吧,这个内部的LinearLayout就是一个多余的布局嵌套,实际上并不需要这样一层,让两个按钮直接包含在外部的LinearLayout当中就可以了。而这个多余的布局嵌套其实就是由于布局引入所导致的,因为我们在ok_cancel_layout.xml中也定义了一个LinearLayout。那么应该怎样优化掉这个问题呢?当然就是使用标签来完成了,修改ok_cancel_layout.xml中的代码,如下所示:

    <?xml version="1.0" encoding="utf-8"?>      <merge xmlns:android="http://schemas.android.com/apk/res/android">          <Button              android:id="@+id/ok"              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:layout_marginLeft="20dp"              android:layout_marginRight="20dp"              android:text="OK" />          <Button              android:id="@+id/cancel"              android:layout_width="match_parent"              android:layout_height="wrap_content"              android:layout_marginLeft="20dp"              android:layout_marginRight="20dp"              android:layout_marginTop="10dp"              android:text="Cancel" />      </merge>  

可以看到,这里我们将ok_cancel_layout最外层的LinearLayout布局删除掉,换用了标签,这就表示当有任何一个地方去include这个布局时,会将标签内包含的内容直接填充到include的位置,不会再添加任何额外的布局结构。好的,的用法就是这么简单,现在重新运行一下程序,你会看到界面没有任何改变,然后我们再通过View Hierarchy工具来查看一下当前的View结构,如下图所示:
这里写图片描述

OK,可以看到,现在EditText和两个按钮都直接包含在了LinearLayout下面,我们的profile.xml当中也就不存在多余的布局嵌套了。

原创粉丝点击