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