androidandroid-layoutandroid-widgetandroid-scrollviewandroid-scroll

There is no way to prevent ScrollView from automatically scrolling when TextView is focused?


If I click text2 for the first time or whenever I click text2 after clicking text1, the ScrollView seems to be scrolling text2 to the top. If I put android:descendantFocusability="blocksDescendants" in the LinearLayout this scrolling does not happen, but I cannot select the text.

What I want is simple: I do not want this auto-scrolling. Is it IMPOSSIBLE to disable this behaviour of ScrollView and the I would have to create my own scroll view class from scratch? If it is impossible, please write that as an answer, so I could give it up.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            <TextView
                    android:text="I am text 1. Click me."
                    android:textColor="@color/black"
                    android:textIsSelectable="true"
                    android:background="#FF0000"
                    android:layout_width="match_parent"
                    android:layout_height="400dp"/>
            <TextView
                    android:text="I am text 2. Click me."
                    android:textIsSelectable="true"
                    android:background="#00FF00"
                    android:textColor="@color/black"
                    android:layout_width="match_parent"
                    android:layout_height="1000dp"/>
        </LinearLayout>
</ScrollView>

enter image description here


Solution

  • You can make a subclass of ScrollView and override the protected method: computeScrollDeltaToGetChildRectOnScreen(Rect rect) and return 0 to disable the autoscrolling effect.

    computeScrollDeltaToGetChildRectOnScreen

    Compute the amount to scroll in the Y direction in order to get a rectangle completely on the screen (or, if taller than the screen, at least the first screen size chunk of it).

    Kotlin Example:

    class CustomScrollView : ScrollView {
        constructor(context: Context?) : super(context) {}
        constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {}
        constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {}
    
        override fun computeScrollDeltaToGetChildRectOnScreen(rect: Rect): Int {
            return 0
        }
    }
    

    Xml Usage:

    <?xml version="1.0" encoding="utf-8"?>
    <mypackagename.com.CustomScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView
                android:text="I am text 1. Click me."
                android:textColor="@color/black"
                android:textIsSelectable="true"
                android:background="#FF0000"
                android:layout_width="match_parent"
                android:layout_height="400dp"/>
            <TextView
                android:text="I am text 2. Click me."
                android:textIsSelectable="true"
                android:background="#00FF00"
                android:textColor="@color/black"
                android:layout_width="match_parent"
                android:layout_height="1000dp"/>
        </LinearLayout>
    </mypackagename.com.CustomScrollView>