在ViewPager中设计一个HorizontalScrollView或使用fragments:

8

我需要设计以下屏幕,需要你的建议:

enter image description here

说明:

标题是静态/固定的,不需做任何更改。

黄色区域:这里很有趣,我需要设计一个类似ViewPager的屏幕,最多可以向左/右滚动4个屏幕。

红色区域:每个屏幕都需要添加一个可滚动的表格/网格,如果它不能适应屏幕大小。

绿色区域:页面切换可以使用屏幕底部的绿色按钮或通过滚动ViewPager来完成。

问题是:这种行为可以使用ViewPager实现吗?还是应该使用Fragments?如果使用Fragment,请问如何使用滑动手势实现页面切换?如果使用ViewPager,则如何添加内部滚动并如何使用底部按钮进行控制?

非常感谢您的帮助!


如果这些表格/网格需要在X轴上可滚动(填充整个宽度),那么我不知道你如何实现,因为你将无法决定哪个小部件应该被允许滚动。如果表格/网格只能垂直滚动,则使用ViewPager。 - user
实际上我偶然发现了以下链接:https://dev59.com/wGw05IYBdhLWcg3w9mdW,人们在那里说这是可能的,我从未尝试过,所以我打开了这个问题来看看人们的意见,也许能得到更好的想法。 - Emil Adz
2个回答

7
我认为这可以通过使用不可滑动的非Swipeable ViewPager 来解决。没有办法让视图页和底层的Fragment响应滑动手势。禁用ViewPager中滑动的方法是:
  1. onTouchEvent() - 返回false
  2. onInterceptTouchEvent() - 返回false
请参考这篇SO问题以获取更多有关如何实现此功能的信息。
接下来,您需要在每个页面保持器中使用Fragments。因此,我们正在构建以下布局:

在父活动中,实例化一个FragmentPagerAdapter,并添加带有标签的选项卡:

活动变化

@Override
protected void onCreate(final Bundle saveInstanceState) {
    final FragmentPagerAdapter myTabAdapter = new MyFragmentPagerAdapter(
            <Your ViewPager View>, <Your activity context, this>);
    myTabAdapter.addTab(getActionBar().newTab(), "YOUR TAG", "Your Title");
    // etc...
}

这为我们提供了上面图表的框架。一个包含ViewPager和底层标签的托管活动。接下来是将Fragment(包含您的表格)放入各自的选项卡中。这由FragmentPagerAdapter实现处理:

片段适配器(活动的内部类):

private class MyFragmentPagerAdapter extends FragmentPagerAdapter implements
        ActionBar.TabListener, ViewPager.OnPageChangeListener {

    /**
     * Constructs a pager adapter to back a {@link ViewPager}.
     * 
     * @param pager
     *            The {@link ViewPager} widget.
     * @param activityContext
     *            The context the widget is being added under.
     */
    public SpotMenuFragmentPagerAdapter(final ViewPager pager,
            final Context activityContext) {
        super(getFragmentManager());
        pager.setAdapter(this);
        this.context = activityContext;
    }

    /**
     * Adds a tab to the hosting activity action bar.
     * 
     * @param newTab
     *            The tab to add.
     * @param tag
     *            The tab tag for id purposes.
     * @param label
     *            The label of the tab displayed to the user.
     */
    public void addTab(final ActionBar.Tab newTab, final String tag,
            final String label) {
        newTab.setTag(tag);
        newTab.setText(label);
        newTab.setTabListener(this);
        getSupportActionBar().addTab(newTab);
    }

    /**
     * This is where you do the work of building the correct fragment based
     * on the tab currently selected.
     * 
     * @see FragmentPagerAdapter#getItem(int)
     */
    @Override
    public Fragment getItem(final int position) {
        final Tab tab = getActionBar().getTabAt(position);
        if ("MY TAG".equals(tab.getTag().toString()) {
            // instantiate the fragment (table) for "MY TAG"
        } else {
            // instantiate something else...
        }
    }

    /**
     * One fragment per tab.
     * 
     * @see android.support.v4.view.PagerAdapter#getCount()
     */
    @Override
    public int getCount() {
        return getSupportActionBar().getTabCount();
    }

    /**
     * @see ViewPager.OnPageChangeListener#onPageScrollStateChanged(int)
     */
    @Override
    public void onPageScrollStateChanged(final int arg0) {
        // No-op.
    }

    /**
     * @see ViewPager.OnPageChangeListener#onPageScrolled(int, float, int)
     */
    @Override
    public void onPageScrolled(final int arg0, final float arg1,
            final int arg2) {
        // No-op.
    }

    /**
     * @see ViewPager.OnPageChangeListener#onPageSelected(int)
     */
    @Override
    public void onPageSelected(final int position) {
        getSupportActionBar().setSelectedNavigationItem(position);
    }

    /**
     * @see TabListener#onTabSelected(app.ActionBar.Tab,
     *      app.FragmentTransaction)
     */
    @Override
    public void onTabSelected(final Tab tab, final FragmentTransaction ft) {
        viewPager.setCurrentItem(tab.getPosition());
    }

    /**
     * @see TabListener#onTabUnselected(ActionBar.Tab,
     *      app.FragmentTransaction)
     */
    @Override
    public void onTabUnselected(final Tab tab, final FragmentTransaction ft) {
        // No-op.
    }

    /**
     * @see TabListener#onTabReselected(ActionBar.Tab,app.FragmentTransaction)
     */
    @Override
    public void onTabReselected(final Tab tab, final FragmentTransaction ft) {
        // No-op.
    }
}

希望到此为止,我们已经有了一个托管“不可横向滑动”的视图翻页器的活动,并且通过位于标题下方(或旁边,具体取决于屏幕大小)的选项卡栏机制来切换选项卡。从这一点出发,我相信您可以自定义以将选项卡栏替换为一些导航箭头。

注意:很多信息都是凭记忆写成的,但希望我能够传达我会怎样处理这个问题的要点。

更新

针对更新后的问题:您可以将选项卡设置为任意视图。相应地设置TabSpec即可。抱歉我自己没有使用过。


实际上,你所提到的滑动问题已经有解决方案了,可以看看这篇文章:https://dev59.com/wGw05IYBdhLWcg3w9mdW,我还没有检查过。但是如果我使用ViewPager,并且没有操作栏,那么我该如何将页面切换按钮放在屏幕底部并自定义它们呢? - Emil Adz
@EmilAdz - 这里有一个非操作栏示例 - BrantApps
“FragmentStatePagerAdapter”和“FragmentPagerAdapter”的区别是什么? - Emil Adz
那么对于我的情况(最多4个片段),使用FragmentPagerAdapter会更好(从性能角度来看)? - Emil Adz
我仍在努力解决水平交换的问题,但是你对FragmentViewPager的信息性回答帮助我在这个屏幕上做了很多工作,所以赏金归你。谢谢。 - Emil Adz
显示剩余2条评论

3
您需要使用HorizontalScrollView,其中它将包含一个LinearLayout,而Linear将包含您的各个元素。
XML应该如下所示:
 <HorizontalScrollView
        android:id="@+id/horizontal_scroll_parent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="horizontal"
        android:scrollbarStyle="outsideInset">

       <LinearLayout android:id="@+id/content_scroll"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="horizontal"
                android:gravity="center_vertical" />

</HorizontalScrollView>

1
那是错误的方法。使用Fragments而不是需要1秒钟加载的过载布局。 - Orri

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