Android,如何混合ActionBar.Tab + View Pager + ListFragment

时间:2013-01-05 13:22:13

标签: android android-actionbar android-viewpager android-listfragment

我一直试图测试如何将所有这些东西混合在一起,我遇到了问题! 我只想要一个使用ActionBar.Tab的三个标签的应用程序。例如,此选项卡可以是电影类型动作,冒险和动画,用户可以在选项卡中滑动,因此它将使用ViewPager,每个选项卡将显示该类型的电影列表。不需要有三个不同的片段类,因为所有选项卡的格式都是简单列表。 我遇到了问题,因为当我选择第二个标签时,onPageSelected的位置是1,

mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mCollectionPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
     public void onPageSelected(int position) {
        mActionBar.setSelectedNavigationItem(position);
     }
});

这导致调用CollectionPagerAdapter类中的方法public Fragment getItem(int i),但是i的值是2 NOT 1,因此它调用TabFragment类的createView,值为2 NOT 1 ,因此标签未成功刷新。

任何帮助都将非常感谢!!

创建标签的代码,

// For each of the sections in the app, add a tab to the action bar.
for (int i = 0; i < mCollectionPagerAdapter.getCount(); i++) {
        mActionBar.addTab(mActionBar.newTab()
            .setText(mGenres.get(i).getName()) 
            .setTabListener(this));

        //Let's request the movies for the first three genres
        new GetMoviesByGenre().execute(mGenres.get(i).getId());         
}

选择标签时,

@Override
public void onTabSelected(ActionBar.Tab tab, android.app.FragmentTransaction arg1) {

//Let's update the dataset for the selected genre
TabFragment fragment = 
      (TabFragment) getSupportFragmentManager().findFragmentByTag(
                   "android:switcher:"+R.id.pager+":"+tab.getPosition());
     if(fragment != null)  // could be null if not instantiated yet
     {
        if(fragment.getView() != null) 
        {
           fragment.updateDisplay(tab.getPosition()); // do what updates are required
        }
     }

  mViewPager.setCurrentItem(tab.getPosition());
}

CollectionPageAdapter类

public class CollectionPagerAdapter extends FragmentPagerAdapter {

final int NUM_ITEMS = 3; // number of tabs

List<Fragment> fragments = new ArrayList<Fragment>();

public Fragment getItem(int pos) {
  return fragments.get(pos);
}

public void addFragment(Fragment f) {
  fragments.add(f);
}

public CollectionPagerAdapter(FragmentManager fm) {
    super(fm);

    //Let's add  the fragments
    for (int i=0;i<NUM_ITEMS;i++)
    {
        Fragment fragment = new TabFragment();
        Bundle args = new Bundle();
        args.putInt(TabFragment.ARG_OBJECT, 0);
        fragment.setArguments(args);
        addFragment (fragment);
    }
}

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

}

TabFragment类

public class TabFragment extends ListFragment {

public static final String ARG_OBJECT = "object";

private MoviesAdapter m_Adapter;
private ArrayList <Movie> mMovies = new ArrayList<Movie>();

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

  // you only need to instantiate these the first time your fragment is
  // created; then, the method above will do the rest
  if (m_Adapter == null) {
      m_Adapter = new MoviesAdapter(getActivity(), mMovies);
  }
  setListAdapter(m_Adapter);
}

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

    int position = getArguments().getInt(ARG_OBJECT); // to check is the right fragment
    View rootView = inflater.inflate(R.layout.tabs, container, false);
    return rootView;
}

public void updateDisplay (int type)
{
     GlobalVars gv = (GlobalVars)getActivity().getApplicationContext();

    switch (type)
    {
        case 0:
            mMovies = gv.getActionMovies();
            break;
        case 1:
            mMovies = gv.getAdventureMovies();
            break;
        case 2:
            mMovies = gv.getAnimationMovies();
            break;
    }

    m_Adapter.notifyDataSetChanged();
}

}

我不知道我做错了什么,我猜这些碎片搞砸了,因为当我按下第二个标签时,第一个标签中的数据会更新,等等......

谢谢!

3 个答案:

答案 0 :(得分:3)

我没有使用CollectionPageAdapter,而是改为使用ViewPager的Android文档中显示的TabsAdapter类,它有效!

public class TabsAdapter extends FragmentPagerAdapter
    implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

private final List<Fragment> fragments = new ArrayList<Fragment>();

static final class TabInfo {
    private final Class<?> clss;
    private final Bundle args;

    TabInfo(Class<?> _class, Bundle _args) {
        clss = _class;
        args = _args;
    }
}

public TabsAdapter(FragmentActivity activity, ViewPager pager) {
    super(activity.getSupportFragmentManager());
    mContext = activity;
    mActionBar = activity.getActionBar();
    mViewPager = pager;
    mViewPager.setAdapter(this);
    mViewPager.setOnPageChangeListener(this);
}

public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
    TabInfo info = new TabInfo(clss, args);
    tab.setTag(info);
    tab.setTabListener(this);
    mTabs.add(info);
    mActionBar.addTab(tab);
    notifyDataSetChanged();
}

@Override
public int getCount() {
    return mTabs.size();
}

@Override
public int getItemPosition(Object object) {
    return POSITION_NONE;
}

@Override
public Fragment getItem(int position) {

    TabInfo info = mTabs.get(position);
    Fragment fr = Fragment.instantiate(mContext, info.clss.getName(), info.args);
    //addFragment (fr, position);
    return  fr;

}

public void addFragment(Fragment f, int location) {

    if (fragments.size() == 0)
        fragments.add(f);
    else
        fragments.add(location, f);
  }

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}

@Override
public void onPageSelected(int position) {
    mActionBar.setSelectedNavigationItem(position);
}

@Override
public void onPageScrollStateChanged(int state) {
}

@Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
    Object tag = tab.getTag();
    for (int i=0; i<mTabs.size(); i++) {
        if (mTabs.get(i) == tag) {
            updateDatasetMovies (i);
            mViewPager.setCurrentItem(i);
        }
    }
}



@Override
public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
    // TODO Auto-generated method stub

}

@Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
    // TODO Auto-generated method stub

}


public void updateDatasetMovies (int pos)
{
    //Let's update the dataset for the selected genre
    TabFragment fragment = 
          (TabFragment) ((FragmentActivity)mContext).getSupportFragmentManager().findFragmentByTag(
                       "android:switcher:"+R.id.pager+":"+pos);

    //TabFragment fragment = (TabFragment) getItem(pos);
    if(fragment != null)  // could be null if not instantiated yet
      {
         if(fragment.getView() != null) 
         {
            // no need to call if fragment's onDestroyView() 
            //has since been called.
            fragment.updateDisplay(pos); // do what updates are required
         }
      }

}

}`

答案 1 :(得分:1)

我同意nirvik的观点,但是应该做出一些改进。这个implementation有一个缺陷 - 当刷到下一个片段时,调用onPageSelected方法,然后通过调用mActionBar.setSelectedNavigationItem(position);来调用onTabSelected方法。这会导致动画中的闪烁。 这样:

viewPager.setCurrentItem(i);

应该替换为:

if(i != viewPager.getCurrentItem()) {
     viewPager.setCurrentItem(i);
}

导致平稳过渡。

答案 2 :(得分:0)

您可以尝试在FragmentPagerAdapter中添加以下代码,看看是否可以解决问题。

public int getItemPosition(Object object) {
    return POSITION_NONE;
}

您也可以尝试使用FragmentStatePagerAdapter