1. 程式人生 > >轉載 viewpager中徹底性動態新增、刪除Fragment

轉載 viewpager中徹底性動態新增、刪除Fragment

viewpager巢狀fragment是一個比較帥氣的使用,但是問題多多,畢竟沒怎麼用過。
之前viewpager的使用頂多是在應用開始的介紹頁,viewpager內嵌幾張介紹圖片,其實這個使用是比較常規的;假如巢狀佈局搞的複雜點,如自定義view/fragment,那麼就要考慮下佈局資源的分發情況了,而不是簡單的對Adapter或者pager進行clear、removeAllViews。
拿自己的專案使用情況來說,開始以為viewpager的頁數是定的,但最後才知道是動態改變的,不僅可以增加,還要動態的刪除!!!這個實時動作真的很折騰,增加是沒有問題的,但是減少卻不如我們所願,總是有殘留的佈局在佔著位子,揮之不去,無論你怎麼clear、remove都於是無補,因為我不懂它的實現機制,so,真心被動。折騰了好幾天,終於在stackoverflow上找到了問題的根源,結合自己專案實際情況解決了自己的問題
,詳情見下文。
所以說:軟體開發有兩種東西是不可或缺的–1.勇於嘗試;2.良好的英文閱讀能力!!
專案使用情況:viewpager+FragmentPagerAdapter+fragment,互動邏輯放置在fragment中;
1.主activity中的動態動態增刪邏輯,因為涉及到動態 重新整理,所以在每次動態新增之前要先將其清空一下
  1. layout.removeAllViews();//涉及到實時重新整理,所以要將之前的佈局清空掉。
  2. homePager.removeAllViewsInLayout();//removeAllViews();//賦值之前先將Adapter中的
  3. homepageFragments.clear();
  4. if(hotIssuesList != null && hotIssuesList.size()>0) {
  5. describeArr = new String[hotIssuesList.size()];
  6. solutionArr = new String[hotIssuesList.size()];
  7. for(int i = 0; i < hotIssuesList.size(); i++) {//hotIssuesList.size()
  8. describeArr[i] = hotIssuesList.get(i).getHotDescirbe();//提取對應pager資料來源。
  9. solutionArr[i] = hotIssuesList.get(i).getHotSolution();
  10. img = new ImageView(this);//準備5個小圖示。
  11. img.setScaleType(ScaleType.FIT_XY);
  12. img.setImageResource(img_ID);
  13. imgsList.add(img);
  14. img.setPadding(6, 3, 6, 3);
  15. layout.addView(img, params);
  16. // colourFragment = new ColourFragment(hotIssuesList.get(i));
  17. // homepageFragments.add(colourFragment);
  18. // homePage2Fragment = new HomePage2Fragment(this, i, hotIssuesList.get(i));
  19. homePage2Fragment = HomePage2Fragment.getInstance(hotIssuesList.get(i));
  20. // homePage2Fragment = new HomePage2Fragment(this, i, new String[]{describeArr[i], solutionArr[i]});
  21. homepageFragments.add(homePage2Fragment);
  22. // viewpagerItemView = new ViewPagerItemView(this, i, new String[]{describeArr[i], solutionArr[i]});
  23. // homepageViews.add(viewpagerItemView);
  24. }
  25. //custom-viewpager
  26. // MyHomePagerAdapter myAdapter = new MyHomePagerAdapter(this, homepageViews, describeArr, solutionArr);
  27. HomePageAdapter adapter = new HomePageAdapter(this, getSupportFragmentManager(), homepageFragments);
  28. homePager.setAdapter(adapter);
  29. //wrapper-viewpager-
  30. // HomePageAdapter adapter = new HomePageAdapter(this, getSupportFragmentManager(), hotIssuesList);
  31. // PagerAdapter wrappedAdapter = new InfinitePagerAdapter(adapter);
  32. // homePager.setAdapter(wrappedAdapter);
  33. homePager.setCurrentItem(0);
  34. imgsList.get(0).setImageResource(img_ID_ov);
  35. homePager.setOnPageChangeListener(new PageListener());
  36. }
從程式碼中可以看出我已經做過了各種嘗試,哎,解決一個問題真的比首次開發難度大多了。
2.最關鍵的地方出來了:–pagerAdapter, 一定要替換成下文的樣式才能正常刪除fragment
  1. public class HomePageAdapter extends FragmentStatePagerAdapter {//FragmentPagerAdapter
  2. // private FragmentManager fm;
  3. private ArrayList<Fragment> fragments = null;
  4. private List<HotIssues> hotIssuesList;
  5. private Context context;
  6. public HomePageAdapter(Context context, FragmentManager fm, ArrayList<Fragment> fragments) {
  7. super(fm);
  8. this.context = context;
  9. this.fragments = fragments;
  10. notifyDataSetChanged();
  11. }
  12. public HomePageAdapter(Context context, FragmentManager fm, List<HotIssues> hotIssuesList) {
  13. super(fm);
  14. this.context = context;
  15. this.hotIssuesList = hotIssuesList;
  16. notifyDataSetChanged();
  17. // this.fragments = fragments;
  18. }
  19. @Override
  20. public Fragment getItem(int arg0) {
  21. // Fragment fragment = new ColourFragment();
  22. // Bundle args = new Bundle();
  23. // args.putInt("title", arg0);
  24. // args.putSerializable("content",hotIssuesList.get(arg0));
  25. // fragment.setArguments(args);
  26. // return fragment;
  27. return fragments.get(arg0);
  28. }
  29. @Override
  30. public int getItemPosition(Object object) {
  31. // TODO Auto-generated method stub
  32. return PagerAdapter.POSITION_NONE;
  33. }
  34. @Override
  35. public int getCount() {
  36. return fragments.size();//hotIssuesList.size();
  37. }
  38. }
注:引用stackoverflow牛人的解決說明:


The ViewPager doesn’t remove your fragments with the code above because it loads several views (or fragments in your case) into memory. In addition to the visible view, it also loads the view to either side of the visible one. This provides the smooth scrolling
from view to view that makes the ViewPager so cool.

To achieve the effect you want, you need to do a couple of things.

  1. Change the FragmentPagerAdapter to a FragmentStatePagerAdapter. The reason for this is that the FragmentPagerAdapter will keep all the views that it loads into memory forever. Where the FragmentStatePagerAdapter disposes of views that fall outside the current and traversable views.

  2. Override the adapter method getItemPosition (shown below). When we callmAdapter.notifyDataSetChanged(); the ViewPager interrogates the adapter to determine what has changed in terms of positioning. We use this method to say that everything has changed so reprocess all your view positioning。

大致意思是說:viewpager在載入當前頁的時候已經將pager頁左右頁的內容載入進記憶體裡了,這樣才保證了viewpager左右滑動的時候的流暢性;
為了解決徹底刪除fragment,我們要做的是:
1.將FragmentPagerAdapter 替換成FragmentStatePagerAdapter,因為前者只要載入過,fragment中的檢視就一直在記憶體中,在這個過程中無論你怎麼重新整理,清除都是無用的,直至程式退出; 後者 可以滿足我們的需求。
2.我們可以重寫Adapter的方法–getItemPosition(),讓其返回PagerAdapter.POSITION_NONE即可;

  1. @Override
  2. public int getItemPosition(Object object) {
  3. // TODO Auto-generated method stub
  4. return PagerAdapter.POSITION_NONE;
  5. }
 到這一步我們就可以真正的實現隨意、徹底刪除viewpager中的fragment;[隨意新增完全OK]
最後重申一句:一定要訓練閱讀外文文獻、網頁的能力!
http://stackoverflow.com/questions/10396321/remove-fragment-page-from-viewpager-in-android
對於國內的問題解決辦法的大抄特抄現象,我只能說:呵呵, 搜一個關鍵字,前5條都是一樣的,從第一條一直抄襲到第5條、 哎、、 
今天週六,過來加班,這個問題上週bug庫裡就有了,一直沒解決,現在知道根源所在,也就有點小輕鬆了,接下來就要搞viewpager+fragment的迴圈實現了,也是個麻煩,,加油吧。