首页 文章

从Android中的ViewPager中删除片段页面

提问于
浏览
121

我正在尝试从ViewPager动态添加和删除片段,添加工作没有任何问题,但删除不能按预期工作 .

每次我想删除当前项目时,最后一项将被删除 .

我还尝试使用FragmentStatePagerAdapter或在适配器的getItemPosition方法中返回POSITION_NONE .

我究竟做错了什么?

这是一个基本的例子:

MainActivity.java

public class MainActivity extends FragmentActivity implements TextProvider {

    private Button mAdd;
    private Button mRemove;
    private ViewPager mPager;

    private MyPagerAdapter mAdapter;

    private ArrayList<String> mEntries = new ArrayList<String>();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mEntries.add("pos 1");
        mEntries.add("pos 2");
        mEntries.add("pos 3");
        mEntries.add("pos 4");
        mEntries.add("pos 5");

        mAdd = (Button) findViewById(R.id.add);
        mRemove = (Button) findViewById(R.id.remove);
        mPager = (ViewPager) findViewById(R.id.pager);

        mAdd.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                addNewItem();
            }
        });

        mRemove.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                removeCurrentItem();
            }
        });

        mAdapter = new MyPagerAdapter(this.getSupportFragmentManager(), this);

        mPager.setAdapter(mAdapter);

    }

    private void addNewItem() {
        mEntries.add("new item");
        mAdapter.notifyDataSetChanged();
    }

    private void removeCurrentItem() {
        int position = mPager.getCurrentItem();
        mEntries.remove(position);
        mAdapter.notifyDataSetChanged();
    }

    @Override
    public String getTextForPosition(int position) {
        return mEntries.get(position);
    }
    @Override
    public int getCount() {
        return mEntries.size();
    }


    private class MyPagerAdapter extends FragmentPagerAdapter {

        private TextProvider mProvider;

        public MyPagerAdapter(FragmentManager fm, TextProvider provider) {
            super(fm);
            this.mProvider = provider;
        }

        @Override
        public Fragment getItem(int position) {
            return MyFragment.newInstance(mProvider.getTextForPosition(position));
        }

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

    }

}

TextProvider.java

public interface TextProvider {
    public String getTextForPosition(int position);
    public int getCount();
}

MyFragment.java

public class MyFragment extends Fragment {

    private String mText;

    public static MyFragment newInstance(String text) {
        MyFragment f = new MyFragment(text);
        return f;
    }

    public MyFragment() {
    }

    public MyFragment(String text) {
        this.mText = text;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View root = inflater.inflate(R.layout.fragment, container, false);

        ((TextView) root.findViewById(R.id.position)).setText(mText);

        return root;
    }

}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/add"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="add new item" />

    <Button
        android:id="@+id/remove"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="remove current item" />

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

</LinearLayout>

fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/position"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:textSize="35sp" />

</LinearLayout>

14 回答

  • 85

    我在 FragmentStatePagerAdapter 遇到了一些问题 . 删除项目后:

    • 还有另一个用于某个位置的项目(一个不属于该位置但位于该位置旁边的位置的项目)

    • 或某些片段未加载(该页面上只显示空白背景)

    经过大量实验,我想出了以下解决方案 .

    public class SomeAdapter extends FragmentStatePagerAdapter {
    
        private List<Item> items = new ArrayList<Item>();
    
        private boolean removing;
    
        @Override
        public Fragment getItem(int position) {
            ItemFragment fragment = new ItemFragment();
            Bundle args = new Bundle();
            // use items.get(position) to configure fragment
            fragment.setArguments(args);
            return fragment;
        }
    
        @Override
        public int getCount() {
            return items.size();
        }
    
        @Override
        public int getItemPosition(Object object) {
            if (removing) {
                return PagerAdapter.POSITION_NONE;
            }
    
            Item item = getItemOfFragment(object);
    
            int index = items.indexOf(item);
            if (index == -1) {
                return POSITION_NONE;
            } else {
                return index;
            }
        }
    
       public void addItem(Item item) {
            items.add(item);
            notifyDataSetChanged();
        }
    
        public void removeItem(int position) {
            items.remove(position);
    
            removing = true;
            notifyDataSetChanged();
            removing = false;
        }
    }
    

    此解决方案仅在删除项目时使用hack . 否则(例如,在添加项目时),它保留了原始代码的清洁度和性能 .

    当然,从适配器的外部,你只调用addItem / removeItem,不需要调用notifyDataSetChanged() .

  • 0

    我只想将源代码从 android.support.v4.app.FragmentPagerAdpater 复制到名为 CustumFragmentPagerAdapter 的自定义类中 . 这使我有机会修改 instantiateItem(...) ,以便每次调用它时,它会在添加从 getItem() 方法接收的新片段之前删除/销毁当前附加的片段 .

    只需按以下方式修改 instantiateItem(...)

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        final long itemId = getItemId(position);
    
        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
    
        // remove / destroy current fragment
        if (fragment != null) {
            mCurTransaction.remove(fragment);
        }
    
        // get new fragment and add it
        fragment = getItem(position);
        mCurTransaction.add(container.getId(), fragment,    makeFragmentName(container.getId(), itemId));
    
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
        }
    
        return fragment;
    }
    
  • 0

    你可以将两者结合起来更好:

    private class MyPagerAdapter extends FragmentStatePagerAdapter {
    
        //... your existing code
    
        @Override
        public int getItemPosition(Object object){
    
          if(Any_Reason_You_WantTo_Update_Positions) //this includes deleting or adding pages
     return PagerAdapter.POSITION_NONE;
        }
    else
    return PagerAdapter.POSITION_UNCHANGED; //this ensures high performance in other operations such as editing list items.
    
    }
    
  • 11

    Louth的解决方案不足以让我的工作正常,因为现有的碎片没有被破坏 . 由this answer激发,我发现解决方案是覆盖 FragmentPagerAdaptergetItemId(int position) 方法,以便在片段的预期位置发生变化时提供新的唯一ID .

    源代码:

    private class MyPagerAdapter extends FragmentPagerAdapter {
    
        private TextProvider mProvider;
        private long baseId = 0;
    
        public MyPagerAdapter(FragmentManager fm, TextProvider provider) {
            super(fm);
            this.mProvider = provider;
        }
    
        @Override
        public Fragment getItem(int position) {
            return MyFragment.newInstance(mProvider.getTextForPosition(position));
        }
    
        @Override
        public int getCount() {
            return mProvider.getCount();
        }
    
    
        //this is called when notifyDataSetChanged() is called
        @Override
        public int getItemPosition(Object object) {
            // refresh all fragments when data set changed
            return PagerAdapter.POSITION_NONE;
        }
    
    
        @Override
        public long getItemId(int position) {
            // give an ID different from position when position has been changed
            return baseId + position;
        }
    
        /**
         * Notify that the position of a fragment has been changed.
         * Create a new ID for each position to force recreation of the fragment
         * @param n number of items which have been changed
         */
        public void notifyChangeInPosition(int n) {
            // shift the ID returned by getItemId outside the range of all previous fragments
            baseId += getCount() + n;
        }
    }
    

    现在,例如,如果删除单个选项卡或对订单进行一些更改,则应在调用 notifyDataSetChanged() 之前调用 notifyChangeInPosition(1) ,这将确保将重新创建所有片段 .

    为什么这个解决方案有效

    Overriding getItemPosition():

    调用 notifyDataSetChanged() 时,适配器调用它所连接的 ViewPagernotifyChanged() 方法 . 然后 ViewPager 检查适配器的 getItemPosition() 为每个项返回的值,删除那些返回 POSITION_NONE 的项(参见source code),然后重新填充 .

    Overriding getItemId():

    ViewPager 重新填充时,这是防止适配器重新加载旧片段所必需的 . 您可以通过在 FragmentPagerAdapter 中查看the source code for instantiateItem()来轻松理解其原因 .

    final long itemId = getItemId(position);
    
        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId));
        }
    

    如您所见,只有在片段管理器找不到具有相同Id的现有片段时,才会调用 getItem() 方法 . 对我而言,即使在调用 notifyDataSetChanged() 之后,旧片段仍然附着似乎是一个错误,但 ViewPager 的文档确实明确指出:

    注意此课程目前正在进行早期设计和开发 . API可能会在以后的兼容库更新中发生变化,需要在针对较新版本编译时更改应用程序的源代码 .

    因此,希望未来版本的支持库中没有必要使用此处提供的解决方法 .

  • 2

    劳斯的回答很好 . 但我不认为总是返回POSITION_NONE是个好主意 . 因为POSITION_NONE意味着应该销毁片段并创建一个新片段 . 您可以在ViewPager的源代码中检查dataSetChanged函数 .

    if (newPos == PagerAdapter.POSITION_NONE) {
                mItems.remove(i);
                i--;
                ... not related code
                mAdapter.destroyItem(this, ii.position, ii.object);
    

    所以我认为你最好使用weakReference的arraylist来保存你创建的所有片段 . 当您添加或删除某些页面时,您可以从自己的arraylist中获得正确的位置 .

    public int getItemPosition(Object object) {
        for (int i = 0; i < mFragmentsReferences.size(); i ++) {
            WeakReference<Fragment> reference = mFragmentsReferences.get(i);
            if (reference != null && reference.get() != null) {
                Fragment fragment = reference.get();
                if (fragment == object) {
                    return i;
                }
            }
        }
        return POSITION_NONE;
    }
    

    根据注释,当主机视图尝试确定项目的位置是否已更改时,将调用getItemPosition . 返回值意味着它的新位置 .

    但这不是必须的 . 我们仍然迈出重要的一步 . 在FragmentStatePagerAdapter的源代码中,有一个名为“mFragments”的数组缓存未被销毁的片段 . 并在instantiateItem函数中 .

    if (mFragments.size() > position) {
            Fragment f = mFragments.get(position);
            if (f != null) {
                return f;
            }
        }
    

    它在发现缓存片段不为null时直接返回缓存片段 . 所以有一个问题 . 例如,让我们删除位置2处的一个页面 . 首先,我们从我们自己的参考arraylist中删除该片段 . 所以在getItemPosition中它将返回该片段的POSITION_NONE,然后该片段将被销毁并从“mFragments”中删除 .

    mFragments.set(position, null);
    

    现在位置3的片段将位于位置2.并且将调用具有参数位置3的instantiatedItem . 此时,“mFramgents”中的第三项不为null,因此它将直接返回 . 但实际上它返回的是位置2处的片段 . 所以当我们转到第3页时,我们会找到一个空页面那里 .

    要解决这个问题 . 我的建议是你可以将FragmentStatePagerAdapter的源代码复制到你自己的项目中,当你添加或删除操作时,你应该添加和删除“mFragments”arraylist中的元素 .

    如果您只使用PagerAdapter而不是FragmentStatePagerAdapter,事情就会变得更简单 . 祝好运 .

  • 0

    我的工作解决方案从视图寻呼机中删除片段页面

    public class MyFragmentAdapter extends FragmentStatePagerAdapter {
    
        private ArrayList<ItemFragment> pages;
    
        public MyFragmentAdapter(FragmentManager fragmentManager, ArrayList<ItemFragment> pages) {
            super(fragmentManager);
            this.pages = pages;
        }
    
        @Override
        public Fragment getItem(int index) {
            return pages.get(index);
        }
    
        @Override
        public int getCount() {
            return pages.size();
        }
    
        @Override
        public int getItemPosition(Object object) {
            int index = pages.indexOf (object);
    
            if (index == -1)
                return POSITION_NONE;
            else
                return index;
        }
    }
    

    当我需要通过索引删除一些页面时,我会这样做

    pages.remove(position); // ArrayList<ItemFragment>
    adapter.notifyDataSetChanged(); // MyFragmentAdapter
    

    这是我的适配器初始化

    MyFragmentAdapter adapter = new MyFragmentAdapter(getSupportFragmentManager(), pages);
    viewPager.setAdapter(adapter);
    
  • -9

    该片段必须已被删除,但问题是viewpager保存状态

    尝试

    myViewPager.setSaveFromParentEnabled(false);
    

    什么都没有用,但这解决了这个问题!

    干杯!

  • 0

    我的最终版本代码,修复了所有错误 . 我花了3天时间

    https://github.com/lin1987www/FragmentBuilder/blob/master/app/src/main/java/android/support/v4/app/FragmentStatePagerAdapterFix.java

    public class FragmentStatePagerAdapterFix extends PagerAdapter {
        private static final String TAG = FragmentStatePagerAdapterFix.class.getSimpleName();
        private static final boolean DEBUG = false;
    
        private WeakReference<FragmentActivity> wrFragmentActivity;
        private WeakReference<Fragment> wrParentFragment;
        private final FragmentManager mFragmentManager;
        private FragmentTransaction mCurTransaction = null;
    
        protected ArrayList<Fragment> mFragments = new ArrayList<>();
        protected ArrayList<FragmentState> mFragmentStates = new ArrayList<>();
        protected ArrayList<String> mFragmentTags = new ArrayList<>();
        protected ArrayList<String> mFragmentClassNames = new ArrayList<>();
        protected ArrayList<Bundle> mFragmentArgs = new ArrayList<>();
    
        private Fragment mCurrentPrimaryItem = null;
        private boolean[] mTempPositionChange;
    
        @Override
        public int getCount() {
            return mFragmentClassNames.size();
        }
    
        public FragmentActivity getFragmentActivity() {
            return wrFragmentActivity.get();
        }
    
        public Fragment getParentFragment() {
            return wrParentFragment.get();
        }
    
        public FragmentStatePagerAdapterFix(FragmentActivity activity) {
            mFragmentManager = activity.getSupportFragmentManager();
            wrFragmentActivity = new WeakReference<>(activity);
            wrParentFragment = new WeakReference<>(null);
        }
    
        public FragmentStatePagerAdapterFix(Fragment fragment) {
            mFragmentManager = fragment.getChildFragmentManager();
            wrFragmentActivity = new WeakReference<>(fragment.getActivity());
            wrParentFragment = new WeakReference<>(fragment);
        }
    
        public void add(Class<? extends android.support.v4.app.Fragment> fragClass) {
            add(fragClass, null, null);
        }
    
        public void add(Class<? extends android.support.v4.app.Fragment> fragClass, Bundle args) {
            add(fragClass, args, null);
        }
    
        public void add(Class<? extends android.support.v4.app.Fragment> fragClass, String tag) {
            add(fragClass, null, tag);
        }
    
        public void add(Class<? extends android.support.v4.app.Fragment> fragClass, Bundle args, String tag) {
            add(fragClass, args, tag, getCount());
        }
    
        public void add(Class<? extends android.support.v4.app.Fragment> fragClass, Bundle args, String tag, int position) {
            mFragments.add(position, null);
            mFragmentStates.add(position, null);
            mFragmentTags.add(position, tag);
            mFragmentClassNames.add(position, fragClass.getName());
            mFragmentArgs.add(position, args);
            mTempPositionChange = new boolean[getCount()];
        }
    
        public void remove(int position) {
            if (position < getCount()) {
                mTempPositionChange = new boolean[getCount()];
                for (int i = position; i < mTempPositionChange.length; i++) {
                    mTempPositionChange[i] = true;
                }
                mFragments.remove(position);
                mFragmentStates.remove(position);
                mFragmentTags.remove(position);
                mFragmentClassNames.remove(position);
                mFragmentArgs.remove(position);
            }
        }
    
        public void clear(){
            mFragments.clear();
            mFragmentStates.clear();
            mFragmentTags.clear();
            mFragmentClassNames.clear();
            mFragmentArgs.clear();
        }
    
        @Override
        public void startUpdate(ViewGroup container) {
        }
    
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Fragment fragment;
            // If we already have this item instantiated, there is nothing
            // to do.  This can happen when we are restoring the entire pager
            // from its saved state, where the fragment manager has already
            // taken care of restoring the fragments we previously had instantiated.
            fragment = mFragments.get(position);
            if (fragment != null) {
                return fragment;
            }
            if (mCurTransaction == null) {
                mCurTransaction = mFragmentManager.beginTransaction();
            }
            FragmentState fs = mFragmentStates.get(position);
            if (fs != null) {
                fragment = fs.instantiate(getFragmentActivity(), getParentFragment());
                // Fix bug
                // http://stackoverflow.com/questions/11381470/classnotfoundexception-when-unmarshalling-android-support-v4-view-viewpagersav
                if (fragment.mSavedFragmentState != null) {
                    fragment.mSavedFragmentState.setClassLoader(fragment.getClass().getClassLoader());
                }
            }
            if (fragment == null) {
                fragment = Fragment.instantiate(getFragmentActivity(), mFragmentClassNames.get(position), mFragmentArgs.get(position));
            }
            if (DEBUG) {
                Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
            }
            fragment.setMenuVisibility(false);
            fragment.setUserVisibleHint(false);
            mFragments.set(position, fragment);
            mFragmentStates.set(position, null);
            mCurTransaction.add(container.getId(), fragment, mFragmentTags.get(position));
            return fragment;
        }
    
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            Fragment fragment = (Fragment) object;
            if (mCurTransaction == null) {
                mCurTransaction = mFragmentManager.beginTransaction();
            }
            if (DEBUG) {
                Log.v(TAG, "Removing item #" + position + ": f=" + object
                        + " v=" + ((Fragment) object).getView());
            }
            if (position < getCount()) {
                FragmentState fragmentState = new FragmentState(fragment);
                Fragment.SavedState savedState = mFragmentManager.saveFragmentInstanceState(fragment);
                if (savedState != null) {
                    fragmentState.mSavedFragmentState = savedState.mState;
                }
                mFragmentStates.set(position, fragmentState);
                mFragments.set(position, null);
            }
            mCurTransaction.remove(fragment);
        }
    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            Fragment fragment = (Fragment) object;
            if (fragment != mCurrentPrimaryItem) {
                if (mCurrentPrimaryItem != null) {
                    mCurrentPrimaryItem.setMenuVisibility(false);
                    mCurrentPrimaryItem.setUserVisibleHint(false);
                }
                if (fragment != null) {
                    fragment.setMenuVisibility(true);
                    fragment.setUserVisibleHint(true);
                }
                mCurrentPrimaryItem = fragment;
            }
        }
    
        @Override
        public void finishUpdate(ViewGroup container) {
            if (mCurTransaction != null) {
                mCurTransaction.commitAllowingStateLoss();
                mCurTransaction = null;
                mFragmentManager.executePendingTransactions();
                // Fix: Fragment is added by transaction. BUT didn't add to FragmentManager's mActive.
                for (Fragment fragment : mFragments) {
                    if (fragment != null) {
                        fixActiveFragment(mFragmentManager, fragment);
                    }
                }
            }
        }
    
        @Override
        public boolean isViewFromObject(View view, Object object) {
            return ((Fragment) object).getView() == view;
        }
    
        @Override
        public Parcelable saveState() {
            Bundle state = null;
            // 目前顯示的 Fragments
            for (int i = 0; i < mFragments.size(); i++) {
                Fragment f = mFragments.get(i);
                if (f != null && f.isAdded()) {
                    if (state == null) {
                        state = new Bundle();
                    }
                    String key = "f" + i;
                    mFragmentManager.putFragment(state, key, f);
                }
            }
            if (mFragmentStates.size() > 0) {
                if (state == null) {
                    state = new Bundle();
                }
                FragmentState[] fs = new FragmentState[mFragmentStates.size()];
                mFragmentStates.toArray(fs);
                state.putParcelableArray("states_fragment", fs);
            }
            return state;
        }
    
        @Override
        public void restoreState(Parcelable state, ClassLoader loader) {
            if (state != null) {
                Bundle bundle = (Bundle) state;
                bundle.setClassLoader(loader);
                Parcelable[] fs = bundle.getParcelableArray("states_fragment");
                mFragments.clear();
                mFragmentStates.clear();
                mFragmentTags.clear();
                mFragmentClassNames.clear();
                mFragmentArgs.clear();
                if (fs != null) {
                    for (int i = 0; i < fs.length; i++) {
                        FragmentState fragmentState = (FragmentState) fs[i];
                        mFragmentStates.add(fragmentState);
                        if (fragmentState != null) {
                            mFragmentArgs.add(fragmentState.mArguments);
                            mFragmentTags.add(fragmentState.mTag);
                            mFragmentClassNames.add(fragmentState.mClassName);
                        } else {
                            mFragmentArgs.add(null);
                            mFragmentTags.add(null);
                            mFragmentClassNames.add(null);
                        }
                        mFragments.add(null);
                    }
                }
                Iterable<String> keys = bundle.keySet();
                for (String key : keys) {
                    if (key.startsWith("f")) {
                        int index = Integer.parseInt(key.substring(1));
                        Fragment f = mFragmentManager.getFragment(bundle, key);
                        if (f != null) {
                            f.setMenuVisibility(false);
                            mFragments.set(index, f);
                            mFragmentArgs.set(index, f.mArguments);
                            mFragmentTags.set(index, f.mTag);
                            mFragmentClassNames.set(index, f.getClass().getName());
                        } else {
                            Log.w(TAG, "Bad fragment at key " + key);
                        }
                    }
                }
                // If restore will change
                notifyDataSetChanged();
            }
        }
    
        public static void fixActiveFragment(FragmentManager fragmentManager, Fragment fragment) {
            FragmentManagerImpl fm = (FragmentManagerImpl) fragmentManager;
            if (fm.mActive != null) {
                int index = fragment.mIndex;
                Fragment origin = fm.mActive.get(index);
                if (origin != null) {
                    if ((origin.mIndex != fragment.mIndex) || !(origin.equals(fragment))) {
                        Log.e(TAG,
                                String.format("fixActiveFragment: Not Equal! Origin: %s %s, Fragment: %s $s",
                                        origin.getClass().getName(), origin.mIndex,
                                        fragment.getClass().getName(), fragment.mIndex
                                ));
                    }
                }
                fm.mActive.set(index, fragment);
            }
        }
    
        // Fix
        // http://stackoverflow.com/questions/10396321/remove-fragment-page-from-viewpager-in-android
        @Override
        public int getItemPosition(Object object) {
            int index = mFragments.indexOf(object);
            if (index < 0) {
                return PagerAdapter.POSITION_NONE;
            }
            boolean isPositionChange = mTempPositionChange[index];
            int result = PagerAdapter.POSITION_UNCHANGED;
            if (isPositionChange) {
                result = PagerAdapter.POSITION_NONE;
            }
            return result;
        }
    }
    
  • 7

    我希望这可以帮助你想要的东西 .

    private class MyPagerAdapter extends FragmentStatePagerAdapter {
    
        //... your existing code
    
        @Override
        public int getItemPosition(Object object){
            return PagerAdapter.POSITION_UNCHANGED;
        }
    }
    
  • 0

    尝试此解决方案 . 我已经使用数据绑定来绑定视图 . 您可以使用常见的“findViewById()”函数 .

    public class ActCPExpense extends BaseActivity implements View.OnClickListener,  {
    private static final String TAG = ActCPExpense.class.getSimpleName();
    private Context mContext;
    private ActCpLossBinding mBinding;
    
    private ViewPagerAdapter adapter;
    
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        try {
            setContentView(R.layout.act_cp_loss);
            mBinding = DataBindingUtil.setContentView(this, R.layout.act_cp_loss);
            mContext = ActCPExpense.this;
            initViewsAct();
    
    
        } catch (Exception e) {
            LogUtils.LOGE(TAG, e);
        }
    
    }
    
    
    private void initViewsAct() {
    
        adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFragment(FragmentCPPayee.newInstance(), "Title");
        mBinding.viewpager.setAdapter(adapter);
        mBinding.tab.setViewPager(mBinding.viewpager);
    
    
    
    }
    
    
    
    @Override
    public boolean onOptionsItemSelected(MenuItem itemActUtility) {
        int i = itemActUtility.getItemId();
        if (i == android.R.id.home) {
            onBackPressed();
    
        } 
    
        return super.onOptionsItemSelected(itemActUtility);
    }
    
    @Override
    public void onClick(View view) {
        super.onClick(view);
        int id = view.getId();
        if (id == R.id.btnAdd) {
            addFragment();
    
        } else if (id == R.id.btnDelete) {
            removeFragment();
    
        }
    
    
    }
        private void addFragment(){
        adapter.addFragment(FragmentCPPayee.newInstance("Title");
        adapter.notifyDataSetChanged();
        mBinding.tab.setViewPager(mBinding.viewpager);
    }
    private void removeFragment(){
        adapter.removeItem(mBinding.viewpager.getCurrentItem());
        mBinding.tab.setViewPager(mBinding.viewpager);
    }
    
    
    class ViewPagerAdapter extends FragmentStatePagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();
    
    
        public ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }
    
        @Override
        public int getItemPosition(@NonNull Object object) {
            return PagerAdapter.POSITION_NONE;
        }
    
    
        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }
    
        @Override
        public int getCount() {
            return mFragmentList.size();
        }
    
    
        public void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
    
        }
    
        public void removeItem(int pos) {
    
            destroyItem(null, pos, mFragmentList.get(pos));
            mFragmentList.remove(pos);
            mFragmentTitleList.remove(pos);
            adapter.notifyDataSetChanged();
            mBinding.viewpager.setCurrentItem(pos - 1, false);
        }
    
        @Override
        public CharSequence getPageTitle(int position) {
            return "Title " + String.valueOf(position + 1);
        }
    }
    
    
    }
    
  • 268

    ViewPager不会使用上面的代码删除您的片段,因为它会将多个视图(或您的案例中的片段)加载到内存中 . 除了可见视图外,它还将视图加载到可见视图的任一侧 . 这提供了从视图到视图的平滑滚动,使ViewPager非常酷 .

    要达到您想要的效果,您需要做一些事情 .

    • 将FragmentPagerAdapter更改为FragmentStatePagerAdapter . 这样做的原因是FragmentPagerAdapter将永久保存它加载到内存中的所有视图 . FragmentStatePagerAdapter处理位于当前和可遍历视图之外的视图 .

    • 重写适配器方法getItemPosition(如下所示) . 当我们调用 mAdapter.notifyDataSetChanged(); 时,ViewPager会询问适配器以确定在定位方面发生了哪些变化 . 我们使用此方法表示所有内容都已更改,因此重新处理所有视图定位 .

    这是代码......

    private class MyPagerAdapter extends FragmentStatePagerAdapter {
    
        //... your existing code
    
        @Override
        public int getItemPosition(Object object){
            return PagerAdapter.POSITION_NONE;
        }
    
    }
    
  • 0

    我添加了一个函数“clearFragments”,我在设置新片段之前使用该函数清除了适配器 . 这称为片段的正确删除操作 . 我的pagerAdapter类:

    private class ChartPagerAdapter extends FragmentPagerAdapter{
        private ArrayList<Fragment> fragmentList;
    
        ChartPagerAdapter(FragmentManager fm){
            super(fm);
            fragmentList = new ArrayList<>();
        }
    
        void setFragments(ArrayList<? extends Fragment> fragments){
            fragmentList.addAll(fragments);
        }
    
        void clearFragments(){
            for(Fragment fragment:fragmentList)
                getChildFragmentManager().beginTransaction().remove(fragment).commit();
            fragmentList.clear();
        }
    
        @Override
        public Fragment getItem(int i) {
            return fragmentList.get(i);
        }
    
        @Override
        public int getCount() {
            return fragmentList.size();
        }
    
    }
    
  • 0

    您可以覆盖 destroyItem 方法

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        fragmentManager.beginTransaction().remove((Fragment) object).commitNowAllowingStateLoss();
    }
    
  • 1

    动态地在viewpager中添加或删除片段 . 在活动开始时调用setupViewPager(viewPager) . 加载不同的片段调用setupViewPagerCustom(viewPager) . 例如按钮点击调用:setupViewPagerCustom(viewPager);

    private void setupViewPager(ViewPager viewPager)
    {
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
        adapter.addFrag(new fragmnet1(), "HOME");
        adapter.addFrag(new fragmnet2(), "SERVICES");
    
        viewPager.setAdapter(adapter);
    }
    
    private void setupViewPagerCustom(ViewPager viewPager)
    {
    
        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
    
        adapter.addFrag(new fragmnet3(), "Contact us");
        adapter.addFrag(new fragmnet4(), "ABOUT US");
    
    
        viewPager.setAdapter(adapter);
    }
    
    //Viewpageradapter, handles the views
    
    static class ViewPagerAdapter extends FragmentStatePagerAdapter
    {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();
    
        public ViewPagerAdapter(FragmentManager manager){
            super(manager);
        }
    
        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }
    
        @Override
        public int getCount() {
            return mFragmentList.size();
        }
    
        @Override
        public int getItemPosition(Object object){
            return PagerAdapter.POSITION_NONE;
        }
    
        public void addFrag(Fragment fragment, String title){
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }
    
        @Override
        public CharSequence getPageTitle(int position){
            return mFragmentTitleList.get(position);
        }
    }
    

相关问题