【问题标题】:Android, How to mix ActionBar.Tab + View Pager + ListFragmentAndroid,如何混合 ActionBar.Tab + View Pager + ListFragment
【发布时间】:2013-01-05 13:22:13
【问题描述】:

我一直在尝试测试如何将所有这些东西混合在一起,但我遇到了问题! 我只想要一个使用 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,因此它会调用值为 2 NOT 1 的 TabFragment 类的 createView ,所以标签没有成功刷新。

任何帮助将不胜感激!

创建标签的代码,

// 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();
}

}

我没有做错什么,我猜是碎片搞砸了,因为当我按下第二个选项卡时,第一个选项卡中的数据会更新,依此类推......

谢谢!

【问题讨论】:

  • 好的,我认为所选选项卡中的位置与视图分页器中的 getView 索引之间的索引变化是因为视图分页器正在准备显示下一页。但是我无法通知列表片段的适配器内容已更改。一个简单的文本示例正在起作用,但在涉及列表时不起作用。

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


【解决方案1】:

我没有使用 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
         }
      }

}

}`

【讨论】:

  • 我的代码与您上面的代码几乎相似。您是否有任何代码可以分享您如何将其更改为使用 TabAdapters 类。我试过了,但遇到了一些问题。
  • 抱歉耽搁了,我很久没有看这段代码了,所以我不记得我改变了什么:(我将添加我的 TabsAdapter 代码作为答案。
  • 感谢您的回复。我其实已经想通了。我采用了 TabAdapter 的方式,一切看起来都好多了。重新加载选项卡时仍会遇到一些问题,但会解决的。
【解决方案2】:

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

viewPager.setCurrentItem(i);

应该替换为:

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

导致平稳过渡。

【讨论】:

    【解决方案3】:

    您可以尝试在您的FragmentPagerAdapter 中包含以下代码,看看是否能解决问题。

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

    您也可以尝试使用FragmentStatePagerAdapter

    【讨论】:

    • 谢谢,如果我使用 getItemPosition 那么我无法访问每个片段来通知适配器的内容发生了变化,就像这样,TabFragment fragment = (TabFragment) getSupportFragmentManager( ).findFragmentByTag("android:switcher:"+R.id.pager+":"+tab.getPosition());无论如何,我使用 ViewPager 的 Android 文档中显示的 TabsAdapter 类更改了所有代码,然后它突然工作了!
    猜你喜欢
    • 1970-01-01
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    • 2015-06-22
    相关资源
    最近更新 更多