【问题标题】:Scrolling vertically and horizontally in Android在Android中垂直和水平滚动
【发布时间】:2014-03-01 14:38:21
【问题描述】:

我有一个RelativeLayout (params = MatchParent,MatchParent) 作为我的内容视图。

RelativeLayout 包含一个 ScrollView(params=Wrap_Content, Wrap_Content)。

ScrollView 然后包含一个LinearLayout(无参数,设置垂直方向)。

我正在向LinearLayout 添加“myrows”。

每个 myrow 由另一个 LinearLayout(无参数,水平方向)组成,其中包含一个 SpannableString,其中包含等间距/填充的数字。

结果是一个可垂直滚动的表格,看起来还不错。问题是,如果我在较小的设备上运行它,SpannableStrings 会延伸到屏幕之外。

在较小的屏幕上,我希望文本足够大以便阅读,因此我还需要能够水平滚动以查看超出屏幕的SpannableString 部分。我已经尝试了几个解决方案。一种是将垂直的ScrollView 放入水平的ScrollView 并捕获xy 等……但人们提到这很危险。我不希望字符串换行。我不能使用保管箱等...来显示超出屏幕的值。它必须是一个平面表,文本足够大,可以阅读,我无法消除任何字符串长度。

我可以将它改为水平的ScrollView 并放置一个向上/向下翻页按钮,但它不会像现在那样流畅。我可以将ListView 放在水平的ScrollView 中并能够双向滚动吗?

对此还有其他想法吗?我可以在底部放置一个滚动条,它可以水平滚动屏幕,它只捕捉您对滚动条本身的手指触摸吗?

谢谢!

【问题讨论】:

  • 如果它只是一堆文本,那么听起来你可以使用 textView 并只使用 wrap_content。试图画一些看起来像桌子的东西?那为什么不使用 ListView 呢?您能否详细介绍一下您想要的结果?
  • 我想要的结果是在我需要显示一个大表格的设备屏幕上,就像使用 msexcel。桌子太宽,不适合较小的设备。我希望能够水平滑动视图以查看表格的其余部分,同时仍然能够上下滚动,因为有超过 100 行。行是动态添加的。就像我上面所说的,这些行太宽了,无法放在较小设备的屏幕上。我不希望行环绕(即到达屏幕的末尾然后转到新行),它们必须离开屏幕。
  • 想象一下使用 msexcel,单元格一直到 AX 列都是满的,显然那不在屏幕上,但是您可以向右滚动以查看所有数据,这就是我需要做的。
  • 好的,我尝试将 ListView 放在 Horizo​​ntalScrollView 中。它似乎工作。但是 ListView 的宽度仅与列表视图中的第一行一样宽,这对我来说不是问题,因为我所有的行都是相同的宽度。
  • 我想出了如何使用自定义 GridView 来做到这一点,它可以在不破坏 ListAdapter 和垂直滚动功能的情况下进行水平滚动。

标签: android android-layout


【解决方案1】:

我终于找到了一个很好的解决方案。使用以下覆盖创建自定义 gridView。我还创建了一个跟随 gridView 滚动的滚动标题。

@Override
public boolean onInterceptTouchEvent (MotionEvent ev) {
    getMaxLeftScroll();
    myLastX = ev.getX();
    myLastY = ev.getY();
    return super.onInterceptTouchEvent(ev);
}


@Override
public boolean onTouchEvent(final MotionEvent ev){

    final int action = ev.getAction();
    final float x;
    final float y;

    switch (action) {
        case MotionEvent.ACTION_MOVE:
            // This handles Scrolling only.
            x = ev.getX();
            y = ev.getY();

            final int deltaX = (int) (myLastX - x);
            final int deltaY = (int) (myLastY - y);

            if(Math.abs(deltaX) > Math.abs(deltaY)) {

                if( (iCurrentLeftScroll+deltaX) > 0 &&
                        iCurrentLeftScroll+deltaX < iMaxLeftScroll) {
                    scrollBy(deltaX, 0);
                    //Listener and call the method here to scroll the header
                    mScrollChangeListener.onGridViewScrolled(deltaX);

                    iCurrentLeftScroll+=deltaX;
                }  //Scrolled by some value

                // Close to right edge within 10? Smooth Scroll remaining small distance if not already there
                else if(deltaX > 0 && (iCurrentLeftScroll<iMaxLeftScroll)) {
                    if ((iMaxLeftScroll - iCurrentLeftScroll) < 10) {
                        scrollBy(iMaxLeftScroll-iCurrentLeftScroll, 0);
                        mScrollChangeListener.onGridViewScrolled(iMaxLeftScroll-iCurrentLeftScroll);
                        iCurrentLeftScroll = iMaxLeftScroll;
                    }
                }
                // Close to left edge within 30? Smooth Scroll remaining small distance if not already there
                else if(deltaX < 0 && (iCurrentLeftScroll>0)) {
                    if ((iCurrentLeftScroll) < 10) {
                        scrollBy(iCurrentLeftScroll*-1, 0);
                        mScrollChangeListener.onGridViewScrolled(iCurrentLeftScroll*-1);
                        iCurrentLeftScroll = 0;
                    }
                }

                //left and right are subjective
                if(iCurrentLeftScroll == iMaxLeftScroll)
                    iScrollStatus = SCROLLED_FULL_LEFT;
                if(iCurrentLeftScroll == 0)
                    iScrollStatus = SCROLLED_FULL_RIGHT;
                if( (iCurrentLeftScroll > 0) && (iCurrentLeftScroll < iMaxLeftScroll) )
                    iScrollStatus = 0;
                Log.d(TAG," Scroll Status " + String.valueOf(iScrollStatus) );
                Log.d(TAG," MaxLeftScroll " + String.valueOf(iMaxLeftScroll) );
                Log.d(TAG," Current Left Scroll " + String.valueOf(iCurrentLeftScroll) );

            }

            myLastX = x;
            myLastY = y;

            break;
    }
    return super.onTouchEvent(ev);
}

【讨论】: