欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

正确使用ViewStub

发布时间:2023/12/20 编程问答 60 豆豆
生活随笔 收集整理的这篇文章主要介绍了 正确使用ViewStub 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

最近在使用ViewStub,在使用的过程中遇到了一些问题,所以现在就在这里记录一下,也免得后面使用的人少走一些坑。事情是这样的,由于项目中要用ViewStub对原有的一些布局页面进行懒加载,提升用户体验,所以简单了解了一下ViewStub的用法后,就将原来的需要懒加载的Layout单独设置为一个xml文件。本来以为是没有问题,但是一看原来并不是这么简单。有好几个需要注意的点,现在分开来讲:

一、ViewStub多次inflate引发的exception:

ViewStub must have a non-null ViewGroup viewParent 相信第一次用的人应该都会遇到过这个的问题,我们进去inflate()的方法源码看看,

public View inflate() {

final ViewParent viewParent = getParent(); if (viewParent != null && viewParent instanceof ViewGroup) { if (mLayoutResource != 0) {
final ViewGroup parent = (ViewGroup) viewParent;
final LayoutInflater factory;
if (mInflater != null) {
factory = mInflater;
} else {
factory = LayoutInflater.from(mContext);
}
final View view = factory.inflate(mLayoutResource, parent,
false); if (mInflatedId != NO_ID) { view.setId(mInflatedId);
} final int index = parent.indexOfChild(this); parent.removeViewInLayout(this); final ViewGroup.LayoutParams layoutParams = getLayoutParams(); if (layoutParams != null) {
parent.addView(view, index, layoutParams);
} else {
parent.addView(view, index);
} mInflatedViewRef = new WeakReference<View>(view);
if (mInflateListener != null) {
mInflateListener.onInflate(this, view);
} return view; } else {
throw new IllegalArgumentException("ViewStub must have a valid layoutResource");
}
}

是不是很熟悉?由于ViewStub第一次inflate的时候,就已经将需要显示的布局替换掉自己了,所以第二次inflate的时候,getParent()是null,所以就会报异常。解决方法是inflate()的时候将view保存起来,然后下次判断这个View是否为NUll,如果是null就inflate().否则就直接使用这个view,还有一种就是setOnInflateListener,这个网上也有文章,这里不细说。如果被包含的layout的子View没有用户逻辑操作的,可以使用ViewStub的setVisibility()来控制显示和隐藏。里面已经做了inflate多次的判断的了,不会有异常的。

二、被包含的layout里面设置layout_margin属性失效而设置padding属性有效的问题。这个问题需要看源码才能解答,所以就看了一下源码。还是看inflate()方法。

final ViewGroup.LayoutParams layoutParams = getLayoutParams();
if (layoutParams != null) {
parent.addView(view, index, layoutParams);
else {
parent.addView(view, index);
}

看到这一段代码了吗?有个getLayoutParams() 以及 parent.addView方法。可以看到,getlayoutParams获取的是VeiwStub的LayoutParams,而不是被显示的Layout_params。所以,addView的时候,要么就是将ViewStub的layoutParams赋值给将要显示的view,要么直接调用addView(view,index),所以如果想要margin有效果,我们之能将layout_margin放到ViewStub里面,同理,如果是在相对布局里面,below_  above_这些属性控制都要放到viewStub那里,而不是放到将要显示的layout里面。那为什么padding会在将要显示的layout中起作用呢?这就要好好理解一下ViewGroup.LayoutParams layoutParams了,你会发现padding并不属于ViewGroup.LayoutParams layoutParams里面的,而是属于View的成员变量,这也就解释了为什么padding属性不会失效了,之前还以为padding设置ViewGroup.LayoutParams里面设置的呢。好了,这里相信大家对ViewStub都有一个很清晰的了解了,有什么问题,可以相互交流哦,如何比较优雅的使用ViewStub呢?经过本人试验,个人还是比较推荐使用setOnInflateListener,因为它只会被调用一次,就是刚inflate的时候,而且无论无论inflate的layout中是不是有其它的事件监听,它都可以实现。

我建了个qq群:207678498

总结

以上是生活随笔为你收集整理的正确使用ViewStub的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。