4

内部に 4 つの Fragments を持つViewPagerを含む親SherlockFragmentActivityクラスがあります。 そのうちの 1 つは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.ジャワ:327)

ViewPager とその FragmentPagerAdapter が機能する方法を完全に理解しているわけではありません。そのため、発生する問題を見つけることができません。

4

2 に答える 2

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);


    }
于 2013-01-22T00:03:29.000 に答える
0

Applied solution according to this post:

MainActivity class:

//...
@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 class:

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

where createFragment is a simple method, that creates needed fragment by passed class name.

于 2013-02-03T12:44:57.187 に答える