在做AndroidScreenSlidePager开源库练习demo的时候,发现布局文件使用的是<merge>标签而不是<FrameLayout>标签。作者给出的说法是:CirclePageIndicator and ViewPager shoud be used as child views of a Framelayout. But here we used merge instead, because the root view in any activity is a FrameLayout.【翻译:CirclePageIndicator and ViewPager必须是作为根节点为FrameLayout的子节点,但是这里我们使用merge替换Framelayout,因为所有的Activity视图的根节点都是FrameLayout。】

Activity中的onCreate方法中的setContentView(R.layout.main);代表的含义是:我们放置的main.xml布局文件被放置在一个id为content的FrameLayout的布局中,这也就是为啥Activity的setContentView方法叫set content view了,就是把我们的xml放入了这个id为content的FrameLayout中。

一、Merge对布局的优化以及示例

<merge/>的出现是为了优化android布局,减少视图树的层级,过多的层级也会导致程序变慢。当LayoutInflater遇到这个标签时,它会跳过它,并将<merge />内的元素添加到<merge />的父元素里。

(1)布局文件:根节点为<FrameLayout>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="center"
android:src="@drawable/golden_gate" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="20dip"
android:background="#AA000000"
android:padding="12dip"
android:text="Golden Gate"
android:textColor="#ffffffff" /> </FrameLayout>

main.xml

activity中的代码:

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

效果图:

使用HierarchyViewer 工具来查看该视图的层级效果,我们可以看到蓝色的矩形的就是我们刚刚的FrameLayout的层数。

(2)布局文件:根节点为<merge>

<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <ImageView
android:id="@+id/goldenIv"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="center"
android:src="@drawable/golden_gate" /> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom"
android:layout_marginBottom="20dip"
android:background="#AA000000"
android:padding="12dip"
android:text="Golden Gate"
android:textColor="#ffffffff" /> </merge>

main2.xml

activity中的代码:

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
}

我们看到的效果是这样的,蓝色的是用来包含之前FrameLayout的父标签,现在直接包裹着ImageView和TextView两个子标签。可以理解为将merge标签中的子集直接加到Activity的FrameLayout跟节点。

二、Merge的使用

(1)activity中的onCreate方法中的setContentView(R.layout.main2);

(2)应用Include或者ViewStub标签从外部导入xml结构时,可以将被导入的xml用merge作为根节点表示,这样当被嵌入父级结构中后可以很好的将它所包含的子集融合到父级结构中,而不会出现冗余的节点。<include layout="@layout/main2"/>

(3)当需要扩充的xml layout本身是由merge作为根节点的话,需要将被导入的xml layout置于 viewGroup中,同时需要设置attachToRoot为True。

View view = inflater.inflate(R.layout.main2, container, true);

 三、Merge的注意事项

(1)<merge />只可以作为xml layout的根节点。

(2)如果你所创建的xml layout并不是用FramLayout作为根节点(而是应用LinerLayout等定义root标签),就不能应用上边的例子通过merge来优化UI结构。【merge的布局效果跟FrameLayout是等同的】

(3)Merge的父布局最好也是FrameLayout,因为使用Merge优化是指将<merge />内的元素添加到<merge />的父元素里,如果父布局不是FrameLayout,那么merge的元素添加到父布局中后,本来的展现效果就是发生变化——按照父布局的样式进行展现。

四、Merge的子布局的LayoutParams设置

可以暂时认为Merge就等同于Framelayout。如果merge节点里面有Linearlayout布局,那么如何在Java代码中通过LayoutParames来设置这个LinearLayout相对于父节点的位置呢?

(1)例如,布局文件如下:(LinearLayout使用的是自定义的)

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent" > <!-- viewPager:图片展现 -->
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" /> <!-- 指示器圆点 -->
<!-- android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
-->
<com.why.screenslidepagerdemo.custom.PageIndicator
android:id="@+id/indicator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="20dp"
android:gravity="bottom|center_horizontal"
app:indicator_spacing="5dp"
app:indicator_type="fraction" /> </merge>

activity_slidepager.xml

(2)引用这个布局文件的代码:

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slidepager);
}

(3)自定义LinearLayout中的相关代码

setLayoutParams 是设给父节点的,所以需要知道父节点的类型,在这里merge可以认为framelayout,但是还是需要通过下面的代码给这个自定义LinearLayout设置下LayoutParams

if (!(getLayoutParams() instanceof FrameLayout.LayoutParams)) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;//暂时不起作用
this.setLayoutParams(params);
}

然后就可以正常使用了,使用代码如下:

FrameLayout.LayoutParams params1 = (FrameLayout.LayoutParams) this.getLayoutParams();
params1.bottomMargin = dp2px(getContext(), 5);
this.setLayoutParams(params1);

大概代码如下:

public class PageIndicator extends LinearLayout

//构造函数1
public PageIndicator(Context context) {
this(context, null);
}
//构造函数2
public PageIndicator(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
//构造函数3
public PageIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//这里取得declare-styleable集合
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PageIndicator, 0, 0);
try {
//这里从集合里取出相对应的属性值,第二参数是如果使用者没用配置该属性时所用的默认值
mIndicatorSpacing = a.getDimensionPixelSize(R.styleable.PageIndicator_indicator_spacing,dp2px(context, DEFAULT_INDICATOR_SPACING));
int indicatorTypeValue = a.getInt(R.styleable.PageIndicator_indicator_type,mIndicatorType.type);
mIndicatorType = IndicatorType.of(indicatorTypeValue);
} finally {
//关闭资源
a.recycle();
} init();//设置布局参数
} //设置布局参数
private void init() {
//这个代码是有效的
this.setOrientation(HORIZONTAL);//设置水平展现
//this.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);//有效 Log.v("PageIndicator", (this.getLayoutParams() instanceof FrameLayout.LayoutParams) + "");//false
Log.v("PageIndicator", (this.getLayoutParams() instanceof LinearLayout.LayoutParams) + "");//false
/*
* 1、通过merge来优化UI结构一般用于FrameLayout根节点
* 2、setLayoutParams 是设给父节点的。 */ //下面的代码是给这个layout设置layoutParams为FrameLayout.LayoutParams,便于后面getlayoutParams时可以指定类型
if (!(getLayoutParams() instanceof FrameLayout.LayoutParams)) {
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;//暂时不起作用
this.setLayoutParams(params);
}
//使用如下:
/*FrameLayout.LayoutParams params1 = (FrameLayout.LayoutParams) this.getLayoutParams();
params1.bottomMargin = dp2px(getContext(), 5);
this.setLayoutParams(params1);*/
}

参考资料:

http://blog.sina.com.cn/s/blog_62f987620100sf13.html

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

关于Merge的整理--AndroidScreenSlidePager开源库中用到的的更多相关文章

  1. 使用AndroidScreenSlidePager开源库

    一.下载地址 https://github.com/LyndonChin/AndroidScreenSlidePager 点击右侧的Download ZIp按钮进行下载.然后解压缩到本地. 二.使用方 ...

  2. 各种Android UI开源框架 开源库

    各种Android UI开源框架 开源库 转 https://blog.csdn.net/zhangdi_gdk2016/article/details/84643668 自己总结的Android开源 ...

  3. 开源框架】Android之史上最全最简单最有用的第三方开源库收集整理,有助于快速开发

    [原][开源框架]Android之史上最全最简单最有用的第三方开源库收集整理,有助于快速开发,欢迎各位... 时间 2015-01-05 10:08:18 我是程序猿,我为自己代言 原文  http: ...

  4. iOS 项目中用到的一些开源库和第三方组件

    iOS 项目中用到的一些 iOS 开源库和第三方组件 分享一下我目前所在公司 iOS 项目中用到的一些 iOS 开源库和第三方组件, 感谢开源, 减少了我们的劳动力, 节约了我们大量的时间, 让我们有 ...

  5. Android主流UI开源库整理(转载)

    http://www.jianshu.com/p/47a4a7b99364 标题隐含了两个层面的意思,一个是主流,另一个是UI.主流既通用,一些常规的按钮.Switch.进度条等控件都是通用控件,因此 ...

  6. Android 开源库获取途径整理

    介绍眼下收藏 Android 开源库比較多的 GitHub 项目.站点.Twitter.App 及怎样获取最新的 Android 开源库. 微信号: 1. GitHub Android 开源项目汇总 ...

  7. Android(常用)主流UI开源库整理

    这几天刚做完一个项目..有点空余时间,就想着吧这一两年做的项目中的UI界面用到的一些库整理一下.后来想了一下,既然要整理,就把网上常用的 AndroidUI界面的主流开源库 一起整理一下,方便查看. ...

  8. Android 第三方开源库收集整理(转)

    原文地址:http://blog.csdn.net/caoyouxing/article/details/42418591 Android开源库 自己一直很喜欢Android开发,就如博客签名一样,  ...

  9. 45.Android 第三方开源库收集整理(转)

    原文地址:http://blog.csdn.net/caoyouxing/article/details/42418591 Android开源库 自己一直很喜欢Android开发,就如博客签名一样,  ...

随机推荐

  1. Xcode 的正确打开方式——Debugging

    程序员日常开发中有大量时间都会花费在 debug 上,从事 iOS 开发不可避免地需要使用 Xcode.这篇博客就主要介绍了 Xcode 中几种能够大幅提升代码调试效率的方式. “If debuggi ...

  2. 【转】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程

    http://blog.csdn.net/xiaominghimi/article/details/6937097 //——2012-12-11日更新   获取"产品付费数量等于0这个问题& ...

  3. 扩展KMP--求字符串S的所有后缀和字符串T的最长公共前缀

    在解上面这个问题前我们要先解决一个类似的问题:求字符串s的所有后缀和s本身的最长公共前缀: 我们用next[]数组保存这些值: 现在我们假设要求next[ x ],并且next[ i ] 0<i ...

  4. HDU 2425 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. 应用JConsole学习Java GC

    应用JConsole学习Java GC 关于Java GC的知识,好多地方都讲了很多,今天我用JConsole来学习一下Java GC的原理. GC原理 在我的上一篇中介绍了Java运行时数据区,在了 ...

  6. Unity3D之游戏暂停制作方法记录

    在游戏开发中我们一般都需要涉及到一个功能:游戏暂停,但是这里指的暂停仅仅是核心模块的暂停,并不是整个游戏都暂停,比如一些UI和UI上的动画与特效是不能被暂停的,整个游戏都暂停了玩家该如何继续游戏呢. ...

  7. 在数据库各种状态下查询DBID的五大类十种方法汇总

    关于DBID: DBID是DataBase IDentifier的缩写,意思就是数据库的唯一标识符. 这个DBID在数据文件头和控制文件都是存在的,可以用于标示数据文件的归属. 对于不同数据库来说,D ...

  8. 用Swashbuckle给ASP.NET Core的项目自动生成Swagger的API帮助文档

    博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:用Swashbuckle给ASP.NET Core的项目自动生成Swagger的API帮助文档.

  9. JdbcTemplate增删改查

    1.使用JdbcTemplate的execute()方法执行SQL语句 jdbcTemplate.execute("CREATE TABLE USER (user_id integer, n ...

  10. 很近没读书了,读书笔记之<<大道至简>>

    空闲时间不想虚度,不知道干啥的时候,就读读存在移动硬盘里的电子书吧,已经放了N久了,不知道什么时候放的,好像是大学刚毕业的时候下载的,...... 好久...... 现在才去读..是不是太晚了.... ...