关于Merge的整理--AndroidScreenSlidePager开源库中用到的

在做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本身也是打算使用Fragment根节点的——也就是说merge主要是用来替换FrameLayout进行优化】

四、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);*/
    }
时间: 2024-09-30 09:36:34

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

使用AndroidScreenSlidePager开源库

一.下载地址 https://github.com/LyndonChin/AndroidScreenSlidePager 点击右侧的Download ZIp按钮进行下载.然后解压缩到本地. 二.使用方法 1.复制AndroidScreenSlidePager-master\SlidePageIndicator\src\main\java\com\liangfeizc\slidepageindicator目录下的PageIndicator.java文件到项目中任意一个包中.以及AndroidScr

Android 开源库获取途径整理

介绍目前收藏 Android 开源库比较多的 GitHub 项目.网站.Twitter.App 及如何获取最新的 Android 开源库. 1. GitHub Android 开源项目汇总 Android 优秀开源项目实现原理解析 把这两个放在前面,是因为这两个项目我和一群小伙伴在精心维护,同时任何人都可以提交 PR 参与进来.其他网站或 App 都可以以此为数据源 AndroidElementals 西班牙一工程师整理的,目前项目数量和介绍上与 Android 开源项目汇总 还有一定差距 2.

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

iOS 项目中用到的一些 iOS 开源库和第三方组件 分享一下我目前所在公司 iOS 项目中用到的一些 iOS 开源库和第三方组件, 感谢开源, 减少了我们的劳动力, 节约了我们大量的时间, 让我们有更多的时间和精力能更加专注的做好自己的产品 用到的组件 1.通过CocoaPods安装 项目名称 项目信息 AFNetworking 网络请求组件 FMDB 本地数据库组件 SDWebImage 多个缩略图缓存组件 UICKeyChainStore 存放用户账号密码组件 Reachability 监

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

[原][开源框架]Android之史上最全最简单最有用的第三方开源库收集整理,有助于快速开发,欢迎各位... 时间 2015-01-05 10:08:18 我是程序猿,我为自己代言 原文  http://blog.csdn.net/caoyouxing/article/details/42418591 主题 开源 安卓开发 http://www.tuicool.com/articles/jyA3MrU Android开源库 自己一直很喜欢Android开发,就如博客签名一样, 我是程序猿,我为自

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

[转]http://www.tuicool.com/articles/jyA3MrU Android开源库 自己一直很喜欢Android开发,就如博客签名一样, 我是程序猿,我为自己代言 . 在摸索过程中,GitHub上搜集了很多很棒的Android第三方库,推荐给在苦苦寻找的开发者,而且我会 不定期的更新 这篇文章. Android下的优秀开发库数不胜数,在本文中,我列举的多是开发流程中最常用的一些.如果你还想了解更多的Android开源库,可以关注我的博客,每一个库都是我认真查看或者编译运行

Android之史上最全最简单最有用的第三方开源库收集整理

Android开源库 自己一直很喜欢Android开发,就如博客签名一样, 我是程序猿,我为自己代言 . 在摸索过程中,GitHub上搜集了很多很棒的Android第三方库,推荐给在苦苦寻找的开发者,而且我会 不定期的更新 这篇文章. Android下的优秀开发库数不胜数,在本文中,我列举的多是开发流程中最常用的一些.如果你还想了解更多的Android开源库,可以关注我的博客,每一个库都是我认真查看或者编译运行的,希望对你产生帮助. 原文: http://blog.csdn.net/caoyou

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

原文地址:http://blog.csdn.net/caoyouxing/article/details/42418591 Android开源库 自己一直很喜欢Android开发,就如博客签名一样, 我是程序猿,我为自己代言 . 在摸索过程中,GitHub上搜集了很多很棒的Android第三方库,推荐给在苦苦寻找的开发者,而且我会 不定期的更新 这篇文章. Android下的优秀开发库数不胜数,在本文中,我列举的多是开发流程中最常用的一些.如果你还想了解更多的Android开源库,可以关注我的博

DICOM:fo-dicom、dcm4che14、dcm4chee等开源库持续自我维护

题记: DICOM专栏系列虽然写了多年,但是依然不能解决大家日常中遇到的种种问题,其实这恰恰就是程序员(码农)工作的最大乐趣所在.就像每个人的人生一样,所处的环境不同,所遭遇的事件不同,结果自然就不同.程序开发亦是如此,操作系统不同.软件版本不同,本地配置不同都会导致种种问题. "授人以鱼不如授人以渔",所以正常的解决之道是希望通过专栏的讲解,能够让大家真正理解每个问题出现的背后原因,从而主动排查并解决问题.对于排查和解决过程中遇到的问题,我会整理总结成博文供大家参考.正如上文所说,每

Android开源库项目集锦

一.兼容类库 ActionBarSherlock : Action Bar是Android 3.0后才開始支持的,ActionBarSherlock是让Action Bar功能支持2.X后的全部平台.并且他会自己主动的推断是调用原生Action Bar还是使用扩展ActionBar. 在我的小熊词典里实用到这个库,并且非常多非常知名的App也在使用这个库.GitHub Official ActionBar科普 Android-ViewPagerIndicator : 这是与ViewPager兼容