Intereting Posts

Просмотр фрагмента ViewPager's, потерянный при отображении родительского фрагмента ViewPager, затем отображается

Я видел некоторое странное поведение с моим ViewPager вместе со своим собственным FragmentStatePagerAdapter.

Иерархия My View выглядит следующим образом:

-> (1) Fragment root view (RelativeLayout) -> (2) ViewPager -> (3) ViewPager's current fragment view 

Когда фрагмент, отвечающий за корневой вид фрагмента (1), скрывается (используя операцию hid () в транзакции фрагмента), а затем отображается (с .show ()), представление фрагмента, которое в настоящее время отображается в ViewPager (3 ) Становится нулевым, хотя фрагмент все еще существует. В принципе, мой ViewPager становится полностью пустым / прозрачным.

Единственный способ найти это – позвонить

 int current = myViewPager.getCurrentItem(); myViewPager.setAdapter(myAdapter); myViewPager.setCurrentItem(current); 

После отображения родительского фрагмента. Это как-то заставляет взгляды воссоздаваться и появляться на экране. К сожалению, это иногда вызывает исключения, связанные с адаптером пейджера, вызывающим unregisterDataSetObserver() дважды на старом наблюдателе.

Есть лучший способ сделать это? Я предполагаю, что я спрашиваю:

Почему мои фрагменты в моем представлении ViewPager уничтожаются, когда родительский фрагмент ViewPager скрыт?

Обновление: это также происходит, когда приложение «сведено к минимуму», а затем «восстановлено» (нажатием клавиши домашнего действия и последующим возвратом).

По запросу, вот мой класс адаптера пейджера:

 public class MyInfoSlidePagerAdapter extends FragmentStatePagerAdapter { private ArrayList<MyInfo> infos = new ArrayList<MyInfo>(); public MyInfoSlidePagerAdapter (FragmentManager fm) { super(fm); } public MyInfoSlidePagerAdapter (FragmentManager fm, MyInfo[] newInfos) { super(fm); setInfos(newInfos); } @Override public int getItemPosition(Object object) { int position = infos.indexOf(((MyInfoDetailsFragment)object).getMyInfo()); return position > 0 ? position : POSITION_NONE; } @Override public CharSequence getPageTitle(int position) { return infos.get(position).getName(); } @Override public Fragment getItem(int i) { return infos.size() > 0 ? MyInfoDetailsFragment.getNewInstance(infos.get(i)) : null; } @Override public int getCount() { return infos.size(); } public Location getMyInfoAtPosition(int i) { return infos.get(i); } public void setInfos(MyInfo[] newInfos) { infos = new ArrayList<MyInfo>(Arrays.asList(newInfos)); } public int getPositionOfMyInfo(MyInfo info) { return infos.indexOf(info); } } 

Я переименовал некоторые переменные, но кроме этого, это именно то, что у меня есть.

Solutions Collecting From Web of "Просмотр фрагмента ViewPager's, потерянный при отображении родительского фрагмента ViewPager, затем отображается"

Вы не предоставляете достаточную информацию для своей конкретной проблемы, поэтому я создал образец проекта, который пытается воспроизвести вашу проблему: приложение имеет активность, содержащую фрагмент ( PagerFragment ) в относительном макете и ниже этого макета. У меня есть кнопка, которая Скрывает и показывает выше PagerFragment . PagerFragment имеет ViewPager и каждый фрагмент в адаптере пейджера просто отображает метку – этот фрагмент называется DataFragment . Список меток создается в родительской активности и передается в PagerFragment, а затем через его адаптер для каждого DataFragment . Изменение видимости PagerFragment выполняется без проблем, и каждый раз, когда он становится видимым снова, он показывает предыдущую отображаемую метку.

Ключ проблемы: используйте Fragment # getChildFragmentManager (), когда вы создаете адаптер viewpager, а не getFragmentManager!

Возможно, вы можете сравнить этот простой проект с тем, что у вас есть, и проверить, где различия. Итак, здесь идет (сверху вниз):

PagerActivity (единственная деятельность в проекте):

 public class PagerActivity extends FragmentActivity { private static final String PAGER_TAG = "PagerActivity.PAGER_TAG"; @Override protected void onCreate(Bundle savedInstance) { super.onCreate(savedInstance); setContentView(R.layout.pager_activity); if (savedInstance == null) { PagerFragment frag = PagerFragment.newInstance(buildPagerData()); FragmentManager fm = getSupportFragmentManager(); fm.beginTransaction().add(R.id.layout_fragments, frag, PAGER_TAG).commit(); } findViewById(R.id.btnFragments).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { changeFragmentVisibility(); } }); } private List<String> buildPagerData() { ArrayList<String> pagerData = new ArrayList<String>(); pagerData.add("Robert de Niro"); pagerData.add("John Smith"); pagerData.add("Valerie Irons"); pagerData.add("Metallica"); pagerData.add("Rammstein"); pagerData.add("Zinedine Zidane"); pagerData.add("Ronaldo da Lima"); return pagerData; } protected void changeFragmentVisibility() { Fragment frag = getSupportFragmentManager().findFragmentByTag(PAGER_TAG); if (frag == null) { Toast.makeText(this, "No PAGER fragment found", Toast.LENGTH_SHORT).show(); return; } boolean visible = frag.isVisible(); Log.d("APSampler", "Pager fragment visibility: " + visible); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); if (visible) { ft.hide(frag); } else { ft.show(frag); } ft.commit(); getSupportFragmentManager().executePendingTransactions(); } } 

Его файл макета pager_activity.xml

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="4dp" > <Button android:id="@+id/btnFragments" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:text="Hide/Show fragments" /> <RelativeLayout android:id="@+id/layout_fragments" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/btnFragments" android:layout_marginBottom="4dp" > </RelativeLayout> </RelativeLayout> 

Обратите внимание, что я добавляю PagerFragment когда активность сначала показана, и класс PagerFragment :

 public class PagerFragment extends Fragment { private static final String DATA_ARGS_KEY = "PagerFragment.DATA_ARGS_KEY"; private List<String> data; private ViewPager pagerData; public static PagerFragment newInstance(List<String> data) { PagerFragment pagerFragment = new PagerFragment(); Bundle args = new Bundle(); ArrayList<String> argsValue = new ArrayList<String>(data); args.putStringArrayList(DATA_ARGS_KEY, argsValue); pagerFragment.setArguments(args); return pagerFragment; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); data = getArguments().getStringArrayList(DATA_ARGS_KEY); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.pager_fragment, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { pagerData = (ViewPager) view.findViewById(R.id.pager_data); setupPagerData(); } private void setupPagerData() { PagerAdapter adapter = new LocalPagerAdapter(getChildFragmentManager(), data); pagerData.setAdapter(adapter); } } 

Его макет (только ViewPager, который принимает полный размер):

 <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager_data" android:layout_width="match_parent" android:layout_height="match_parent" /> 

И его адаптер:

 public class LocalPagerAdapter extends FragmentStatePagerAdapter { private List<String> pagerData; public LocalPagerAdapter(FragmentManager fm, List<String> pagerData) { super(fm); this.pagerData = pagerData; } @Override public Fragment getItem(int position) { return DataFragment.newInstance(pagerData.get(position)); } @Override public int getCount() { return pagerData.size(); } } 

Этот адаптер создает DataFragment для каждой страницы:

 public class DataFragment extends Fragment { private static final String DATA_ARG_KEY = "DataFragment.DATA_ARG_KEY"; private String localData; public static DataFragment newInstance(String data) { DataFragment df = new DataFragment(); Bundle args = new Bundle(); args.putString(DATA_ARG_KEY, data); df.setArguments(args); return df; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); localData = getArguments().getString(DATA_ARG_KEY); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.data_fragment, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { view.findViewById(R.id.btn_page_action).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getActivity(), localData, Toast.LENGTH_SHORT).show(); } }); ((TextView) view.findViewById(R.id.txt_label)).setText(localData); } } 

DataFragment компоновка DataFragment :

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="4dp" > <Button android:id="@+id/btn_page_action" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:text="Interogate" /> <TextView android:id="@+id/txt_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textAppearance="?android:attr/textAppearanceLarge" /> </RelativeLayout> 

Наслаждайтесь кодированием!

Возможно, это поможет mViewPager.setOffscreenPageLimit (5)

Задайте количество страниц, которые должны быть сохранены в обе стороны текущей страницы в иерархии представлений в состоянии ожидания. Страницы, выходящие за этот предел, будут воссозданы с адаптера, если это необходимо.

Это предлагается как оптимизация. Если вы заранее знаете количество страниц, которые вам понадобятся для поддержки или имеют механизмы ленивой загрузки на ваших страницах, настройка этой настройки может иметь преимущества в воспринимаемой гладкости анимации и взаимодействия пейджинга. Если у вас есть небольшое количество страниц (3-4), которые вы можете сохранить активными одновременно, меньше времени будет потрачено на макет для вновь созданных подтипов просмотра в качестве страниц пользователя взад и вперед.

Вы должны держать этот предел низким, особенно если ваши страницы имеют сложные макеты. По умолчанию этот параметр равен 1.

View Pager довольно непреклонен в сохранении свежести Fragments и, таким образом, оптимизации производительности, освобождая память, когда фрагмент не используется. Очевидно, что это полезная полезная черта в мобильной системе. Но из-за этого постоянного освобождения ресурсов фрагмент создается каждый раз, когда он получает фокус.

 mViewPager.setOffscreenPageLimit(NUMBEROFFRAGMENTSCREENS); 

Вот документация.

Эта старая почта имеет интересное решение для вашей проблемы .. Пожалуйста, обратитесь

У меня такая же проблема. В моем приложении (FragmentActivity) есть пейджер (ViewPager) с 3 кадрами. При прохождении между фрагментами они уничтожаются и воссоздаются все время. На самом деле это не создает проблем в функциональности (ожидайте незамкнутых курсоров), но я тоже задавался вопросом об этом вопросе.

Я не знаю, есть ли временное решение для изменения поведения ViewPager, но я предлагаю иметь объект конфигурации (возможно, статический) и до уничтожения сохранить объект myViewPager объекте config.

 public class App extends FragmentActivity { static MyData data; @Override protected void onCreate(Bundle savedInstanceState) { data = (MyData) getLastCustomNonConfigurationInstance(); if (data == null) { data = new MyData(); data.savedViewPager = myViewPager; } else { myViewPager = data.savedViewPager; } } @Override public Object onRetainCustomNonConfigurationInstance() { Log.d("onRetainCustomNonConfigurationInstance", "Configuration call"); return data; } } public class MyData { public ViewPager savedViewPager; } 

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

Надеюсь, вы найдете мое предложение полезным!