【问题标题】:Viewpager and Sherlock Fragments. How to do somethng inside fragment from FragmentActivity?Viewpager 和 Sherlock 片段。如何在 FragmentActivity 的片段内做一些事情?
【发布时间】:2013-01-21 14:50:01
【问题描述】:

我有一个父 SherlockFragmentActivity 类,其中包含 ViewPager 和 4 个 Fragment。
其中之一从 SherlockListFragment 扩展,我想通过单击它的选项卡将其滚动到顶部。

MainActivity 类:

public class MainActivity extends SherlockFragmentActivity  {

ViewPager viewPager;
TabAdapter tabAdapter;

@Override
public void onCreate(Bundle savedInstanceState) {
    setTheme(Constants.THEME);

    viewPager = new ViewPager(this);
    viewPager.setId(R.id.pager);
    viewPager.setBackgroundResource(R.color.background_color);

    tabAdapter = new TabAdapter(this,viewPager);

    super.onCreate(savedInstanceState);
    setContentView(viewPager);

    // Action bar setup
    setupTabs(savedInstanceState);
}

private void setupTabs(Bundle savedInstanceState) {
    final ActionBar actionBar = getSupportActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    for (int i = 1; i <= 4; i++) {
        ActionBar.Tab tab = getSupportActionBar().newTab();
        switch (i) {
            case 1:
                tab.setText(R.string.feed).setTabListener(tabAdapter);
                tabAdapter.addTab(EventListFragment.class);
                break;
            case 2:
                tab.setText(R.string.downloads).setTabListener(tabAdapter);
                tabAdapter.addTab(LocalEventListFragment.class);
                break;
            case 3:
                tab.setText(R.string.tags).setTabListener(tabAdapter);
                tabAdapter.addTab(TagsFragment.class);
                break;
            case 4:
                tab.setText(R.string.settings).setTabListener(tabAdapter);
                tabAdapter.addTab(SettingsFragment.class);
                break;
        }
        getSupportActionBar().addTab(tab);
    }
}

TabAdapter 类:

public static class TabAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener, ActionBar.TabListener {

    private final Context mContext;
    private final ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
    private final ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
    private final ActionBar mActionBar;
    private final ViewPager mViewPager;

    public TabAdapter(SherlockFragmentActivity activity, ViewPager pager){
        super(activity.getSupportFragmentManager());
        mContext = activity;
        mActionBar = activity.getSupportActionBar();
        mViewPager = pager;
        mViewPager.setAdapter(this);
        mViewPager.setOnPageChangeListener(this);
    }

    public void addTab(Class<?> clss){
        classes.add(clss);
        mFragments.add(Fragment.instantiate(mContext, clss.getName(),
                null));
    }

    @Override
    public Fragment getItem(int i) {
        return mFragments.get(i);
    }

    public int getId(int index){
        return mFragments.get(index).getId();
    }

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

    @Override
    public void onPageSelected(int position) {
        // fixed double call onTabReselected
        if (mActionBar.getSelectedNavigationIndex() != position)
            mActionBar.setSelectedNavigationItem(position);
    }

    @Override
    public void onPageScrollStateChanged(int i) {
    }

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

    @Override
    public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
        mViewPager.setCurrentItem(tab.getPosition());
    }

    @Override
    public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
        final int position = tab.getPosition();
        final Fragment fragment =  mFragments.get(position);
        if (fragment != null) {
            switch (position) {
                case 0:
                    // call tab's ListFragment scroll to top item
                    ((EventListFragment) fragment).scrollToTop();
                    break;
                case 1:
                    // do something
                    break;
        }
    }
}

onTabReselected 调用,然后用户按下当前选项卡,所以我尝试进行 EventListFragment 滚动:

EventListFragment 类:

public class EventListFragment extends SherlockListFragment {

    @Override
    public void onCreate(Bundle state) {
        super.onCreate(state);
        mAdapter = new EventListAdapter(getSherlockActivity());
        setListAdapter(mAdapter);
    }

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

   @Override
   public final View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View eventListLayout = inflater.inflate(R.layout.eventlist_fragment,null);
        ListView lv = (ListView) eventListLayout.findViewById(android.R.id.list);
        ViewGroup parent = (ViewGroup) lv.getParent();
        //Remove ListView and add PullToRefreshListView in its place
        int lvIndex = parent.indexOfChild(lv);
        parent.removeViewAt(lvIndex);
        mPullToRefreshListView = onCreatePullToRefreshListView(inflater, savedInstanceState);
        parent.addView(mPullToRefreshListView, lvIndex, lv.getLayoutParams());
        return eventListLayout;
   }

   public void scrollToTop() {
      if (getSherlockActivity() != null) {  // null after screen rotation
        final ListView listView =  getListView();
        listView.post(new Runnable(){
        public void run() {
            listView.smoothScrollToPosition(0);
        }});
      }
   }

它适用于应用程序启动,但屏幕旋转后 scrollToTop - getSherlockActivity() 返回 null
如果去掉这个条件检查,有一个例外:

java.lang.IllegalStateException:尚未创建内容视图 在 android.support.v4.app.ListFragment.ensureList(ListFragment.java:328) 在 android.support.v4.app.ListFragment.getListView(ListFragment.java:222) 在 com.project.fragment.EventListFragment.scrollToTop(EventListFragment.java:337) 在 com.project.MainActivity$TabAdapter.onTabReselected(MainActivity.java:411) 在 com.actionbarsherlock.internal.app.ActionBarWrapper$TabWrapper.onTabReselected(ActionBarWrapper.java:327)

我还没有完全了解 ViewPager 及其 FragmentPagerAdapter 的工作原理。所以找不到问题,就是这样。

【问题讨论】:

标签: android android-fragments actionbarsherlock android-viewpager fragmentpageradapter


【解决方案1】:

使用这个 FragmentPageAdapter:

public class TestFragmentAdapter extends FragmentPagerAdapter implements IconPagerAdapter {
    protected static final String[] CONTENT = new String[] { "CATEGORIAS", "PRINCIPAL", "AS MELHORES", };
    protected static final int[] ICONS = new int[] {
            R.drawable.perm_group_calendar,
            R.drawable.perm_group_camera,
            R.drawable.perm_group_device_alarms,
    };

    private int mCount = CONTENT.length;

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

    @Override
    public Fragment getItem(int position) {Fragment f = null;
    switch(position){
    case 0:
    {
    f = new ArrayListFragment();//YourFragment
    // set arguments here, if required
    Bundle args = new Bundle();
    f.setArguments(args);
    break;
    }
    case 1:
    {
        f = new HomeFragment();//YourFragment
        // set arguments here, if required
        Bundle args = new Bundle();
        f.setArguments(args);
        break;
    }
    case 2:
    {   
        f = new EndlessCustomView();//YourFragment
        // set arguments here, if required
        Bundle args = new Bundle();
        f.setArguments(args);
        break;
    }   
    default:
      throw new IllegalArgumentException("not this many fragments: " + position);
    }


    return f;
    }

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

    @Override
    public CharSequence getPageTitle(int position) {
      return TestFragmentAdapter.CONTENT[position % CONTENT.length];
    }



    @Override
    public int getIconResId(int index) {
      return ICONS[index % ICONS.length];
    }

    public void setCount(int count) {
        if (count > 0 && count <= 10) {
            mCount = count;
            notifyDataSetChanged();
        }
    }
}

此活动:

public class BaseSampleActivity extends SlidingFragmentActivity {
    private static final Random RANDOM = new Random();

    TestFragmentAdapter mAdapter;
    ViewPager mPager;
    PageIndicator mIndicator;
    protected ListFragment mFrag;



    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        setContentView(R.layout.themed_titles);


                getSupportActionBar().setDisplayHomeAsUpEnabled(true);

                mAdapter = new TestFragmentAdapter(getSupportFragmentManager());

                mPager = (ViewPager)findViewById(R.id.pager);
                mPager.setAdapter(mAdapter);
                mPager.setCurrentItem(1);
                mIndicator = (TitlePageIndicator)findViewById(R.id.indicator);
                mIndicator.setViewPager(mPager);


    }

【讨论】:

    【解决方案2】:

    根据this post应用解决方案:

    MainActivity 类:

    //...
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        FragmentManager manager = getSupportFragmentManager();
        for (int i = 0; i < tabAdapter.getClasses().size(); i++) {
            String className = tabAdapter.getClasses().get(i).getName();
            if (manager.findFragmentByTag(className) != null) {
                manager.putFragment(outState, className, manager.findFragmentByTag(className));
            }
        }
    }
    //...
    

    TabAdapter 类:

    //...
    public void addTab(Class<?> clss, FragmentManager manager, Bundle savedInstanceState) {
            classes.add(clss);
            String className = clss.getName();
            tags.add(className);
            Fragment fragment;
    
            if (savedInstanceState != null) {
                fragment = manager.getFragment(savedInstanceState, className);
                if (fragment == null) {
                    fragment = createFragment(className);
                    manager.beginTransaction().add(fragment, className);
                }
            } else {
                fragment = createFragment(className);
                manager.beginTransaction().add(fragment, className);
            }
            mFragments.add(fragment);
        }
    //...
    

    createFragment 是一个简单的方法,通过传递的类名创建所需的片段。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-11
      • 1970-01-01
      相关资源
      最近更新 更多