【问题标题】:How to check if a viewStub is already inflated?如何检查 viewStub 是否已经膨胀?
【发布时间】:2014-05-21 12:25:29
【问题描述】:

我没有找到任何布尔方法来完成这项任务。我可以通过检查 viewStub 的 id 是否更改为指定为 inflatedid 的那个来做到这一点吗?

Java代码:

    protected void plantViewTree() {
    // TODO Auto-generated method stub

        ViewStub mViewstub = (ViewStub) findViewById(R.id.viewStub00);

            if (mViewStub is inflated) {
              //do somthing
              }else
               mViewstub.inflate();

}

更新 对 eOutput 的评论

根据此代码,toast 始终显示其消息,这意味着由于 mViewStub 已分配给 findViewById,它永远不会为空,除非底层 alyout 中的 viewstub 视图不可用。有什么建议吗?

protected void plantViewTree() {
    // TODO Auto-generated method stub
    ViewStub mViewstub = (ViewStub) findViewById(R.id.viewStub00);
    if (mViewstub != null)
        Toast.makeText(getApplicationContext(), "view is inflated", 
Toast.LENGTH_LONG).show();
    else
        mViewstub.inflate();
}

【问题讨论】:

  • 如果不充气,则为空。你可以检查它是否为空。
  • @Eu.Dr.请看更新

标签: android view viewstub


【解决方案1】:

我们可以查看ViewStub源码,最重要的方法是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");
        }
    } else {
        throw new IllegalStateException("ViewStub must have a non-null ViewGroup viewParent");
    }
}

注意这一行parent.removeViewInLayout(this),它在inflate之后在布局中被删除了。所以我们可以通过这种方式检查viewStub是否已经被inflate。

if (mViewStub.getParent() != null) {
    mViewStub.inflate();
} else {
    mViewStub.setVisibility(View.VISIBLE);
}

【讨论】:

  • 查看viewstub是否完成了它的工作只是检查,mViewStub.getParent() != null,如果它没有完成它的工作父将是!= null否则父将是null
【解决方案2】:
if (mViewStub.getParent() != null) { 
    //have not been inflated
    mViewStub.inflate();
} else { 
    //already inflated
}

【讨论】:

    【解决方案3】:

    来自谷歌的注释:

    当 ViewStub 可见,或调用 inflate() 时, 布局资源被夸大了。

    这样您就可以检查可见性(甚至检查它是否为“null”)。

    【讨论】:

    • 这不是真的,viewstub 在膨胀时不为空
    【解决方案4】:

    一种更简单的方法,在 Kotlin 中:

    if (viewStub != null) {
       viewStub.isVisible = true
    } else {
       // The view has been inflated already.
    }
    

    【讨论】:

      【解决方案5】:

      你可以在 Kotlin 中使用它。我知道它使用标签(它并不酷)但它易于使用。 这是 kotlin 扩展功能:

      fun ViewStub.doInflate(init: View.() -> Unit = {}, action: (View) -> Unit = {}) {
      val isInflated = (tag as? Boolean) ?: false
      if (!isInflated) {
          setOnInflateListener { _, view ->
              this.tag = true
              init.invoke(view)
              action.invoke(view)
          }
          this.inflate()
      } else {
          action.invoke(this.rootView)
      }
      

      }

      你可以像这样使用它:

       myViewStub.doInflate({
                  //code that run with initialisation
              }, {
                 //code that run if stub already inflated
              })
      

      【讨论】:

        【解决方案6】:

        正如文档所暗示的,我们不应该对 ViewStub 进行长期引用,并且 android 还允许将 inflatedId 分配给 ViewStub,一旦它膨胀,它就会存在

        所以我们可以有一个像getInflatedView(): View这样的函数签名

        fun getInflatedView(@LayoutRes layoutId: Int): View {
            val stub: ViewStub? = findViewById(R.id.stubId)
            stub?.layoutResource = layoutId
            return stub?.inflate() ?: findViewById(R.id.inflatedId)
        }
        

        【讨论】:

          【解决方案7】:

          你可以使用这个扩展:

          /**
           * To prevent crash when we try inflate view that was already inflated. Because OS delete ViewStub by inflating.
           */
          fun ViewStub?.safeInflate() {
              if (this?.parent != null) inflate()
          }
          

          【讨论】:

            【解决方案8】:

            致电yourViewStub.visibility(View.VISIBLE),您无需检查它是否充气。

            【讨论】:

            • 得到了同样的迷恋。
            【解决方案9】:

            我使用flags 解决了这个问题。我声明了一个全局布尔变量isInflatedBefore set 最初是false

            代码:

            //declaration of the variable
            private boolean isInflatedBefore = false
            
            ...
            ... 
            ...
            
            protected void plantViewTree() {
                // TODO Auto-generated method stub
            
                ViewStub mViewstub = (ViewStub) findViewById(R.id.viewStub00);
            
                if (! isInflatedBefore) {
                    isInflatedBefore = true;
                    mViewstub.inflate();
                          }else {
                            //some code
                           }
            

            【讨论】:

              猜你喜欢
              • 2021-09-03
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-09-26
              • 1970-01-01
              相关资源
              最近更新 更多