内部に 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 が機能する方法を完全に理解しているわけではありません。そのため、発生する問題を見つけることができません。