繁体   English   中英

选择不同的选项卡时如何在 ViewPager + TabLayout 中暂停片段?

[英]How to pause a fragment in ViewPager + TabLayout when a different tab is selected?

现在我有一个标签布局,下面有一个 ViewPager + 适配器。 我想在选择不同的选项卡时暂停片段(不是销毁/弹出它,只是暂停它)并在选择片段的选项卡时恢复它。

public class PagerFragment extends Fragment {

    ViewPagerAdapter pagerAdapter;
    ViewPager pager;
    TabLayout tabLayout;
    int position;

    public PagerFragment() {
        super();
    }

    public void setPosition(int position) {
        this.position = position;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onStop() {
        super.onStop();
    }

    @Override
    public void onPause() {
        super.onPause();
        pagerAdapter.clear();
        pagerAdapter.notifyDataSetChanged();
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!isAdded()) {
            pagerAdapter.instantiateItem(pager, position);
        }
    }

    @SuppressLint("InflateParams")
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_pager, null);
        pagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
        setPosition(position);
        pagerAdapter.setDevicesList(devicesList);
        pager = root.findViewById(R.id.pager);
        pager.setAdapter(pagerAdapter);
       
        tabLayout = root.findViewById(R.id.tab_layout);

        for (int i = 0; i < devicesList.size(); i++) {
            tabLayout.addTab(tabLayout.newTab().setText(String.valueOf(devicesList.get(i).getName())));
        }

        TabLayout.Tab tab = tabLayout.getTabAt(position);
        if (tab != null) {
            tab.select();
            pager.setCurrentItem(position);
            tabLayout.setupWithViewPager(pager);

            tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
                @Override
                public void onTabSelected(TabLayout.Tab tab) {
                    pager.setCurrentItem(tab.getPosition());
                }

                @Override
                public void onTabUnselected(TabLayout.Tab tab) {
                    int pos = tab.getPosition();
                }

                @Override
                public void onTabReselected(TabLayout.Tab tab) {

                }
            });
        }
        tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager));
        return root;
    }
}



public class ViewPagerAdapter extends FragmentPagerAdapter  {


    ArrayList<ConnectedBluetoothDevice> devicesList;
    ArrayList<DataViewFragment> dataViewFragments;

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

    /**
     * Initializes the adaptor with the device list and the list of data fragments.
     * @param devicesList List of devices to be displayed in their own data fragment.
     */
    public void setDevicesList(ArrayList<ConnectedBluetoothDevice> devicesList) {
        this.devicesList = devicesList;
        dataViewFragments = new ArrayList<>();
        for (int i = 0; i < devicesList.size(); i++) {
            dataViewFragments.add(new DataViewFragment(devicesList.get(i)));
        }
    }

    /**
     * GetItem
     * @param position position of item in the viewPager list to be returned
     * @return fragment to view
     */
    @NonNull
    public Fragment getItem(int position) {
        if (dataViewFragments != null && position < dataViewFragments.size()) {
            return dataViewFragments.get(position);
        } else {
            return new DataViewFragment(null);
        }
    }

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

    /**
     * Updates the tabs in tabLayout while swiping pages
     * @param position of the viewPage
     * @return title of the tab
     */
    public CharSequence getPageTitle(int position) {
        super.getPageTitle(position);
        return devicesList.get(position).getName();
    }

    public void clear() {
        dataViewFragments.clear();
    }
}

一些注意事项:

  • 我被指示在 ViewPager 和 FragmentPagerAdapter 中修复此错误,所以请不要向我推荐 ViewPager2 和 FragmentStatePagerAdapter 中的解决方案:)
  • 我听说setOffscreenPageLimit(0); 不是最佳实践,所以我想避免这种情况(特别是因为我只需要暂停片段而不破坏它)

这取决于您使用的ViewPager版本,因为它是稍后添加的。

您正在使用已弃用的构造函数

因此,只要您使用最新版本的Viewpager ,您就应该使用不推荐使用的构造函数:-

public FragmentPagerAdapter(
    @NonNull FragmentManager fm,
    @FragmentPagerAdapter.Behavior int behavior
)

构造函数具有行为BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT

那么只有当前片段在 RESUMED state 中。 所有其他片段的上限为 STARTED

为了从RESUMED onPause进入STARTED生命周期 state 被调用。

所以改变

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

public ViewPagerAdapter(FragmentManager fm) {
            super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
        }

此方法用于仅在选择指定选项卡时调用函数才能运行。

 @Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);

    if (isVisibleToUser) {
      // add your tab functions here
    } else {
        // do nothing
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM