Android <include /> работает, а ViewStub - нет, почему?

Я использую ViewStub внутри FrameLayout, чтобы я мог раздувать его с помощью учебника, когда приложение открывается в первый раз.

Моя активность.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).

1-й подход - настройка видимости:

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

2-й подход - раздувание ViewStub:

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

При втором подходе я регистрировал возвращенное представление (inflatedView), выполняя inflatedView.getTag, и он возвращал тег RelativeLayout intro_landing1 "RelativeLayoutIntroViewTag", поэтому представление фактически возвращается, но я его не вижу.

Чтобы убедиться, что я правильно разместил ViewStub в иерархии дерева представлений, я использовал <include/> тег в файле Activity.xml вместо 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>

И это работает.

Почему он не показывает ViewStub после изменения видимости или инфляции?

Спасибо!

3 ответа

Решение

Поэтому я не смог воспроизвести вашу проблему. Здесь я поделюсь своим голым кодом, как он работает на моей установке.
Я подозреваю, что у вас может быть где-то дополнительный код, который может неправильно взаимодействовать с тем, что вы пытались сделать. (Я попытался установить это как можно ближе к вопросу)

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);
    }
}

PS Обычно я делаю ссылки на демонстрационный проект, но в этом случае кода не так много, и в будущем он не будет зависеть от ссылки, если кто-нибудь когда-нибудь увидит ответ. Надеюсь, поможет

Оказывается, моя реализация была правильной, но вот что произошло:

При загрузке мое приложение открыло представление учебника (накачало ViewStub) и записало ранее запущенные в общие предпочтения (SP) и сразу после этого перезапустило действие (снова запустил onCreated), но на этот раз представление учебника не было раздутым, потому что если приговор провалился.

Это происходит только в первый раз, когда приложение открывается, и поэтому было неясно, что это была проблема

Я до сих пор не знаю, почему он запускает работу при первом открытии приложения, но я верю, что это связано с проблемой памяти.

Я решил это, написав флаг инфляции учебника в SP только после того, как пользователи выполнили шаги.

Поскольку ответ @Alex.F был практически правильным, я отмечу его как awnser.

Пусть это поможет вам понять ViewStub поведение
2. ViewStub нельзя изменить видимость без настройки макета ресурса и инфляции. поэтому, как только вы установите ресурс макета, вы можете inflate или же setVisibility(View.VISIBLE);
3. Когда метод inflate() вызывается ViewStub удаляется из его родителя и заменяется правым представлением (корневым представлением вашего макета).
Подробнее о том, как использовать View Stub в Android

Другие вопросы по тегам