2013-07-30 3 views
1

У меня есть ViewPager, позволяющий пользователю перемещаться между 5 различными видами, где каждый «вид» расширяет фрагмент.Фрагменты и ViewPager в Android

у меня есть свой собственный адаптер, который продлить FragmentPagerAdapter и которые реализуют GetItem() как

@Override public Fragment getItem(int position) { 
    switch(position) { 
     case 0: 
      return new TextDescriptionFragment(); 
     // Handle the 4 other cases the same way 
    } 
} 

Это прекрасно работает, и пользователь может сильно ударить между 5 различными видами. Но здесь возникает проблема: каждый из первых 4 просмотров содержит такие представления, как Button и EditText, с которыми пользователь может взаимодействовать.

И затем я хочу, чтобы последняя страница (Страница № 5) отображала все входные значения пользователя из всех видов с 4 предыдущих страниц (фрагментов). Как мне это сделать?

Я не могу найти способ считывать введенные пользователем значения из предыдущих фрагментов. Представления могут даже не существовать (но будут воссозданы, если пользователь вернется).

И я не могу получить существующие фрагменты.

+0

Но я не могу получить фрагменты для 4-х первых страниц. Они могут даже не существовать. – MTilsted

ответ

1

Я бы подумал о том, что пользовательский объект хранит данные, заполняемые каждым фрагментом. Что-то вроде:

public class FillerData implements Parcelable { 
    private String page0$data0; 
    private String page0$data1; 
    private String page0$data2; 

    // getters and setters if you wish 

    // implement Parcelable interface as this object will be managed by host activity 
} 

Вы будете иметь только один такой объект управляется родительской деятельности и родительская деятельность будет реализовать интерфейс для раскрытия этого объекта:

public static interface FillerDataExposer { 
    public FillerData exposeFiller(); 
} 

public class MyFragmentHostActivity extends FragmentActivity implements FillerDataExposer { 
    private static final String FILLER_KEY = "FILLER_KEY"; 
    private FillerData myFillerData; 

    protected void onCreate(Bundle savedInstance) { 
     ....... 
     if(savedInstance != null) { 
      myFillerData = (FillerData) savedInstance.getParcelable(FILLER_KEY); 
     } else { 
      myFillerData = new FillerData(); 
     } 
    } 

    protected void onSaveInstanceState(Bundle savedInstance) { 
     super.onSaveInstanceState(); 
     savedInstance.putExtra(FILLER_KEY, myFillerData); 
    } 

    public FillerData exposeFiller() { 
     return this.myFillerData; 
    } 
} 

Теперь каждый из ваших фрагментов будет иметь доступ к этому централизованному объекту наполнителя данных через родительскую активность.Для того, чтобы уменьшить вес вашего кода, все ваши фрагменты могут продлить из класса фрагмента базы, который обеспечивает доступ к FillerDataExposer реализации (на самом деле, родительская активность):

public abstract class AbstractFillerFragment extends Fragment { 
    protected FillerDataExposer dataExposer; 

    public void onAttach(Activity act) { 
     super.onAttach(act); 
     // make sure no ClassCastExceptions 
     this.dataExposer = (FillerDataExposer) act; 
    } 
} 

Фрагменты, которые должны записать только данные, заполненные может выглядеть это:

public class Page1Fragment extends AbstractFillerFragment { 

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = // inflate XML resource ... 
     yourEditText = (EditText) view.findViewById(...); 
     // other relevant code .... 
    } 

    public void onViewCreated(View view, Bundle savedInstanceState) { 
     yourEditText.setText(dataExposer.exposeFiller.setPageX$DataY()); 
     // some code for EditText.addTextChangedListener(new TextWatcher() could look like: 
     yourEditText.addTextChangedListener(new TextWatcher() { 

      public void afterTextChanged(Editable s) { 

      dataExposer.exposeFiller().setPage1$Data0(s.toString()); 

      } 

      public void beforeTextChanged(CharSequence s, int start, int count, int after) {} 

      public void onTextChanged(CharSequence s, int start, int before, int count) {} 
     }); 
    } 
} 

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

public class FinalFragment extends AbstractFillerFragment { 
    public void collectAllData() { 
     DataFiller allDataCollectedObject = dataExposer.exposeFiller(); 
     // by calling get...() you should have access to collected data. 
    } 
} 

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

Надеюсь, это имеет смысл ...

+0

Проблема в том, что, как и в onpause, onSaveInstanceState (Bundle savedInstance) не будет вызываться для всех фрагментов, когда я просматриваю последний фрагмент. – MTilsted

+0

Вам не нужно заботиться о onpause. Данные доступны все время повсюду, что бы вы ни делали. – gunar

+0

Одна вещь для добавления: для каждого фрагмента вам нужно установить edittext или другие представления в данные, уже находящиеся в DataFiller. Это можно сделать в onViewCreated. – gunar

0

2 решения приходят мне на ум.

Первый - это сохранение пользовательских входных данных при вызове методов первого 4-х фрагмента onpause(). Вы можете сохранить данные в предпочтении, а затем извлечь их из своего 5-го фрагмента.

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

yourcustomviewpager.setOffscreenPageLimit(5); 

О setOffscreenPageLimit из the android doc:

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

+0

Остановленный трюк не работает, потому что onpause не вызывается для страницы 3, когда просматривается страница 4 (Последняя страница). – MTilsted

+0

Вы правы. Таким образом, вы можете сохранять входные данные каждый раз, когда ввод изменяется (вы должны установить прослушиватели для ваших текстовых просмотров). –

+0

Плотина, это много кода. И мне действительно нужен метод fragmentNotVisibleAnymore(). Я думаю, что я попытаюсь использовать setOnPageChangeListener, который затем может вызвать метод в каждом фрагменте для сбора всех данных. – MTilsted

Смежные вопросы