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。
我在 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。