75

I am using a TableLayout. I need to have both horizontal and vertical scrolling for this layout. By default I am able to get vertical scrolling in the view but horizontal scrolling is not working.

I am using Android SDK 1.5 r3. I have already tried android:scrollbars="horizontal".

I have read on some forums that in the cupcake update, horizontal scrolling is possible.

How can I make my layout scroll in both directions?

Michael Celey
  • 12,395
  • 6
  • 55
  • 61
mudit
  • 24,821
  • 31
  • 86
  • 132

8 Answers8

143

I was able to find a simple way to achieve both scrolling behaviors.

Here is the xml for it:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent" android:layout_height="fill_parent"
    android:scrollbars="vertical">

    <HorizontalScrollView 
        android:layout_width="320px" android:layout_height="fill_parent">

        <TableLayout
            android:id="@+id/linlay" android:layout_width="320px"
            android:layout_height="fill_parent" android:stretchColumns="1"
            android:background="#000000"/>

    </HorizontalScrollView>

</ScrollView>
deej
  • 1,653
  • 1
  • 26
  • 26
mudit
  • 24,821
  • 31
  • 86
  • 132
  • Horizontal scrolling is going good... but there are no visible horizontal scroll bars.. how can we do that..? – Amit Mar 11 '10 at 13:01
  • 4
    warning: this may be a bad practice. See this question/answer: http://stackoverflow.com/questions/4490821/scrollview-inside-scrollview#4492050 – Pedro Loureiro Jan 17 '11 at 23:59
  • 7
    @PedroLoureiro actually, the question in the link you posted refers to combining `ScrollView` with `ListView`. This is because `ListView` has a ton of optimizations in it that do not play nicely with a surrounding `ScorollView`. The answer posted here is not using `ListView`, so the linked argument is irrelevant. – David Wasser Sep 28 '15 at 16:21
  • Any alternative for sticky columns and rows? Scrolling is not smooth with sticky views – Aditi Parikh Sep 01 '17 at 11:07
  • 2
    I thought this was a good idea, but it actually doesn't allow diagonal scroll - you can only scroll one axis at a time.. which is kind of bad – Maverick Meerkat Oct 17 '18 at 15:29
  • can u attach screenshot of ur output. – pallavi richhariya Dec 31 '18 at 09:28
  • 1
    Diagonal scrolling does not work this way – ievgen Jun 19 '21 at 04:23
  • To show both vertical and horizontal scrollbars, you can use this way https://stackoverflow.com/a/69925768/5426065 – tuantv.dev Nov 11 '21 at 09:15
  • @ievgen for smooth diagonal scroll see my answer https://stackoverflow.com/a/69932128/11880323 – cmak Feb 23 '22 at 10:37
10

its too late but i hope your issue will be solve quickly with this code. nothing to do more just put your code in below scrollview.

<HorizontalScrollView
        android:id="@+id/scrollView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent">

      <ScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            //xml code
      </ScrollView>
</HorizontalScrollView>
Morteza Jalambadani
  • 2,016
  • 6
  • 21
  • 33
Ashish Tikarye
  • 814
  • 8
  • 11
2

In this post Scrollview vertical and horizontal in android they talk about a possible solution, quoting:

Matt Clark has built a custom view based on the Android source, and it seems to work perfectly: http://blog.gorges.us/2010/06/android-two-dimensional-scrollview

Beware that the class in that page has a bug calculating the view's horizonal width. A fix by Manuel Hilty is in the comments:

Solution: Replace the statement on line 808 by the following:

final int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.leftMargin + lp.rightMargin, MeasureSpec.UNSPECIFIED);
Community
  • 1
  • 1
neteinstein
  • 17,327
  • 11
  • 90
  • 120
2

Since other solutions are old and either poorly-working or not working at all, I've modified NestedScrollView, which is stable, modern and it has all you expect from a scroll view. Except for horizontal scrolling.

Here's the repo: https://github.com/ultimate-deej/TwoWayNestedScrollView

I've made no changes, no "improvements" to the original NestedScrollView except for what was absolutely necessary. The code is based on androidx.core:core:1.3.0, which is the latest stable version at the time of writing.

All of the following works:

  • Lift on scroll (since it's basically a NestedScrollView)
  • Edge effects in both dimensions
  • Fill viewport in both dimensions
deej
  • 1,653
  • 1
  • 26
  • 26
1

The problem with most of the answers here is that they only achieve vertical or horizontal scroll, BUT not diagonal (horizontal AND vertical at the same time).

The easiest way I've found to get it working is:

  • Create two new classes extending HorizontalScrollView and ScrollView (use whatever name, like "ScrollViewX" and "ScrollViewY").
  • Make a new XML and use the class extending HorizontalScrollView inside the one extending ScrollView.
  • Inside the two classes, override their onTouch methods to always return false (override and use performClick() too, for accessibility reasons).
  • Use a GestureDetector and update the scrolling of both classes with it.

Creating the classes isn't really required, since you could just set an onTouch listener for both. But I believe it's better in terms of organization and it may be useful if you require more customizations later.

The only problem I've found is that, since one ScrollView is inside the other, now one of the scrollbars is only going to be visible when you scroll while being on the edge of the view.

A workaround could be: either don't use scrollbars, or make a custom view to replace said scrollbar (you set its size according to the ScrollView size and move it as the scroll is updated).

Note: I tried to describe it as much as I could. If someone needs more details, let me know

cmak
  • 513
  • 1
  • 4
  • 13
1

Use this:

android:scrollbarAlwaysDrawHorizontalTrack="true"

Example:

<Gallery android:id="@+id/gallery"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:scrollbarAlwaysDrawHorizontalTrack="true" />
Michael Celey
  • 12,395
  • 6
  • 55
  • 61
Patel Ekta
  • 596
  • 5
  • 5
0

You can do this by using below code

<HorizontalScrollView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent">
                    <ScrollView
                        android:layout_width="wrap_content"
                        android:layout_height="match_parent">
                        <LinearLayout
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content">
                            
                        </LinearLayout>
                    </ScrollView>
    </HorizontalScrollView>
0

This implementation can always display both horizontal and vertical scrollbars

activity_main.xml

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- vertical scroll view -->
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        android:fadeScrollbars="false"
        android:scrollbarSize="@dimen/scroll_bar_size">

        <!-- horizontal scroll view hidden scroll bar -->
        <HorizontalScrollView
            android:id="@+id/real_horizontal_scroll_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fillViewport="true"
            android:scrollbars="none">

            <!-- content view -->
            <EditText
                android:id="@+id/real_inside_view"
                android:layout_width="wrap_content"
                android:layout_height="match_parent" />
        </HorizontalScrollView>
    </ScrollView>

    <!-- fake horizontal scroll bar -->
    <HorizontalScrollView
        android:id="@+id/fake_horizontal_scroll_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:fadeScrollbars="false"
        android:scrollbarSize="@dimen/scroll_bar_size">

        <!-- fake content view that has width equals the real content view -->
        <View
            android:id="@+id/fake_inside_view"
            android:layout_width="wrap_content"
            android:layout_height="@dimen/scroll_bar_size" />
    </HorizontalScrollView>
</RelativeLayout>

MainActivity.java

    final EditText realInsideView = findViewById(R.id.real_inside_view);
    final HorizontalScrollView realHorizontalSv = findViewById(R.id.real_horizontal_scroll_view);

    final View fakeInsideView = findViewById(R.id.fake_inside_view);
    final HorizontalScrollView fakeHorizontalSv = findViewById(R.id.fake_horizontal_scroll_view);

    realHorizontalSv.setOnScrollChangeListener(new View.OnScrollChangeListener() {
        @Override
        public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
            fakeInsideView.setMinimumWidth(realInsideView.getWidth());
            fakeHorizontalSv.setScrollX(scrollX);
        }
    });
tuantv.dev
  • 78
  • 7