Stop ScrollView from auto-scrolling to an EditText

后端 未结 21 1289
长发绾君心
长发绾君心 2020-11-30 23:17

Seems to be a common problem without a great solution that I have found. Goal is to stop a ScrollView from auto-scrolling to an EditText (or any vi

相关标签:
21条回答
  • 2020-11-30 23:30

    The issue is not on the java code, but on the manifest code.

    In your AndroidManifest.xml add an attribute to the Activity:

            <activity android:name=".MyActivity" android:windowSoftInputMode="adjustPan"> </activity>
    
    0 讨论(0)
  • 2020-11-30 23:30

    By adding 2 parameters in:

    android:focusable="true"
    android:focusableInTouchMode="true"
    

    In which Main layout is there.

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/layMain"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/background"
        android:focusable="true"
        android:focusableInTouchMode="true">
    

    By this EditText will not be auto focused.

    0 讨论(0)
  • 2020-11-30 23:30

    For me, it didn't work to override ScrollView onTouch. Also did not work android:descendantFocusability="beforeDescendants" android:focusableInTouchMode="true" This and another mentioned solutions only worked for the first time - only when EditText is not selected, but once you select it, scrollview autoscrolls again.

    Because I was already written a code to hide a keyboard when touching other views, I just added two lines of code and it worked like a champ:

    public static void setupUI(final Activity activity, final View view) {
        //view is the parent view in your layout
        OnTouchListener mTouchListener = new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                try {
                    View vFocused = null;
                    vFocused = activity.getCurrentFocus();
    
                    if (vFocused != null) {
                        hideSoftKeyboard(activity, v);
                        if (vFocused instanceof EditText) {
                            vFocused.clearFocus();//this is the trick to avoid ScrollView autoscroll
                        }
                    }
                } catch (Exception e) {
                }
                return false;
            }
        };
    
        // Set up touch listener for non-text box views to hide keyboard.
        if (!(view instanceof EditText) && !(view instanceof ViewGroup)) {
            view.setOnTouchListener(mTouchListener);
        }
    
        // If a layout container, iterate over children and seed recursion.
        if (view instanceof ViewGroup) {
            view.setOnTouchListener(mTouchListener);
            for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
                View innerView = ((ViewGroup) view).getChildAt(i);
                setupUI(activity, innerView);
            }
        }
    }
    public static void hideSoftKeyboard(Context context, View v) {
        InputMethodManager inputMethodManager = (InputMethodManager) context
                .getSystemService(Activity.INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
    }
    

    also added this in root view:

    android:descendantFocusability="beforeDescendants" android:focusableInTouchMode="true"
    

    Maybe its not really nice solution, but its working.

    0 讨论(0)
  • 2020-11-30 23:31

    Only this code works for me:

    public static void preventScrollViewFromScrollingToEdiText(ScrollView view) {
        view.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
        view.setFocusable(true);
        view.setFocusableInTouchMode(true);
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                v.requestFocusFromTouch();
                return false;
            }
        });
    }
    

    All credits go to this original answer.

    0 讨论(0)
  • 2020-11-30 23:32

    Here is what I did

     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent" style="@style/measurementTableRowStyle"
        android:focusable="true" android:layout_height="fill_parent">
        <requestFocus></requestFocus>
        <LinearLayout android:id="@+id/linearLayout1"
            android:orientation="horizontal" android:layout_width="fill_parent"
            android:layout_height="wrap_content">
            <TextView android:id="@+id/desc_text" android:text="Value : "
                style="@style/attributeNameTextStyle" android:layout_width="wrap_content"
                android:focusable="true" android:layout_height="wrap_content">
                <requestFocus></requestFocus>
            </TextView>
    
            <TextView style="@style/attributeValueStyle" android:id="@+id/value_text"
                android:text="TextView" android:layout_width="wrap_content"
                android:layout_height="wrap_content"></TextView>
        </LinearLayout>
    

    The reason is in such cases you have to make all other views focus-able inside the scrollview by an explicit android:focusable="true" and then <requestFocus></requestFocus> . This should work everytime IMO

    0 讨论(0)
  • 2020-11-30 23:32

    My solution is below, to trace the source code and override some function to stop auto scrolling by focused item.

    You can check if the focusedView is TextView or its child is TextView, by using focusedView.findViewById(R.id.textview_id_you_defined) != null or focusedView instanceof TextView == true.

    public class StopAutoFocusScrollView extends ScrollView {
    
        private View focusedView;
        private ScrollMonitorListener listener;
    
        public interface ScrollMonitorListener {
            public boolean enableScroll(View view);
        }
        public StopAutoFocusScrollView(Context context) {
            super(context);
        }
    
        public StopAutoFocusScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public StopAutoFocusScrollView(Context context, AttributeSet attrs, 
               int defStyle) {
            super(context, attrs, defStyle);
        }
    
        public void setScrollMonitorListener(ScrollMonitorListener listener) {
            this.listener = listener;
        }
    
        @Override
        public void requestChildFocus(View child, View focused) {
            focusedView = focused
            super.requestChildFocus(child, focused);
        }
        //flow : requestChildFocus -> scrollToChild -> scrollBy
        //Therefore, you can give listener to determine you want scroll to or not
        @Override
        public void scrollBy(int x, int y) {
            if (listener == null || listener.enableScroll(focusedView)) {
                super.scrollBy(x, y);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题