Android Fragment получает пустой контейнер в onCreateView()

Я пытаюсь использовать фрагменты Android очень просто, подобно учебнику на веб-сайте разработчика Android.

У меня есть Activity (MediaInfoActivity) со следующим кодом:

public class MediaInfoActivity extends FragmentActivity {
    private final String TAG = "MediaInfoActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate()");
        setContentView(R.layout.media_info_activity_layout);
    }

}

Вот код для файла media_info_activity_layout.xml:

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

    <fragment class="com.hawkforce.test.MediaInfoFragment"
            android:id="@+id/mediaInfoFragment"
            android:layout_weight="1"
            android:layout_width="match_parent"
            android:layout_height="0dp" />

    <FrameLayout android:id="@+id/mediaPlayerBarPanel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >

    <fragment class="com.hawkforce.test.MediaPlayerBarFragment"
                android:id="@+id/mediaPlayerBar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

    </FrameLayout>

И, наконец, вот код для MediaInfoFragment:

public class MediaInfoFragment extends Fragment {
    private final static String TAG = "MediaInfoFragment";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate()");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        Log.i(TAG, "onCreateView()");
        if (container == null) {
            Log.i(TAG, "onCreateView(): container = null");
        }

        return inflater.inflate(R.layout.media_info_fragment_layout, container, false);
    }

}

Вот моя проблема: контейнер, переданный в методе onCreateView() MediaInfoFragment, имеет значение null. Насколько я понял, это должно иметь место только для фрагментов, отличных от UI. Однако у моего Fragment есть пользовательский интерфейс, который отображается на экране при запуске MediaInfoActivity. Это вызывает проблемы, потому что не применяется стиль, объявленный в файле макета xml фрагмента.

Вот мой журнал:

I/MediaInfoActivity: onCreate()
I/MediaInfoFragment: onCreate()
I/MediaInfoFragment: onCreateView()
I/MediaInfoFragment: onCreateView(): container = null

Я не вижу здесь ничего очевидного?

Ответы

Ответ 1

Вам просто нужно создать надувник, подобный ребрам в вашем фрагменте.

View rootView;
 public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    if (rootView == null) {
        rootView = inflater.inflate(R.layout.activity_my_cart, null);
    } else {
        ((ViewGroup) container.getParent()).removeView(rootView);
    }
    return rootView;
}

Я надеюсь, что это сработает по вашему вопросу.

Ответ 2

Я не уверен, так как у меня нет кода SDK передо мной, но я думаю, что жизненный цикл вызова функции "onCreateView" отличается от двух случаев: 1. Статические настройки фрагмента в макете 2. Загрузка прагматически с помощью FragmentManager.

В первом случае отладчик попадает в метод Fragment.onCreateView() сразу после добавления представления содержимого в родительскую активность как часть кода onCreate():

При вызове: setContentView (R.layout.some_layoue); Вы увидите отладчик в Fragment.onCreateView(), прежде чем перейти к следующей строке

Во втором случае Fragment.onCreateView() вызывается только после завершения операции onCreate().

Это выглядит как ошибка дизайна для меня, но, возможно, как функция дизайна. В любом случае контейнер имеет значение null при добавлении фрагмента статически, потому что связанный объект еще не создан.

Фактически разница между двумя ситуациями намного глубже. В случае переключения статических фрагментов между фрагментами правильная иерархия представлений не будет правильно.

Например, если вы добавите кнопку-A в фрагмент A и кнопку-B в фрагмент-B и переключите фрагменты с кодом, который выглядит так (выделение только соответствующего кода):

public void turnOnFragment() {
    FragmentManager manager = getFragmentManager();
    if (manager != null) {
        manager.beginTransaction()
                .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
                .attach(this)
                .commit();
    }
}



public void turnOffFragment() {
    FragmentManager manager = getFragmentManager();
    if (manager != null) {
        manager.popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        manager.beginTransaction()
                .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
                .detach(this)
                .commit();


    }
}

Вы увидите, что в случае статических фрагментов кнопки из обоих фрагментов представлены, хотя и включаются и выключаются. Если, однако, фрагменты добавляются программно, то переключатель отлично работает, а иерархия просмотра очищается и отображается только кнопка из соответствующего фрагмента.

Это основано на моем опыте с версией 4.4.2