使用 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 解决方案复杂得多,但我认为它会起作用。我还没测试完。
我对 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 解决方案复杂得多,但我认为它会起作用。我还没测试完。