【问题标题】:FragmentPagerAdapter - how to detect a swipe or a tab click when user goes to a new tab?FragmentPagerAdapter - 当用户转到新标签时如何检测滑动或标签点击?
【发布时间】:2015-01-17 20:08:59
【问题描述】:

我有一个MainActivity,它在FragmentPagerAdapter 中有三个片段,如下所示。如何通过滑动或单击选项卡来确定用户何时从第一个片段转到第二个或从第二个到第三个?我看到getItem() 方法并不总是像我声明的mViewPager.setOffscreenPageLimit(2) 那样被调用;

public class MainThreeTabAdapter extends FragmentPagerAdapter {

    private final String[] CONTENT = new String[]{"News", "Rewards", "Me"};

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

    @Override
    public Fragment getItem(int position) {
        if (position == 0) {
            return NewsFragment.newInstance();
        } else if (position == 1) {
            return RewardsFragment.newInstance();
        } else if (position == 2) {
            return MeFragment.newInstance(true, App.getAccountData().getId());
        } else {
            return null;
        }

    }

    @Override
    public CharSequence getPageTitle(int position) {
        return CONTENT[position % CONTENT.length];
    }

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

在MainActivity的onCreate()

    mainThreeTabAdapter = new MainThreeTabAdapter(getFragmentManager());

    // Set up the ViewPager with the sections adapter.
    // this ensures that 2 tabs on each side of current are kept in memory, which is all we need for our case. Default = 1
    // this is all taken from the Quickreturn facebook sample app
    mViewPager.setOffscreenPageLimit(2);
    mViewPager.setAdapter(mainThreeTabAdapter);

【问题讨论】:

    标签: android android-fragments android-viewpager android-tabhost android-pageradapter


    【解决方案1】:

    getItem() 方法仅在创建视图时调用。要了解为什么没有调用getItem(),有助于了解ViewPager 的默认行为。默认情况下,当您在 ViewPager 的特定页面上时,它还会创建该特定页面之前和之后的页面。如果您要以 [a,b,c] 的顺序命名 3 个片段,并且您在页面 b 上,由于 ViewPager 片段的默认行为,a 和 c 已经通过调用 getItem(int) 创建.由于已经创建了片段,因此您不会再收到对 getItem() 的调用

    另外:可以使用ViewPager.setOffScreenLimit()修改此行为

    为了在用户切换页面时收到通知,您实际上想要做的是使用ViewPager.addOnPageChangeListener()OnPageChangeListener 设置为ViewPager,以便在选择页面时收到通知。

    【讨论】:

    • setOnPageChangeListener() 现在已弃用。应该改用addOnPageChangeListener()
    • 为什么这不是一个被接受的答案?我觉得它回答了这个问题。我有同样的问题,这个答案为我回答了这个问题。使用onPageSelected(int position) 方法,我可以使用if 语句检查正在显示的片段
    【解决方案2】:
        mViewPager.setAdapter(mSectionsPagerAdapter);
        mViewPager.setOffscreenPageLimit(4);
        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
            }
    
            @Override
            public void onPageSelected(int position) {
                _position = position;
                switch (position) {
                    case 0:
                        _header.setButtonVisible(1, View.GONE);
                        break;
                    case 1:
                        _header.setButtonVisible(1, View.GONE);
                        break;
                    case 2:
                        _header.setButtonVisible(1, View.VISIBLE);
                        break;
                    case 3:
                        _header.setButtonVisible(1, View.VISIBLE);
                        break;
                }
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
    
            }
        });
    

    【讨论】:

      【解决方案3】:

      如果我假设您在 ViewPager 中使用 TabLayout,您应该使用 addOnTabSelectedListener()。这将处理明确的选项卡单击或滑动。

      mTabLayout.setupWithViewPager(mViewPager);
      
      mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
              @Override
              public void onTabSelected(TabLayout.Tab tab) {
                  Logger.d(TAG, "tabSelected: " + tab.getPosition());
              }
      
              @Override
              public void onTabUnselected(TabLayout.Tab tab) {
                  Logger.d(TAG, "tabUnselected: " + tab.getPosition());
              }
      
              @Override
              public void onTabReselected(TabLayout.Tab tab) {
                  Logger.d(TAG, "tabReselected: " + tab.getPosition());
              }
      });
      

      【讨论】:

      • 但是 addOnTabSelectedListener 是通过 tabclick 和滑动调用的。
      【解决方案4】:

      首先我猜你有以下声明的字段

      ViewPager pager;
      TabLayout tabs;
      MainThreeTabAdapter adapter;
      

      接下来,您必须创建适配器实例并将其设置为寻呼机。在这里你可以添加监听器调用addOnPageChangeListener

      adapter = new MainThreeTabAdapter(getSupportFragmentManager());
      pager.setAdapter(adapter);
      pager.addOnPageChangeListener(/*here is your listener instance*/);
      tabs.setupWithViewPager(pager);
      

      当页面通过滑动或点击选项卡切换到新页面时,onPageSelected(int position) 方法将被调用。

      如果您想获取当前片段的实际实例以直接与其交互,您可以创建自己的FragmentPagerAdapter,它应该缓存创建的片段:

      public abstract class CachingFragmentPagerAdapter extends FragmentPagerAdapter {
      
          private final SparseArray<Fragment> registeredFragments = new SparseArray<>();
      
          public CachingFragmentPagerAdapter(FragmentManager fm) {
              super(fm);
          }
      
          @Override
          public Object instantiateItem(ViewGroup container, int position) {
              Fragment fragment = (Fragment) super.instantiateItem(container, position);
              registeredFragments.put(position, fragment);
              return fragment;
          }
      
          @Override
          public void destroyItem(ViewGroup container, int position, Object object) {
              registeredFragments.remove(position);
              super.destroyItem(container, position, object);
          }
      
          public Fragment getRegisteredFragment(int position) {
              return registeredFragments.get(position);
          }
      
          public SparseArray<Fragment> getRegisteredFragments() {
              return registeredFragments;
          }
      }
      

      这样你就不得不

      1. CachingFragmentPagerAdapter 扩展您的MainThreeTabAdapter
      2. addOnPageChangeListener 添加到ViewPager
      3. onPageSelected 方法中查找片段并与之交互,如下所示:

        public void onPageSelected(int position) {
            final Fragment fragment = adapter.getRegisteredFragment(position);
            if (fragment instanceof NewsFragment) {
                //...
            } else ...
        }
        

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-09
        • 1970-01-01
        • 2021-02-15
        • 1970-01-01
        • 1970-01-01
        • 2014-10-30
        相关资源
        最近更新 更多