Android <include/> 有效,但 ViewStub 无效,为什么?

Android <include/> works but ViewStub doesn't, why?

我在 FrameLayout 中使用 ViewStub,这样我就可以在第一次打开应用程序时使用教程视图对其进行扩充。

我的Activity.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">

   ...

   <ViewStub
       android:id="@+id/introHolder"
       android:inflatedId="@+id/introHolder"
       android:layout="@layout/intro_landing1"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />
</FrameLayout>

我正在膨胀的视图称为 intro_landing1.xml,它是一个 RelativeLayout。

intro_landing1.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent" android:background="@color/opaqBlack30"
android:id="@+id/introView1"
android:tag="RelativeLayoutIntroViewTag">

<!--...-->

</RelativeLayout>

在我的 Activity onCreate 中,我使用了两种不同的方法来膨胀 ViewStub,但它们都不起作用(我看不到 intro_landing1 视图)。

第一种方法 - 设置可见性:

if(!previouslyStarted){
   ((ViewStub) findViewById(R.id.introHolder)).setVisibility(View.VISIBLE);
}

第二种方法 - 给 ViewStub 充气:

ViewStub introStub =  (ViewStub) findViewById(R.id.introHolder);
introStub.setLayoutResource(R.layout.intro_landing1);
View inflatedView = introStub.inflate();

使用第二种方法,我通过执行 inflatedView.getTag 记录了返回的视图 (inflatedView),它返回了 intro_landing1 RelativeLayout 的标签 "RelativeLayoutIntroViewTag" 所以实际上返回了视图,但我没有看到它。

为了确保我在视图树层次结构中正确定位了 ViewStub,我在 Activity.xml 中使用了 <include/> 标记,而不是像这样的 ViewStub:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">

   ...

   <!-- <ViewStub
       android:id="@+id/introHolder"
       android:inflatedId="@+id/introHolder"
       android:layout="@layout/intro_landing1"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />-->

   <include layout="@layout/intro_landing1"/>

</FrameLayout>

这行得通。

为什么在可见性更改或 inflation 后不显示 ViewStub?

谢谢!

所以我无法重现你的问题。我将在这里分享我的裸代码,因为它适用于我的设置。
我怀疑您可能在某处有一些额外的代码,这些代码可能会错误地与您尝试做的事情进行交互。 (我试着把它设置得尽可能接近问题)

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.myexample.helloworld.MainActivity">

    <ViewStub
        android:id="@+id/myViewStub"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:inflatedId="@+id/myInflatedViewStub"
        android:visibility="gone"
        android:layout="@layout/stub"/>
</FrameLayout>

stub.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="100dp"
        android:text="Large Text"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"/>
</RelativeLayout>

MainActivity.java

public class MainActivity
        extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ((ViewStub) findViewById(R.id.myViewStub)).setVisibility(View.VISIBLE);
    }
}

P.S。我通常 link 到一个演示项目,但在这种情况下没有太多代码,如果有人看到答案,它不会依赖于将来的 link。希望对你有帮助

这可以帮助您理解 ViewStub 行为
2. ViewStub 不设置布局资源和inflation 无法更改可见性。所以一旦你设置了布局资源,你就可以 inflate 或者 setVisibility(View.VISIBLE);
3. 当方法 inflate() 被调用时,ViewStub 被从其父视图中移除并被正确的视图(布局的根视图)替换。
更多How to use View Stub in android

事实证明我的实施是正确的,但实际情况是这样的:

在启动我的应用程序时打开教程视图(膨胀 ViewStub)并将之前启动的写入共享首选项(SP),然后立即重新启动 activity(运行 onCreated ) 但这次教程视图没有膨胀,因为 if sentense 失败。

这只会在应用程序第一次打开时发生,因此无法立即确定问题所在

我仍然不知道为什么它会在第一次打开应用程序时重新启动活动,但我相信这是由于内存问题。

我把教程inflation标志写入SP解决了,只有在用户按照步骤操作后才解决。

由于@Alex.F的回答几乎是正确的,我将其标记为awnser。