我正在尝试构建一个以纵向和横向模式显示书籍的应用程序。所以很明显有1页以纵向显示,2页以横向显示。每种模式都很好,但是当我将方向从纵向更改为横向时,viewPager 尝试从纵向模式获取 2 个页面,而不是尝试从横向模式获取 2 个双页......实际上FragmentStatePagerAdapter 保留了 2 个片段以纵向创建并在为横向模式创建 2 个双页之前使用它们. 如果我在纵向模式下再次切换,FragmentStatePagerAdapter 使用之前在横向模式下创建的 2 个片段,所以我再次看到 1 个双页而不是 1 个单页等。如果我继续切换方向,我得到一个 OutOfMemoryError,因为 FragmentStatePagerAdapter 从来没有在方向改变时刷新它的碎片。
这里有 2 个用例,便于理解:
- 我以纵向模式启动 viewPager
- 我看到了第 1 页
- 我向右滑动,我看到了第 2 页
- 我向右滑动,我看到第 3 页 ok
- 我将屏幕旋转到横向模式
- 我看到第 3 页错了
- 我向右滑动,我看到第 4 页错误
我向右滑动,我看到第 5 页和第 6 页 ok
我以纵向模式启动 viewPager
- 我看到了第 1 页
- 我向右滑动,我看到了第 2 页
- 我向右滑动,我看到第 3 页 ok
- 我向右滑动,我看到第 4 页 ok
- 我向右滑动,我看到第 5 页 ok
- 我将屏幕旋转到横向模式
- 我看到第 5 页错了
- 我向左滑动,我看到第 4 页错误
我向左滑动,我看到第 2 页和第 3 页 ok
public class PlayerFragmentActivity extends FragmentActivity { private Intent mIntent; private ViewPager mPortraitPager; private ViewPager mLandscapePager; private Boolean mIsLandscape; private String mKey; private int mNbPages; private int mNbDoublePages; private PageFactory mPageFactory; private DoublePageFactory mDoublePageFactory; private PagerAdapter mPagerAdapter; @Override protected void onStop(){ super.onStop(); mPagerAdapter = null; mDoublePageFactory = null; mPageFactory = null; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_activity_player); mIntent = getIntent(); mKey = mIntent.getStringExtra("key"); mNbPages = mIntent.getIntExtra("nbPages", 0); mNbDoublePages = DoublePageFactory.getDoublePageNumFromPageNum(mNbPages); Resources res = getResources(); mIsLandscape = (res.getConfiguration().orientation == 1) ? false : true; mPortraitPager = (ViewPager) findViewById(R.id.portraitPager); mLandscapePager = (ViewPager) findViewById(R.id.landscapePager); mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager()); if (mIsLandscape) { mDoublePageFactory = new DoublePageFactory(this, mKey, mNbPages, res.getInteger(R.integer.nb_page_columns), res.getInteger(R.integer.nb_page_columns)); mPortraitPager.setVisibility(View.GONE); mLandscapePager.setAdapter(mPagerAdapter); mPortraitPager.setAdapter(null); } else { mPageFactory = new PageFactory(this, mKey, this.mNbPages, res.getInteger(R.integer.nb_page_columns), res.getInteger(R.integer.nb_page_columns)); mLandscapePager.setVisibility(View.GONE); mPortraitPager.setAdapter(mPagerAdapter); mLandscapePager.setAdapter(null); } } public class MyPagerAdapter extends FragmentStatePagerAdapter { public MyPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { Bundle args = new Bundle(); if(mIsLandscape){ Fragment doublePageFragment = new DoublePageFragment(); args.putInt(DoublePageFragment.ARG_DOUBLEPAGE_NUM, position + 1); doublePageFragment.setArguments(args); return doublePageFragment; }else{ Fragment pageFragment = new PageFragment(); args.putInt(PageFragment.ARG_PAGE_NUM, position + 1); pageFragment.setArguments(args); return pageFragment; } } @Override public int getCount() { return (mIsLandscape) ? mNbDoublePages:mNbPages; } /* j'ai essayé cette méthode mais ça ne fonctionne pas :( */ @Override public void destroyItem(ViewGroup container, int position, Object object) { FragmentManager manager = ((Fragment) object).getFragmentManager(); FragmentTransaction trans = manager.beginTransaction(); trans.remove((Fragment) object); trans.commit(); super.destroyItem(container, position, object); } @Override public int getItemPosition(Object object){ return PagerAdapter.POSITION_NONE; } @Override public CharSequence getPageTitle(int position) { return "p." + position + 1; } } public boolean isLandscape() { return mIsLandscape; } public ImageView getSinglePage(int position) { return mPageFactory.getPage(position); } public LinearLayout getDoublePage(int position) { return mDoublePageFactory.getDoublePage(position); } } public class PageFragment extends Fragment { private PlayerFragmentActivity mPlayerFragmentActivity; public static final String ARG_PAGE_NUM = "page_number"; public static final String ARG_WOBOOK_DIRECTORY = "book_directory"; public static final String ARG_NB_PAGE_COLUMNS = "nb_page_columns"; public static final String ARG_NB_PAGE_ROWS = "nb_page_rows"; @Override public ImageView onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mPlayerFragmentActivity = ((PlayerFragmentActivity) getActivity()); return mPlayerFragmentActivity.getSinglePage(getArguments().getInt(ARG_PAGE_NUM)); } @Override public void onStop(){ super.onStop(); mPlayerFragmentActivity = null; }
}
public class DoublePageFragment extends Fragment { private PlayerFragmentActivity mPlayerFragmentActivity; public static final String ARG_DOUBLEPAGE_NUM = "double_page_number"; public static final String ARG_WOBOOK_DIRECTORY = "book_directory"; public static final String ARG_NB_PAGE_COLUMNS = "nb_page_columns"; public static final String ARG_NB_PAGE_ROWS = "nb_page_rows"; @Override public LinearLayout onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mPlayerFragmentActivity = ((PlayerFragmentActivity) getActivity()); return mPlayerFragmentActivity.getDoublePage(getArguments().getInt(ARG_DOUBLEPAGE_NUM)); } @Override public void onStop(){ super.onStop(); mPlayerFragmentActivity = null; } }
我读过框架中的 FragmentManager 负责保存状态并恢复寻呼机制作的任何活动片段。所以我猜当方向改变时,FragmentManager 说
嘿 !我已经创建了 2 个项目,所以我不需要创建新闻,让我们获取它们
但实际上它从旧的方向模式中获取了 2 个项目(页面/双页)。所以我需要找到一种方法来在发生方向变化时删除 FragmentManager 保存的片段。
此致