1

У меня есть ViewPager, размещенный во фрагменте, который содержит два ListFragments, которые заполнены Cursor, возвращенными из SQLite-запроса. Недавно я добавил spinner в свою панель действий, которая позволит пользователю сортировать списки в ViewPager. Тем не менее, каждый раз, когда выбран счетчик, сортируется только второй список, даже когда отображается первый список. Похоже, что ViewPager не отслеживает отображаемый в настоящее время ListFragment.ViewPager FragmentPagerAdapter обновляет только последний фрагмент onNavigationItemSelected

Я пробовал переопределить getItemPosition в моем адаптере и использовать n otifyDataSetChanged, но это не поможет. Я попытался кэшировать положение текущего активного фрагмента в onAttach(), но безрезультатно. Я также попытался использовать интерфейс OnSortChanged, реализованный моим адаптером, чтобы попытаться воссоздать ListFragments. Я действительно в недоумении. Вот мой текущий код:

Мой главный фрагмент:

public class BeerMenuFragment extends SherlockFragment { 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.beer_menu_fragment, container, 
      false); 
    ViewPager pager = (ViewPager) view.findViewById(R.id.beer_pager); 

    pager.setAdapter(buildAdapter()); 
    return view; 
} 

private PagerAdapter buildAdapter() { 
    return (new BeerMenuAdapter(getChildFragmentManager())); 
} 
} 

Мои FragmentPagerAdapter:

public class BeerMenuAdapter extends FragmentPagerAdapter { 
private final int NUM_ITEMS = 2; 

public BeerMenuAdapter(FragmentManager fm) { 
    super(fm); 
} 

/* 
* (non-Javadoc) 
* 
* @see android.support.v4.view.PagerAdapter#getPageTitle(int) 
*/ 
@Override 
public CharSequence getPageTitle(int position) { 
    return BeerListFragment.getTitle(position); 
} 

@Override 
public int getCount() { 
    return NUM_ITEMS; 
} 

@Override 
public Fragment getItem(int position) { 
    return BeerListFragment.newInstance(position); 
} 
} 

И, наконец, ListFragment:

public class BeerListFragment extends SherlockListFragment implements 
    OnNavigationListener { 
private static final String KEY_POSITION = "position"; 
private static final String KEY_SPINNER = "ab_spinner"; 
private IconicAdapter adapter; 
private static final String[] LABELS = { "Newest First", "Oldest First", 
     "Alphabetical" }; 
private Context ctxt; 
private int mShowItems; 
private Cursor data; 
private boolean synthetic = true; 

static BeerListFragment newInstance(int position) { 
    BeerListFragment frag = new BeerListFragment(); 
    Bundle args = new Bundle(); 

    args.putInt(KEY_POSITION, position); 
    frag.setArguments(args); 
    return (frag); 
} 

static String getTitle(int position) { 
    String header = "Draft"; 
    switch (position) { 
    case 0: 
     header = "Draft"; 
     break; 
    case 1: 
     header = "Bottle"; 
     break; 
    } 
    return (header); 
} 

/* 
* (non-Javadoc) 
* 
* @see 
* android.support.v4.app.ListFragment#onCreateView(android.view.LayoutInflater 
* , android.view.ViewGroup, android.os.Bundle) 
*/ 
@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
    View result = inflater.inflate(R.layout.menu_list_fragment, container, 
      false); 

    ctxt = getActivity().getApplicationContext(); 
    SQLiteDatabase db = DatabaseHelper.getInstance(ctxt) 
      .getReadableDatabase(); 

    SherlockFragmentActivity activity = getSherlockActivity(); 
    ArrayAdapter<String> show = null; 
    ActionBar bar = activity.getSupportActionBar(); 

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 
     show = new ArrayAdapter<String>(bar.getThemedContext(), 
       android.R.layout.simple_spinner_item, LABELS); 
    } else { 
     show = new ArrayAdapter<String>(activity, 
       android.R.layout.simple_spinner_item, LABELS); 
    } 

    show.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 
    bar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 
    bar.setListNavigationCallbacks(show, this); 

    if (savedInstanceState != null) { 
     bar.setSelectedNavigationItem(savedInstanceState 
       .getInt(KEY_SPINNER)); 
    } 

    data = getBeerMenuDbData(db, mShowItems); 

    // set up list adapter 
    adapter = new IconicAdapter(ctxt, data); 

    setListAdapter(adapter); 
    return (result); 
} 

private Cursor getBeerMenuDbData(SQLiteDatabase db, int showItems) { 
    String order; 
    String WHERE; 
    switch (showItems) { 
    case 1: // Oldest First 
     order = DbContract.BeerEntry.COLUMN_MODIFIED + " ASC"; 
     break; 
    case 2: // Alphabetical 
     order = DbContract.BeerEntry.COLUMN_TITLE + " ASC"; 
     break; 
    default: // Newest first 
     order = DbContract.BeerEntry.COLUMN_MODIFIED + " DESC"; 
     break; 
    } 
    String[] COLUMNS = { DbContract.BeerEntry._ID, 
      DbContract.BeerEntry.COLUMN_TITLE, 
      DbContract.BeerEntry.COLUMN_MODIFIED }; 
    WHERE = "serving='" + getTitle(getArguments().getInt(KEY_POSITION, -1)) 
      + "'"; 
    return db.query(DbContract.BeerEntry.TABLE_NAME, COLUMNS, WHERE, null, 
      null, null, order); 
} 

class IconicAdapter extends CursorAdapter { 
    LayoutInflater inflater; 

    IconicAdapter(Context context, Cursor data) { 
     super(context, data, 0); 
     inflater = LayoutInflater.from(context); 
    } 

    @Override 
    public void bindView(View view, Context context, Cursor cursor) { 
     String dateString = cursor.getString(2); 
     String[] dateArray = new String[3]; 
     TextView beerName = (TextView) view.findViewById(R.id.beerName); 
     TextView date = (TextView) view.findViewById(R.id.drinkDate); 
     RatingBar rb = (RatingBar) view.findViewById(R.id.ratingBar1); 

     beerName.setText(cursor.getString(1)); 
     if (!dateString.isEmpty()) { 
      dateArray = dateString.split("-"); 
      date.setText(dateArray[1] + "/" + dateArray[2] + "/" 
        + dateArray[0]); 
     } else { 
      date.setText(dateString); 
     } 
     rb.setRating((float) Math.random() * 5.0f); 
    } 

    @Override 
    public View newView(Context context, Cursor cursor, ViewGroup parent) { 
     return inflater 
       .inflate(R.layout.beer_club_list_item, parent, false); 
    } 
} 

/* 
* (non-Javadoc) 
* 
* @see android.support.v4.app.Fragment#onDestroy() 
*/ 
@Override 
public void onDestroy() { 
    super.onDestroy(); 
    ((CursorAdapter) getListAdapter()).getCursor().close(); 
} 

@Override 
public boolean onNavigationItemSelected(int itemPosition, long itemId) { 
    if (synthetic) { 
     synthetic = false; 
     return true; 
    } 

    mShowItems = itemPosition; 
    SQLiteDatabase db = DatabaseHelper.getInstance(ctxt) 
      .getReadableDatabase(); 
    Cursor newData = getBeerMenuDbData(db, mShowItems); 
    adapter.changeCursor(newData); 
    return true; 
} 

@Override 
public void onSaveInstanceState(Bundle outState) { 
    outState.putInt(KEY_SPINNER, getSherlockActivity() 
      .getSupportActionBar().getSelectedNavigationIndex()); 
} 
} 

Заранее спасибо за любую помощь !

+0

Из любопытства запишите вызовы 'onNavigationItemSelected' и посмотрите, вызваны ли они для обоих экземпляров' BeerListFragment', или только один экземпляр.Моя догадка заключается в том, что когда вы вызываете 'setListNavigationCallbacks' для вашего второго' BeerListFragment', он перезаписывает обратный вызов первого, поэтому первый не получает обратный вызов для сортировки своих данных, а второй - всегда. –

+0

@steven, я зарегистрировался так, как вам было предложено, и я получаю один вызов «onNavigationItemSelected», и это только для 2-го «BeerListFragment», даже когда показывался 1-й фрагмент. –

ответ

1

Итак, ваша проблема заключается в том, что вы звоните bar.setListNavigationCallbacks(show, this) внутри своих BeerListFragment. Когда ваш первый BeerListFragment создан в вашем ViewPager, он устанавливает себя как обратный вызов для выбора навигации. Затем, когда ваш второй BeerListFragment создан (ViewPager s возобновляет страницы слева и справа от просматриваемой в настоящее время страницы), он устанавливает себя как обратный вызов для выбора навигации, а перезаписывает 1-й BeerListFragment, который теперь больше не будет ответный вызов onNavigationItemSelected.

Это все результаты с поведением вы видите, последний BeerListFragment называть bar.setListNavigationCallbacks будет только один, чтобы получить onNavigationItemSelected обратного вызова. Вот почему сортируется только второй BeerListFragment.

Чтобы решить эту проблему, я бы порекомендовал вам сделать несколько вещей:

  1. Manage установки обратного вызова для навигации выборов в BeerMenuFragment, и передавать результаты детям Fragment ы, которые находятся в «живой» (в onResume). Для этого вам нужно будет использовать один из answers here.
  2. Сохраните последнюю применяемую опцию сортировки и проверьте в onResume каждого BeerListFragment, чтобы узнать, соответствует ли его сортировка, и если нет, примените сортировку.

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

+1

Да! Спасибо @Steven за помощь. Я использовал метод getRegisteredFragment, упомянутый в ссылке «ответы здесь», а затем настроил интерфейс OnSortOrderChangedListener, чтобы рассказать дочерние фрагменты, когда порядок сортировки изменился! –