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中的動態動態增刪邏輯,因為涉及到動態 刷新,所以在每次動態添加之前要先將其清空一下

layout.removeAllViews();//涉及到實時刷新,所以要將之前的布局清空掉。
        homePager.removeAllViewsInLayout();//removeAllViews();//賦值之前先將Adapter中的
        homepageFragments.clear();
        if(hotIssuesList != null && hotIssuesList.size()>0) {
            describeArr = new String[hotIssuesList.size()];
            solutionArr = new String[hotIssuesList.size()];
            for(int i = 0; i < hotIssuesList.size(); i++) {//hotIssuesList.size()
                describeArr[i] = hotIssuesList.get(i).getHotDescirbe();//提取對應pager數據源。
                solutionArr[i] = hotIssuesList.get(i).getHotSolution();
                img = new ImageView(this);//准備5個小圖標。
                img.setScaleType(ScaleType.FIT_XY);
                img.setImageResource(img_ID);
                imgsList.add(img);
                img.setPadding(6, 3, 6, 3);
                layout.addView(img, params);
                
//                colourFragment = new ColourFragment(hotIssuesList.get(i));
//                homepageFragments.add(colourFragment);
//                homePage2Fragment = new HomePage2Fragment(this, i, hotIssuesList.get(i));
                homePage2Fragment = HomePage2Fragment.getInstance(hotIssuesList.get(i));
//                homePage2Fragment = new HomePage2Fragment(this, i, new String[]{describeArr[i], solutionArr[i]});
                homepageFragments.add(homePage2Fragment);
//                viewpagerItemView = new ViewPagerItemView(this, i, new String[]{describeArr[i], solutionArr[i]});
//                homepageViews.add(viewpagerItemView);
            }
            
            //custom-viewpager
//            MyHomePagerAdapter myAdapter = new MyHomePagerAdapter(this, homepageViews, describeArr, solutionArr);
            HomePageAdapter adapter = new HomePageAdapter(this, getSupportFragmentManager(), homepageFragments);
            homePager.setAdapter(adapter);
            
            //wrapper-viewpager-
//            HomePageAdapter adapter = new HomePageAdapter(this, getSupportFragmentManager(), hotIssuesList);
//            PagerAdapter wrappedAdapter = new InfinitePagerAdapter(adapter);
//            homePager.setAdapter(wrappedAdapter);
            
            homePager.setCurrentItem(0);
            imgsList.get(0).setImageResource(img_ID_ov);
            homePager.setOnPageChangeListener(new PageListener());
        } 

代碼中可以看出我已經做過了各種嘗試,哎,解決一個問題真的比首次開發難度大多了。
2.最關鍵的地方出來了:--pagerAdapter, 一定要替換成下文的樣式才能正常刪除fragment

public class HomePageAdapter extends FragmentStatePagerAdapter {//FragmentPagerAdapter

//    private FragmentManager fm;
    private ArrayList<Fragment> fragments = null;
    private List<HotIssues> hotIssuesList;
    private Context context;

    public HomePageAdapter(Context context, FragmentManager fm, ArrayList<Fragment> fragments) {
        super(fm);
        this.context = context;
        this.fragments = fragments;
        notifyDataSetChanged();
    }
    
    public HomePageAdapter(Context context, FragmentManager fm, List<HotIssues> hotIssuesList) {
        super(fm);
        this.context = context;
        this.hotIssuesList = hotIssuesList;
        notifyDataSetChanged();
//        this.fragments = fragments;
    }

    @Override
    public Fragment getItem(int arg0) {
//        Fragment fragment = new ColourFragment();
//        Bundle args = new Bundle();
//        args.putInt("title", arg0);
//        args.putSerializable("content",hotIssuesList.get(arg0));
//        fragment.setArguments(args);
//        return fragment;
        return fragments.get(arg0);
    }

    @Override
    public int getItemPosition(Object object) {
        // TODO Auto-generated method stub
        return PagerAdapter.POSITION_NONE;
    }
    
    @Override
    public int getCount() {
        return fragments.size();//hotIssuesList.size();
    }
    
}

注:引用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中的視圖就一直在內存中,在這個過程中無論你怎么刷新,清除都是無用的,直至程序退出; 后者 可以滿足我們的需求。

  @Override
    public int getItemPosition(Object object) {
        // TODO Auto-generated method stub
        return PagerAdapter.POSITION_NONE;
    }

最后重申一句:一定要訓練閱讀外文文獻、網頁的能力!
http://stackoverflow.com/questions/10396321/remove-fragment-page-from-viewpager-in-android

2.我們可以重寫Adapter的方法--getItemPosition(),讓其返回PagerAdapter.POSITION_NONE即可;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM