如何检查 viewStub 是不是已经膨胀?

Posted

技术标签:

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

我没有找到任何布尔方法来完成这项任务。我可以通过检查 viewStubid 是否更改为指定为 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.请看更新 【参考方案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
               

【讨论】:

以上是关于如何检查 viewStub 是不是已经膨胀?的主要内容,如果未能解决你的问题,请参考以下文章

ViewStub 在有条件地膨胀多个布局时引发错误

动态更改视图存根 layout_height 属性?

创建新视图时动态隐藏视图

如何检查线性布局中是不是有可用空间

如何检测圆形腐蚀/膨胀

我们可以通过检查 isRegisteredForLocalNotifications 从 didRegisterForRemoteNotificationsWithDeviceToken 更新 Vie