include 替换成 ViewStub .

2021-01-27  本文已影响0人  王家匀匀

ViewStub 的优点就是不用的布局,可以不加载。不像include,虽然没有显示,但是总要先加载布局。

xml 需要修改:
step1:
<include>替换成<ViewStub>标签。

step2:
layout 属性换成 android:layout.
注意,如果不修改,运行会奔溃。 报没有设置layout。

step3:
id 修改为带viewStub 的名字。不修改不报错,但是表意不清晰;

step4:
设置 android:inflatedId="@+id/your_layout"。
注意:如果与约束性布局结合使用, android:inflatedId 属性值必须与 android:id一致。
设置与 id不同的值不会报错,但是会导致约束失效。具体参考:
https://stackoverflow.com/questions/47164398/how-to-use-viewstub-in-constraintlayout

当与databinding 结合使用时,根据id获取viewStub.inflate获取到view,
根据 DataBindingUtil.getBinding(view)获取到 viewStub 的binding。
代码如下(这里的binding 是根布局binding):

     val inflateView = binding.contentViewStub.viewStub?.inflate()
     val newBinding = DataBindingUtil.getBinding<IncludeNewLayoutBinding>(inflateView)
     newBinding?.vm = vm 

注意事项:ViewStub 只能inflate一次。在可能被复用的地方格外要注意(比如recyclerView 的adapter中)
ViewStub inflate 后,就会被替换为对应的layout, 再获取父布局就为null.
也就是 上面的代码,如果inflate后 ,binding.contentViewStub.viewStub 获取到的就是null。
那么inflate后,怎么隐藏呢,设置 visibility 来控制。
参考代码:

  if (binding.contentViewStub.isInflated) {
                //viewStub 只能inflate 一次
               binding.contentViewStub.binding?.root?.visibility = View.VISIBLE
  } else {
                //这里viewStub肯定不为null
                val inflateView = binding.contentViewStub.viewStub!!.inflate()
                val newBinding = DataBindingUtil.getBinding<IncludeContentLayoutBinding>(inflateView)
                newBinding?.vm = vm
   }



题外话:
来看下源码ViewStubProxy.isInflated() 怎么判断的:很显然,加载后返回true,没加载返回false。

    /**
     * Returns <code>true</code> if the ViewStub has replaced itself with the inflated layout
     * or <code>false</code> if not.
     *
     * @return <code>true</code> if the ViewStub has replaced itself with the inflated layout
     * or <code>false</code> if not
     */
    public boolean isInflated() {
        return mRoot != null;
    }

getViewStub 可以看到,只要加载过就返回null.没有加载过就返回layout。
那么用之前判断下有没有加载过。加载过,控制可见性;没加载,如果需要显示直接加载。

    /**
     * Returns the ViewStub in the layout or <code>null</code> if the ViewStub has been inflated.
     *
     * @return the ViewStub in the layout or <code>null</code> if the ViewStub has been inflated.
     */
    @Nullable
    public ViewStub getViewStub() {
        return mViewStub;
    }
上一篇下一篇

猜你喜欢

热点阅读