Android viewpager: weird bug when adding/removing

2019-04-11 03:43发布

I dont know how to explain this, so i uploaded a video in Youtube. Everything works fine when i am adding pages. Also removing page works if i start at the end of the list and move progressively to the first page, but if i remove somewhere between 0-end and after that i add page, i am getting a blank page. Fragment is created but view is not.

Is there something wrong with my code? Yes, i have seen this question, returning POSITION_NONE is not an option, because application i am working on downloads content from web and displays it in listview, so recreating fragments everytime when user removes page is not very effective.

Button click:            Result:

Add page                 [Fragment 1]
Add page                 [Fragment 1][Fragment 2]
Add page                 [Fragment 1][Fragment 2][Fragment 3]
remove page(position2)   [Fragment 1][Fragment 2]
remove page(position1)   [Fragment 1]
Add page                 [Fragment 1][Fragment 2]
remove page(position1)   [Fragment 1]
remove page(position0)    ---No pages---


Add page                 [Fragment 0]
Add page                 [Fragment 0][Fragment 1]
Add page                 [Fragment 0][Fragment 1][Fragment 2]
add page                 [Fragment 0][Fragment 1][Fragment 2][fragment 3]
remove page(position2)   [Fragment 0][Fragment 1][Fragment 3]
add page                 [Fragment 0][Fragment 1][Fragment 3][Blank page]
remove page(position0)   [Fragment 1][Fragment 3][Fragment 3][Blank page]

MainActivity.class

    public class MainActivity extends FragmentActivity {
    private static final String TAG = "MainActivity";
    private ViewPager mViewpager;
    private ArrayList<Fragment> fragmentslist;
    private SectionsPagerAdapter mPagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        fragmentslist = new ArrayList<Fragment>();
        mPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
        mViewpager = (ViewPager)findViewById(R.id.pager);
        mViewpager.setAdapter(mPagerAdapter);
        mViewpager.setOffscreenPageLimit(4);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected (MenuItem item){
        switch(item.getItemId()){
        case R.id.menu_add_page:
            Bundle bundle = new Bundle();
            bundle.putInt("Position", fragmentslist.size());
            fragment frag = new fragment();
            frag.setArguments(bundle);
            fragmentslist.add(frag);
            mPagerAdapter.notifyDataSetChanged();
            mViewpager.setCurrentItem(fragmentslist.indexOf(frag));
            Log.i(TAG, "Add fragment");
            break;
        case R.id.menu_remove_page:
            if(fragmentslist.size() > 0){
                mPagerAdapter.removeItem(mViewpager.getCurrentItem());
            }
            Log.i(TAG, "Removing page " + mViewpager.getCurrentItem());
            break;
        }
        return true;
    }


    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return fragmentslist.get(position);
        }

        @Override
        public int getCount() {
            return fragmentslist.size();
        }

        @Override
        public int getItemPosition(Object object){
            int index = fragmentslist.indexOf(object);
            if(index != -1){
                Log.i(TAG, "Position: " + index);
                return index;
            }
            else{
                Log.i(TAG, "POSITION_NONE");
                return POSITION_NONE;
            }
        }

        public void removeItem(int position){
            Fragment fragment = (Fragment)fragmentslist.get(position);
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();
            fragmentslist.remove(position);
            notifyDataSetChanged();
        }

    }


    public static class fragment extends Fragment{
        private String colors[] = {"#FF0000", "#00FF00", "#FFFF00", "#FF6600"};

        public View onCreateView(LayoutInflater inflater, ViewGroup root, Bundle savedInstanceState){
            View mView = inflater.inflate(R.layout.fragment_layout, null);
            RelativeLayout layout = (RelativeLayout)mView.findViewById(R.id.relativelayout);
            TextView text = (TextView)mView.findViewById(R.id.textView1);

            int position = this.getArguments().getInt("Position");
            text.setText("Page: " + position);
            layout.setBackgroundColor(Color.parseColor(colors[position]));
            Log.i("fragment", "Page: " + position + " view created");
            return mView;
        }
    }

}

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v4.view.ViewPager
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v4.view.ViewPager>

fragment_layout.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" 
android:id="@+id/relativelayout">

<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerVertical="true"
    android:text="Large Text"
    android:textSize="40sp" />

1条回答
闹够了就滚
2楼-- · 2019-04-11 04:15

Try doing mViewpager.setAdapter(null) before adding or removing items from the list. Afterwards, set the adapter back to mPagerAdapter. It appears that ViewPager was not designed to handle insertions or deletions except from the end of the list.

I have working sample code that might be useful to you. Take a look at ViewPager sample.

查看更多
登录 后发表回答