临时/动态禁用Viewpager中的单个页面

5

我有一个扩展的FragmentPagerAdapter,为ViewPager提供了3个片段,使我可以在3个页面之间滑动或使用我添加到操作栏的选项卡手动选择页面。

我想临时禁止用户使用任何导航类型访问最后一页(禁用任何特定页面的更通用的解决方案也很有趣,但不是必需的)。然后,我将通过其中一个片段的回调重新启用他们的访问权限。

我已经阅读了一些类似问题的答案,这些问题不允许通过覆盖onTouchEvent和onInterceptTouchEvent来滑动,然后在其中使用一些自定义手势检测,甚至使用beginFakeDrag()的半个解决方案。

我的当前解决方案只是在适配器中设置较小的项目数,确保使用notifyDataSetChanged(),并在必要时将其改回。是否有任何优雅的替代方法,也许不需要更改数据集?

我还看到ActionBar.Tab没有setEnable()方法,大多数建议只删除选项卡。我能否让选项卡保持可见但不可选?我的方法是定义哪个选项卡被禁用,并在用户选择禁用的选项卡时重新选择先前选择的选项卡。

编辑: 我的目标是禁用选项卡和滑动到最后一页。


为什么不将最后一个选项卡的布局切换为用户无法交互的内容呢?ViewPager并不适合这些需求。是的,你可以通过更改数据集来动态使用它,但是阻止选项卡界面比更改ViewPager的行为更容易。 - einschnaehkeee
嗯,我并不是真的在寻找更简单的方法。我正在使用选项卡和滑动来进行导航。对于这两个问题,我都有可行的解决方案;我只是想寻求其他可能打包得更好的建议。 - BioeJD
但无论如何,你是对的,阻止与页面的交互肯定是可行的解决方案。 - BioeJD
你还需要考虑到用户并不习惯在Android设备上看到被阻止的选项卡页面。因此,除非你向他明确解释了这种行为,否则他可能会认为你的应用程序无法正常工作,因为通常情况下所有选项卡都是可访问的。当我看到无法点击的按钮或其他奇怪的东西时,我个人总是有点困惑。我的第一个想法总是“它是否正常工作或者是一个错误?”。因此,也许使用另一种UI解决方案可能更好。 - einschnaehkeee
这是一个非常好的观点。最终,问题的那一部分取决于用户反馈,我会考虑所有可能的解决方案。话虽如此,问题仍然保持不变,无论它是否会让用户感到困惑,在任何事情最终确定之前都需要做出决定。另外,我已经考虑过在启用最终页面之前将选项卡删除。 - BioeJD
1个回答

6

你肯定需要创建自己的自定义ViewPager子类。我创建了一个简单的自定义ViewPager,叫做CustomSwipePager,它将在需要时处理阻止用户交互。

public class CustomSwipeViewPager extends ViewPager {

    private boolean mLastPageEnabled = false;
    private int mLastPageIndex = 0;

    public NoSwipeViewPager(Context context) {
        super(context);
    }

    public NoSwipeViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setLastPageEnabled(boolean enabled) {
        mLastPageEnabled = enabled;
    }

    public void setLastPageIndex(int index) {
        mLastPageIndex = index;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event){

        if(!mLastPageEnabled && getCurrentItem() >= (mLastPageIndex - 1)) {
            // Always return false to disable user swipes
            return false;
        }

        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (!mLastPageEnabled && getCurrentItem() >= (mLastPageIndex - 1)) {
            // Always return false to disable user swipes
            return false;
        }

        return true;
    }
}

在类中有两种关键方法可以利用,分别是setLastPageEnabled()setLastPageIndex()。您可以将最后一页的索引设为您需要的任意值,在您的情况下,如果您有三个项目,您会将其设置为2。然后还可以使用setLastPageEnabled(false)来禁用滑动,要重新启用,请使用setLastPageEnabled(true)

您可以像这样将此自定义视图包含到您的布局中:

<com.mypackage.CustomSwipeViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/custom_swipe_view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

最后,在Fragment或Activity中适当的位置引用它:

private CustomSwipeViewPager mPager;

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

    mPager = (CustomSwipeViewPager) findViewById(R.id.custom_swipe_view_pager);
    mPager.setLastPageEnabled(false);
    mPager.setLastPageIndex(2);
}

3
这与我在问题中提到的解决方案类似,您可以重写onTouchEvent和onTouchInterceptEvent。非常干净的实现。这个解决方案缺少的部分是检测手势的方向,以便仍然可以从倒数第二页向后滑动到上一页。如果我决定采用这种方法,我会包含我的代码。 - BioeJD
正如@einschnaehkeee在他的评论中所暗示的那样,这有点像ViewPager的黑客使用方式,但我已经考虑过其他选项,并决定这个功能最适合我的用例。我想我希望我错过了一些明显的东西。 - BioeJD
1
我猜唯一的其他选择就是根据需要添加/删除最后一页。此时,您可能需要考虑更改UI。也许最后一页甚至不属于ViewPager,但我对您的设计不熟悉。 - Andrea Thacker
是的,我已经考虑过其他UI选项了。对于这个目的使用移动软件已经相当独特了,所以我必须做出很多决定,是坚持使用Android API组件还是重新设计很多东西。但我确实有理由想要在ViewPager中显示页面;我只是觉得它们与发布的问题无关,因为那是其中一个假设。感谢您的建议。 - BioeJD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接