在做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. codeforces 651A Joysticks

    A. Joysticks time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  2. TypeScript学习笔记(五):接口

    使用接口 在前面的笔记中我们知道可以使用Object Type来指定参数的属性,如下: function printLabel(labelledObj: {label: string}) { cons ...

  3. MVC神韵---你想在哪解脱!(十二)

    追加一条电影信息 运行应用程序,在浏览器中输入“http://localhost:xx/Movies/Create”,在表单中输入一条电影信息,然后点击追加按钮,如图所示. 点击追加按钮进行提交,表单 ...

  4. Castle IOC容器实践之FactorySupport Facility

    PDF版本下载:http://file.ddvip.com/2008_10/1223538519_ddvip_4853.rar示例代码下载:http://file.ddvip.com/2008_10/ ...

  5. SQL Server 数据类型映射 (ADO.NET)

    SQL Server 数据类型映射 (ADO.NET) .NET Framework 3.5 更新:November 2007 SQL Server 和 .NET Framework 基于不同的类型系 ...

  6. JQuery要点(一)

    简介: jQuery Mobile 是用于创建移动 Web 应用的前端开发框架. jQuery Mobile 可以应用于智能手机与平板电脑. jQuery Mobile 使用 HTML5 & ...

  7. Unity中关于等待的函数

    public void InvokeRepating(string methodName,float time,float repeatRate); 语法 注: 1.methodeName为调用的方法 ...

  8. DuiLib(三)——控件消息

    上一篇讲了控件创建,这篇说说控件消息.directui的中心思想是在真实窗口之上画出所有控件,那这些控件是如何获取各自消息的? 通过第一篇的示例可以看到窗口消息的传递过程: CWindowWnd::_ ...

  9. SQL Server 数据导入Mysql详细教程

  10. Codeforces Gym 100342H Problem H. Hard Test 构造题,卡迪杰斯特拉

    Problem H. Hard TestTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100342/at ...