【问题标题】:How to switch List fragment and Detail fragment in view pager tab?如何在视图分页器选项卡中切换列表片段和详细信息片段?
【发布时间】:2020-07-04 19:02:52
【问题描述】:

我正在尝试在视图寻呼机的第一个选项卡中实现片段的切换。我尝试了在link 找到的方法,它在第一个选项卡中使用根片段,然后切换子片段。但是,当第二个子片段屏幕旋转发生时,应用程序会切换回第一个子片段,除此之外,这似乎是一种 hack。

我尝试搜索其他方法,但发现了几十个似乎都很混乱的答案。 here 的解释似乎是对的,但我不完全理解。这是该链接的解释和代码:

这种方法是通过覆盖getItem(...) 方法以及每次调用viewPager.getAdapter().notifyDataSetChanged() 时调用的getItemPosition(Object object) 来切换显示在FragmentPagerAdapter 内的片段。例如:

public static class MyPagerAdapter extends FragmentStatePagerAdapter {
// Return a different fragment for position based on additional state tracked in a member variable
@Override
public Fragment getItem(int position) {
    // For a given position, return two different potential fragments based on a condition
}

// Force a refresh of the page when a different fragment is displayed
@Override
public int getItemPosition(Object object) {
    // this method will be called for every fragment in the ViewPager
    if (object instanceof SomePermanantCachedFragment) {
        return POSITION_UNCHANGED; // don't force a reload
    } else {
        // POSITION_NONE means something like: this fragment is no longer valid
        // triggering the ViewPager to re-build the instance of this fragment.
        return POSITION_NONE;
    }
}
}

假设我有 ListFragmentDetailFragment 应该在第一个选项卡中切换。

  1. 我会在哪里打电话给viewPager.getAdapter().notifyDataSetChanged()
  2. (...基于成员变量中跟踪的其他状态)我该如何实现?
  3. SomePermanantCachedFragment 在我的情况下指的是ListFragment

例如,我也尝试搜索 github,但没有成功...

【问题讨论】:

    标签: android android-fragments android-viewpager


    【解决方案1】:

    如果您在 PagerAdapter 中的片段是动态的,那么您应该使用 Dynamic FragmentPagerAdapter。

    public class DynamicFragmentPagerAdapter extends PagerAdapter {
        private static final String TAG = "DynamicFragmentPagerAdapter";
      
        private final FragmentManager fragmentManager;
      
        public static abstract class FragmentIdentifier implements Parcelable {
            private final String fragmentTag;
            private final Bundle args;
          
            public FragmentIdentifier(@NonNull String fragmentTag, @Nullable Bundle args) {
                this.fragmentTag = fragmentTag;
                this.args = args;
            }
          
            protected FragmentIdentifier(Parcel in) {
                fragmentTag = in.readString();
                args = in.readBundle(getClass().getClassLoader());
            }
    
            @Override
            public void writeToParcel(Parcel dest, int flags) {
                dest.writeString(fragmentTag);
                dest.writeBundle(args);
            }
          
            protected final Fragment newFragment() {
                Fragment fragment = createFragment();
                Bundle oldArgs = fragment.getArguments();
                Bundle newArgs = new Bundle();
                if(oldArgs != null) {
                    newArgs.putAll(oldArgs);
                }
                if(args != null) {
                    newArgs.putAll(args);
                }
                fragment.setArguments(newArgs);
                return fragment;
            }
    
            protected abstract Fragment createFragment();
        }
      
        private ArrayList<FragmentIdentifier> fragmentIdentifiers = new ArrayList<>();
    
        private FragmentTransaction currentTransaction = null;
    
        private Fragment currentPrimaryItem = null;
    
        public DynamicFragmentPagerAdapter(FragmentManager fragmentManager) {
            this.fragmentManager = fragmentManager;
        }
    
        private int findIndexIfAdded(FragmentIdentifier fragmentIdentifier) {
            for (int i = 0, size = fragmentIdentifiers.size(); i < size; i++) {
                FragmentIdentifier identifier = fragmentIdentifiers.get(i);
                if (identifier.fragmentTag.equals(fragmentIdentifier.fragmentTag)) {
                    return i;
                }
            }
            return -1;
        }
    
        public void addFragment(FragmentIdentifier fragmentIdentifier) {
            if (findIndexIfAdded(fragmentIdentifier) < 0) {
                fragmentIdentifiers.add(fragmentIdentifier);
                notifyDataSetChanged();
            }
        }
    
        public void removeFragment(FragmentIdentifier fragmentIdentifier) {
            int index = findIndexIfAdded(fragmentIdentifier);
            if (index >= 0) {
                fragmentIdentifiers.remove(index);
                notifyDataSetChanged();
            }
        }
    
        @Override
        public int getCount() {
            return fragmentIdentifiers.size();
        }
    
        @Override
        public void startUpdate(@NonNull ViewGroup container) {
            if (container.getId() == View.NO_ID) {
                throw new IllegalStateException("ViewPager with adapter " + this
                        + " requires a view id");
            }
        }
    
        @SuppressWarnings("ReferenceEquality")
        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            if (currentTransaction == null) {
                currentTransaction = fragmentManager.beginTransaction();
            }
            final FragmentIdentifier fragmentIdentifier = fragmentIdentifiers.get(position);
            // Do we already have this fragment?
            final String name = fragmentIdentifier.fragmentTag;
            Fragment fragment = fragmentManager.findFragmentByTag(name);
            if (fragment != null) {
                currentTransaction.attach(fragment);
            } else {
                fragment = fragmentIdentifier.newFragment();
                currentTransaction.add(container.getId(), fragment, fragmentIdentifier.fragmentTag);
            }
            if (fragment != currentPrimaryItem) {
                fragment.setMenuVisibility(false);
                fragment.setUserVisibleHint(false);
            }
            return fragment;
        }
    
        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            if (currentTransaction == null) {
                currentTransaction = fragmentManager.beginTransaction();
            }
            currentTransaction.detach((Fragment) object);
        }
    
        @SuppressWarnings("ReferenceEquality")
        @Override
        public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            Fragment fragment = (Fragment) object;
            if (fragment != currentPrimaryItem) {
                if (currentPrimaryItem != null) {
                    currentPrimaryItem.setMenuVisibility(false);
                    currentPrimaryItem.setUserVisibleHint(false);
                }
                fragment.setMenuVisibility(true);
                fragment.setUserVisibleHint(true);
                currentPrimaryItem = fragment;
            }
        }
    
        @Override
        public void finishUpdate(@NonNull ViewGroup container) {
            if (currentTransaction != null) {
                currentTransaction.commitNowAllowingStateLoss();
                currentTransaction = null;
            }
        }
    
        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
            return ((Fragment) object).getView() == view;
        }
    
        @Override
        public Parcelable saveState() {
            Bundle bundle = new Bundle();
            bundle.putParcelableArrayList("fragmentIdentifiers", fragmentIdentifiers);
            return bundle;
        }
    
        @Override
        public void restoreState(Parcelable state, ClassLoader loader) {
            Bundle bundle = ((Bundle)state);
            bundle.setClassLoader(loader);
            fragmentIdentifiers = bundle.getParcelableArrayList("fragmentIdentifiers");
        }
    }
    

    完成后,您可以使用removeFragmentaddFragment 更改 ViewPager 中的片段。

    从技术上讲,您可以添加一个 setFragment(int index) 方法来专门在索引 0 处替换它。

    如果片段似乎没有更新,刷新 ViewPager 的技巧始终是setAdapter(null); setAdapter(adapter);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-20
      • 1970-01-01
      相关资源
      最近更新 更多