New UI-<merge>标签减少视图层级,让布局更高效

来源:互联网 发布:淘宝怎么来的 编辑:程序博客网 时间:2024/05/20 16:09

New UI-<merge>标签减少视图层级,让布局更高效

 ——转载请注明出处:coder-pig,欢迎转载,请勿用于商业用途!


小猪Android开发交流群已建立,欢迎大家加入,无论是新手,菜鸟,大神都可以,小猪一个人的

力量毕竟是有限的,写出来的东西肯定会有很多纰漏不足,欢迎大家指出,集思广益,让小猪的博文

更加的详尽,帮到更多的人,O(∩_∩)O谢谢!

小猪Android开发交流群:小猪Android开发交流群群号:421858269

新Android UI实例大全目录:http://blog.csdn.net/coder_pig/article/details/42145907



本节引言:

前面我们已经学了布局优化的两个小技巧:

①使用include简化布局,解决布局复用的;②ViewStub延时加载,加快页面加载速度

那么今天再给大家介绍一个标签<merge>,"merge"直译"合并,混合",难道是合并布局?

呵呵,没错,你猜对了,是合并布局,不过有点遗憾的是,他合并的布局只能是:FrameLayout(帧布局)

只能合并一种布局,也没想象中那么种,仅仅减少关于FrameLayout的冗余层次,从而达到优化UI

的目的,事实如此,也不必多解释什么,不过每一样都系都有自己存在的意义,可能现在界面比较简单

的时候并不能体现他的价值,以后就知道了...而<merge>通常是

搭配着<include>标签来使用的,嗯呢,废话不多说,开始本节内容吧!


本节正文:


1.一个简单的例子引入<merge>

一个简单的FrameLayout的布局中:有一个普通的TextView:

布局文件如下:

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     tools:context="com.jay.example.test.MainActivity" >  
  6.   
  7.     <TextView  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_gravity="center"  
  11.         android:gravity="center"  
  12.         android:text="呵呵"  
  13.         android:textSize="20sp" />  
  14.   
  15. </FrameLayout>  

那么,现在你来猜猜他的布局层次是怎么样的?

直接:LinearLayout -> FrameLayout  -> TextView 么?

带着疑惑,我们打开之前教过大家的布局层次查看工具:Hierarchy Viewer


如图,竟然出现了两个FrameLayout,第一反应,这没必要吧,把第二个FrameLayout搞掉!

恩,先不急,听我娓娓道来,从图中我们可以了解到这样一个信息,布局的结构基础都是:

PhoneWindowsDecorView -> LinearLayout  ->FrameLayout

接下来加载的布局资源都跟在这个FrameLayout后面就比如上面的布局

或许你还不信,我们在FrameLayout里添加上一个LinearLayout和一个TextView:


好了,上面这个图就验证了我们的说法,那么我们怎么来消除(优化)这个多余的FrameLayout呢?

就要用到今天要介绍的这个<merge>标签了!



2)merge标签怎么用:

答:超简单,直接把布局文件的外层的FrameLayout改成merge即可:


看下布局文件:

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <merge xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools" >  
  3.   
  4.     <TextView  
  5.         android:layout_width="wrap_content"  
  6.         android:layout_height="wrap_content"  
  7.         android:layout_gravity="center"  
  8.         android:gravity="center"  
  9.         android:text="呵呵"  
  10.         android:textSize="20sp" />  
  11.   
  12. </merge>  

没错,就是这么简单,从上面我们就可以看出,merge的作用是:

!!代替一层FrameLayout,如果是其他布局的话,他就没作用了哦!

除了上面这种应用情况外,我们更多的时候是跟这个include组合使用的



3)include结合merge:

这里找了网上的一个经典例子给大家体会下:


先看下层次图:


接下来就贴代码咯

编写流程:

①创建按钮布局文件okcalcelbar_button.xml

②创建okcancelbar.xml的文件,通过include引入两个上面的按钮

③values目录下面创建自定义属性的文件attrs.xml

④创建OkCancelBar类继承LinearLayout

创建主布局文件


详细代码:

okcalcelbar_button.xml

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <Button xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="wrap_content"  
  4.     android:layout_height="wrap_content" />  

okcancelbar.xml

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <merge xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="wrap_content"  
  4.     android:layout_height="wrap_content" >  
  5.   
  6.     <include  
  7.         android:id="@+id/okcancelbar_ok"  
  8.         layout="@layout/okcalcelbar_button" />  
  9.   
  10.     <include  
  11.         android:id="@+id/okcancelbar_cancel"  
  12.         layout="@layout/okcalcelbar_button" />  
  13.   
  14. </merge>  

attrs.xml

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <declare-styleable name="OkCancelBar">   
  4.         <attr name="okLabel" format="string"/>    
  5.        <attr name="cancelLabel" format="string"/>    
  6.     </declare-styleable>    
  7. </resources>  

OkCancelBar.java:

[java] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. package com.xzw.merge;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.util.AttributeSet;  
  6. import android.view.Gravity;  
  7. import android.view.LayoutInflater;  
  8. import android.widget.Button;  
  9. import android.widget.LinearLayout;  
  10.   
  11. public class OkCancelBar extends LinearLayout {  
  12.     public OkCancelBar(Context context, AttributeSet attrs) {  
  13.         super(context, attrs);  
  14.         setOrientation(HORIZONTAL); // 横排  
  15.         setGravity(Gravity.CENTER); // 居中显示  
  16.         setWeightSum(1.0f);  
  17.   
  18.         LayoutInflater.from(context).inflate(R.layout.okcancelbar, thistrue);  
  19.         // TypedArray是一个数组容器  
  20.         TypedArray array = context.obtainStyledAttributes(attrs,  
  21.                 R.styleable.OkCancelBar, 00);  
  22.   
  23.         String text = array.getString(R.styleable.OkCancelBar_okLabel);// 这里的属性是:名字_属性名  
  24.         if (text == null)  
  25.             text = "Ok";  
  26.         ((Button) findViewById(R.id.okcancelbar_ok)).setText(text);  
  27.   
  28.         text = array.getString(R.styleable.OkCancelBar_cancelLabel);  
  29.         if (text == null)  
  30.             text = "Cancel";  
  31.         ((Button) findViewById(R.id.okcancelbar_cancel)).setText(text);  
  32.   
  33.         array.recycle();  
  34.     }  
  35.   
  36. }  

activity_main.xml:

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.   
  3. <merge  
  4.     xmlns:android="http://schemas.android.com/apk/res/android"  
  5.     xmlns:okCancelBar="http://schemas.android.com/apk/res/com.xzw.merge">  
  6.   
  7.     <ImageView    
  8.         android:layout_width="fill_parent"   
  9.         android:layout_height="fill_parent"   
  10.       
  11.         android:scaleType="center"  
  12.         android:src="@drawable/golden_gate" />  
  13.       
  14.     <com.xzw.merge.OkCancelBar  
  15.         android:layout_width="fill_parent"   
  16.         android:layout_height="wrap_content"   
  17.         android:layout_gravity="bottom"  
  18.         android:paddingTop="8dip"  
  19.         android:gravity="center_horizontal"  
  20.         android:background="#AA000000"  
  21.         okCancelBar:okLabel="Save"  
  22.         okCancelBar:cancelLabel="Don't save" />  
  23.   
  24. </merge>  


代码难点分析:

①attrs.xml文件:

上面自定义属性文件中OkCancelBar就是定义在<declare-styleable name="OkCancelBar">

</declare-styleable> 里的名字,获取里面属性用 名字_ 属性 连接起来就可以.

TypedArray 通常最后调用 .recycle() 方法,为了保持以后使用该属性一致性!

②activity_main.xml文件

xmlns:okCancelBar:是我们自定义属性的命名空间前缀。

也就是下面     okCancelBar:okLabel="Save"      okCancelBar:cancelLabel="Don't save"

用到的 "http://schemas.android.com/apk/res/com.xzw.merge" 

其中com.xzw.merge 是类文件所在包名。使用自定义属性必须加上该命名空间。


ps:简单点说就是attrs.xml自定义两个属性,以及设置属性的类型,然后在使用该自定义属性的布局中,

需要添加

xmlns:"declare-styleable里的name值"="http://schemas.android.com/apk/res/自定义类文件所在包名"

然后可以通过:

TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.OkCancelBar, 0, 0);

获取里面两个属性的值!接下来的就自己想咯!




4)merge的一些注意事项:

①merge标签只能作为xml文件的根节点,就是最外层的那个

②merge只能合并FrameLayout哦,如果根节点为LinearLayout或者其他,再使用<merge>标签

就会报错哦!

③使用LayoutInflater的inflate方法加载<merge>标签的布局文件时,需要为他指定一个父容器控件,

并且设置attachToRoot属性为true!!!





最后说两句:

关于merge合并布局就写到这里,如果后续有什么新的发现,会补上...





本节demo下载:MergeTest

参考资料:

http://bbs.51cto.com/thread-969619-1.html

0 0
原创粉丝点击