博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于Merge的整理--AndroidScreenSlidePager开源库中用到的
阅读量:4691 次
发布时间:2019-06-09

本文共 5347 字,大约阅读时间需要 17 分钟。

在做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>

main.xml

activity中的代码:

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

效果图:

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

 

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

main2.xml

activity中的代码:

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

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

 

二、Merge的使用

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

(2)应用Include或者ViewStub标签从外部导入xml结构时,可以将被导入的xmlmerge作为根节点表示,这样当被嵌入父级结构中后可以很好的将它所包含的子集融合到父级结构中,而不会出现冗余的节点<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使用的是自定义的)

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);*/    }

 参考资料:

转载于:https://www.cnblogs.com/whycxb/p/4878087.html

你可能感兴趣的文章
c#中关于@的作用
查看>>
Excel转换成xml文件
查看>>
关于Java链接c#的webapi的注意事项
查看>>
关于vs无法创建虚拟目录的问题
查看>>
ad域的那些事儿
查看>>
如何将自己写的程序加入到计算机服务里
查看>>
C# 二维码 ThoughtWorks.QRCode.dll
查看>>
git 提交顺序
查看>>
ios9怎么设置6位密码 ios9设置6位密码图文教程
查看>>
Python单元测试——深入理解unittest
查看>>
python BaseManager中register()的描述
查看>>
Windbg 脚本命令简介 一
查看>>
Java中跳出多层循环的简单方法
查看>>
类和对象:面向对象编程 - 零基础入门学习Python037
查看>>
寄存器AX
查看>>
C/C++UNION中包含STRUCT
查看>>
CocoStuff—基于Deeplab训练数据的标定工具【三、标注工具的使用】
查看>>
译:Local Spectral Graph Convolution for Point Set Feature Learning-用于点集特征学习的局部谱图卷积...
查看>>
搜索引擎 ElasticSearch 之 步步为营 【主目录】
查看>>
oracle:order siblings by / join 、 mysql:创建动态表名及参数处理 / prepare语句 / 存储过程和函数区别简介...
查看>>