Обработка изменений ориентации с помощью фрагментов

В настоящее время я тестирую свое приложение с многопанельным представлением Fragment с использованием пакета совместимости HC, и у меня много проблем с обработкой изменений ориентации.

Моя активность Host имеет 2 панели в альбомной ориентации (menuFrame и contentFrame) и только menuFrame в портретной ориентации, в которые загружаются соответствующие фрагменты. Если у меня есть что-то в обеих панелях, но затем я меняю ориентацию на книжную, я получаю NPE, поскольку он пытается загрузить представления во фрагменте, который будет в (несуществующем) contentFrame. Использование метода setRetainState() во фрагменте содержимого не сработало. Как я могу разобраться с этим, чтобы система не загружала фрагмент, который не будет отображаться?

Большое спасибо!


person Alex Curran    schedule 28.05.2011    source источник


Ответы (3)


Кажется, что onCreateViewMethod вызывал проблемы; он должен возвращать значение null, если контейнер имеет значение null:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {   
    if (container == null) // must put this in
        return null;
    return inflater.inflate(R.layout.<layout>, container, false);
}
person Alex Curran    schedule 10.08.2011
comment
это не избавляет от фрагмента. Это просто мешает его рисовать. Он все еще находится в памяти, и вы будете дублировать свои фрагменты при каждом повороте. - person Marty Miller; 16.07.2014

Вероятно, это не идеальный ответ, но если у вас есть contentFrame для портрета, и в вашей деятельности загружается только menuFrame, когда saveInstanceState имеет значение null, тогда фрагменты фрейма вашего контента будут отображаться при изменении ориентации.

Хотя не идеально, так как тогда, если вы нажмете кнопку «Назад» (столько раз, сколько необходимо), вы никогда не увидите фрагмент меню, так как он не был загружен в contentFrame.

Жаль, что демонстрационные примеры API FragmentLayout не сохраняют правильное состояние фрагмента при изменении ориентации. Тем не менее, поразмыслив над этой проблемой и испробовав разные вещи, я не уверен, что есть прямой ответ. Лучший ответ, который я придумал до сих пор (не проверенный), - это иметь одинаковую компоновку в книжной и альбомной ориентации, но скрыть menuFrame, когда что-то есть в detailsFrame. Точно так же покажите его и скройте frameLayout, когда последний пуст.

person PJL    schedule 06.06.2011

Создавайте новый экземпляр только в первый раз.

Это помогает:
Создайте новый экземпляр фрагмента при первом запуске действия, в противном случае повторно используйте старый фрагмент.
Как вы можете это сделать?
FragmentManager — это ключ

Вот фрагмент кода:

if(savedInstanceState==null) {
    userFragment = UserNameFragment.newInstance();
    fragmentManager.beginTransaction().add(R.id.profile, userFragment, "TAG").commit();
}
else {
    userFragment = fragmentManager.findFragmentByTag("TAG");
}

Сохранить данные на стороне фрагмента

Если в вашем фрагменте есть EditText, TextViews или любые другие переменные класса, которые вы хотите сохранить при изменении ориентации. Сохраните его onSaveInstanceState() и извлеките их методом onCreateView()

Вот фрагмент кода:

// Saving State

@Override
public void onSaveInstanceState(Bundle outState) {
     super.onSaveInstanceState(outState);
     outState.putString("USER_NAME", username.getText().toString());
     outState.putString("PASSWORD", password.getText().toString());
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {

     View view = inflater.inflate(R.layout.user_name_fragment, parent, false);

     username = (EditText) view.findViewById(R.id.username);
     password = (EditText) view.findViewById(R.id.password);


     // Retriving value

     if (savedInstanceState != null) {
         username.setText(savedInstanceState.getString("USER_NAME"));
         password.setText(savedInstanceState.getString("PASSWORD"));
     }

     return view;
}

Вы можете увидеть полный рабочий код ЗДЕСЬ

person Rohit Singh    schedule 31.12.2018