私のActivity
にはViewPager
が含まれており、Adapter
を拡張するカスタムFragmentStatePagerAdapter
です。 ViewPager
には3つのフラグメントが含まれます
ViewPagerからフラグメントを削除するコード
MainActivity
public void deleteElement(){
final int currentItem = mViewPager.getCurrentItem();
mPagerAdapter.removeItem(currentItem);
mPagerAdapter.notifyDataSetChanged();
}
CustomPagerAdapter
private ArrayList<Item> data;
public void removeItem(int index){
data.remove(index);
}
中間のFragment
(インデックス1)を削除する場合:
data
から正しいitem
を削除しています。Fragment
3がnotifyDataSetChanged
の後に削除され、現在のFragment
はまだユーザーが見たフラグメントであり、ロードされているデータはSavedInstance
バンドルそのため、ユーザーが削除しようとしたのと同じFragment
が表示されるという最終結果は、彼にとってはちょっと残念です。
アイデア?
*****[〜#〜] edit [〜#〜]******
ViewPager2機能 のように思われる
この質問は少し古いことは知っていますが、Googleが最近この問題を ViewPager2 で解決したことを知るのは興味深いかもしれません。例を参照してください here
まず、build.gradleファイル内の次の依存関係:
_ dependencies {
implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'
}
_
これで、xmlファイルのViewPagerを次のように置き換えることができます。
_ <androidx.viewpager2.widget.ViewPager2
Android:id="@+id/pager"
Android:layout_width="match_parent"
Android:layout_height="0dp"
Android:layout_weight="1" />
_
次に、アクティビティでViewPagerをViewPager2に置き換える必要があります。
ViewPager2には、RecycleView.AdapterまたはFragmentStateAdapterが必要です。
_ public class TabAdapter extends FragmentStateAdapter {
private final List<Tab> tabs;
public TabAdapter(@NonNull FragmentManager fm, List<Tab> tabs, Lifecycle lifecycle) {
super(fm, lifecycle);
this.tabs = tabs;
}
@NonNull
@Override
public Fragment createFragment(int position) {
//create your fragment here
}
@Override
public int getItemCount() {
return tabs.size();
}
@Override
public long getItemId(int position) {
// use a distinct id for each item to allow the adapter to see the changes
}
}
_
TabLayoutを使用していた場合は、TabLayoutMediatorを使用できます。
_ TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager, true, new TabLayoutMediator.OnConfigureTabCallback() {
@Override
public void onConfigureTab(@NotNull TabLayout.Tab tab, int position) {
// configure your tab here
tab.setText(tabs.get(position).getTitle());
}
});
tabLayoutMediator.attach();
_
データを削除するには、コレクションからアイテムを削除した後、notifyDataSetChanged()
メソッドを呼び出すか、削除されたアイテムの位置でnotifyItemRemoved()
を呼び出します。
これを追加してみてください:
private class MyPagerAdapter extends FragmentStatePagerAdapter {
//... your existing code
@Override
public int getItemPosition(Object object){
return PagerAdapter.POSITION_NONE;
}
}
PagerAdapter#getItemPosition
を実装する以外に選択肢はありません。 ViewPagerがその位置を更新する方法を決定する正確な方法であるソースを見ると、notifyDataSetChanged
の後に新しいフラグメントを追加するか、無効なフラグメントをドロップします。それほど難しくないはずです。渡されたフラグメントの状態にアクセスするだけでよく、また、順序を保持するアクティビティのマスター状態にアクセスする必要があります。
また、各フラグメントの順序を変更できるため、getItemId
を実装して各フラグメントの一貫したIDを返す必要があります。
これが、写真のViewPagerでの処理方法です。
private inner class PhotoPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
override fun getItem(position: Int): PhotoViewFragment {
// getItem is called to instantiate the fragment for the given page.
return PhotoViewFragment.newInstance(position, [email protected][position])
}
override fun getItemId(position: Int): Long {
return [email protected][position].ID!!.hashCode().toLong()
}
override fun getItemPosition(`object`: Any): Int {
val frag = `object` as PhotoViewFragment
val idx = [email protected] { ph -> ph.ID == frag.dataBinding.photo.ID }
return if (idx >= 0) idx else PagerAdapter.POSITION_NONE
}
override fun getCount(): Int {
return [email protected]
}
}
FragmentStatePagerAdapterの代わりにFragmentPagerAdapterの使用を試みることができます。事は、私もこの問題に遭遇したことであり、それは私を助けた。
最初にアダプタをnullに設定してから、元に戻す必要があります。
int currentPosition = mViewPager.getCurrentItem();
mPagerAdapter.notifyDataSetChanged();
mViewPager.setAdapter(null);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(currentPosition);