使用 FragmentPagerAdapter 在滑动期间跳过片段

Skipping Fragments During Swipes with a FragmentPagerAdapter

我对 Android 编程还很陌生,所以这 [希望|可能] 是个愚蠢的问题。

我正在复制底部有 4 个标签的 iOS 应用程序的行为。

最初,只有第一个和最后一个处于活动状态。中心2只有在搜索成功后才会激活

我喜欢 Android 的滑动更改行为(我可能会将其添加到 iOS 应用程序)。

但是,我不确定跳过两个不活动中心的正确方法,因此从右向左滑动会从第一个选项卡滑动到最后一个选项卡(反之亦然)。

我在已发布的 API 中没有看到任何挂钩。我想我可能会弄乱 getItem() 中返回的项目(而不是发送中间的一个,我直接转到最后一个),但我想知道这是否是正确的方法。我很担心,因为您在 getItem() 上实例化实例,所以这意味着它可能不是执行此操作的最佳位置。

对此有任何反馈吗?我知道使用 Android,做某事通常有十几种方法,但通常只有一两种 "correct" 方法。

我想以正确的方式做到这一点。

好的。我说我会报告我如何 "solved" 这个问题。它不是 100% 完美,但它确实有效,我认为它基本上是在做正确的事情。

首先,我使用了the TabLayout system, where you create a TabLayout object, and give it a ViewPager and FragmentPagerAdapter

我发现 Tab class 是最终的。你不能 subclass 它。这意味着我需要为状态使用片段 (enabled/disabled)。您可以打开和关闭选项卡的可点击,但我向 Fragment subclass 添加了一个 "enabled" 标志。这是我用来查询选项卡状态的。

然后我在 Adapter subclass 中创建了一个嵌入的 class。我实现了 ViewPager.OnPageChangeListener(这是一个接口):

private class MyTabPagerListener implements ViewPager.OnPageChangeListener

我将其作为侦听器添加到 TabLayout:

mViewPager.addOnPageChangeListener(new MyTabPagerListener(mTabLayout,this));

然后我在onPageSelected()方法中实现了"skipping"代码。我试着预测选择的去向,这样我就可以跳转到适当的选项卡。整个思路就是弄清楚方向。如果下一个选择的标签被禁用,那么我们继续:

public void onPageSelected(int position) {
    AWrapperBaseFragment    fragment = (AWrapperBaseFragment)mAdapter.getItem(position);
    mSkipToPosition = -1; // This will inform the "wrap up" function that we need to skip to another tab.

    if ( !fragment.isEnabled() ) {
        Log.d(TAG, "Page " + position + " is disabled, selecting a different one.");
        int oldPosition = mTabLayout.getSelectedTabPosition();
        if ( position > oldPosition ) {
            Log.d(TAG, "Going up.");
            for ( int i = position + 1; i < mAdapter.getCount(); i++ ) {
                AWrapperBaseFragment    comp_fragment = (AWrapperBaseFragment)mAdapter.getItem(i);
                if ( comp_fragment.isEnabled() ) {
                    mSkipToPosition = i;
                    break;
                }
            }
        }

        if ( mSkipToPosition == -1 ) {
            Log.d(TAG, "Going down.");
            for ( int i = position - 1; i > -1; i-- ) {
                AWrapperBaseFragment    comp_fragment = (AWrapperBaseFragment)mAdapter.getItem(i);
                if ( comp_fragment.isEnabled() ) {
                    mSkipToPosition = i;
                    break;
                }
            }
        }
    }

    mSelectedPosition = position;

    if ( mSkipToPosition == -1 ) {
        mSkipToPosition = mSelectedPosition;
    }

    Log.d(TAG, "Page selection will " + ((mSelectedPosition != mSkipToPosition) ? ("change from " + mSelectedPosition + " to " + mSkipToPosition) : "not be changed." ));
}

该函数设置一个信号量,在状态改变回调中执行:

public void onPageScrollStateChanged(int state) {
    Log.d(TAG, "New Scroll State for page " + mSelectedPosition + ": " + state);
    if ( (state == 0) && (mSkipToPosition > -1) && (mSkipToPosition != mSelectedPosition) ) {
        Log.d(TAG, "This is a disabled page, so page selection will change from " + mSelectedPosition + " to " + mSkipToPosition + "." );
        mViewPager.setCurrentItem(mSkipToPosition, true);
    }
}

正如我所说,它并不完美。有一个明显的犹豫,您仍然看到禁用的选项卡内容经过(所以不要在禁用的选项卡中留下斜坡)。

它比 iOS 解决方案复杂得多,但我认为它会起作用。我还没测试完。