Question Arrêtez ScrollView de défilement automatique à un EditText


Semble être un problème commun sans une excellente solution que j'ai trouvée. Le but est d'arrêter un ScrollView du défilement automatique à un EditText (ou toute vue à ce sujet) qui a le focus.

Vous avez un tas de vues (Buttons, TextViews, etc.) dans un ScrollView, dont l'un est un EditText. En cliquant sur dire un bouton dans le ScrollView, la ScrollView défile vers le bas EditText (son hors écran). Cela n'est pas souhaitable, car il y a d'autres éléments que vous ne souhaitez pas faire défiler hors de l'écran.

Maintenant, je peux empêcher que cela ne se produise lorsque l’écran affiche d’abord d’autres éléments ScrollView. Cependant, le problème général existe toujours. L'utilisateur fait défiler manuellement vers le EditText, entre des nombres, puis fait défiler vers le haut (EditText hors écran maintenant), ils cliquent sur un bouton dans le ScrollView, et devine quoi? le ScrollView fait défiler jusqu'à ce sacré EditText.

Je pense à étendre le ScrollView et substituer certaines des méthodes là-bas comme findFocusableViewInBounds, mais j'ai le sentiment que je vais me retrouver avec plus d'ennuis.

S'il vous plait aidez si vous le pouvez.

J'ai joué avec des choses comme avoir une hauteur de 0 EditText au sommet de ma ScrollView, en ajoutant les propriétés de l'élément Next Focusable aux autres éléments du ScrollView, etc. Je suppose qu'un "hack" pourrait être EditText perdre le focus lorsque le clavier virtuel ou manuel est caché ou quelque chose.


38
2018-05-30 12:38


origine


Réponses:


Après avoir lutté contre ce problème pendant un certain temps, j'ai trouvé une solution qui semble fonctionner sans être trop laide. Tout d'abord, assurez-vous que peu importe ViewGroup (directement) contient votre EditText a descendantFocusability réglé sur "Avant les descendants" focusable mis à "vrai" et focusableInTouchMode réglé sur "true" Ce ne sera pas le ScrollView lui-même, mais la disposition à l’intérieur où vous avez vos différentes vues. Ensuite ajoutez un onTouchListener à ton ScrollView qui supprime le focus de la EditText quand il est touché, comme ça:

ScrollView scroll = (ScrollView)findViewById(R.id.scrollView1);
scroll.setOnTouchListener(new OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (myEditText.hasFocus()) {
            myEditText.clearFocus();
        }
        return false;
    }
});

Dites-moi si cela ne résout pas le problème. Ce qui devrait arriver, c'est que la mise en page se concentre plutôt que la EditText, donc aucun défilement ne devrait avoir lieu.


33
2018-06-26 19:56



Il suffit de créer une vue vide en haut de linearlayout

<View android:layout_width="fill_parent" android:id="@+id/focus_view" android:layout_height="0dp" android:focusable="true" android:focusableInTouchMode="true"><requestFocus/></View>

Une seule ligne résout le problème


16
2017-07-26 13:01



J'ai eu le même problème. Il y a un truc que j'utilise pour résoudre ce problème:

public void onClick(View v) {
    button.requestFocusFromTouch(); //prevents from loosing focus and scrolling view down
    ....
}

9
2018-05-30 14:01



Le problème ne réside pas dans le code Java, mais dans le code du manifeste.

Dans votre AndroidManifest.xml, ajoutez un attribut à l'activité:

        <activity android:name=".MyActivity" android:windowSoftInputMode="adjustPan"> </activity>

8
2018-05-28 15:15



En ajoutant 2 paramètres dans:

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

Dans quelle disposition principale est là.

<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">

Par ça EditText ne sera pas focalisé automatiquement.


5
2018-06-23 05:57



Voici ce que j'ai fait

 <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>

La raison en est que dans de tels cas, vous devez rendre toutes les autres vues focalisables à l’intérieur de la android:focusable="true" et alors <requestFocus></requestFocus>  . Cela devrait fonctionner à chaque fois IMO


4
2017-09-11 05:45



thomas88wp réponse, https://stackoverflow.com/a/6486348/528746 travaillé pour moi Mais j'ai eu deux problèmes: 1. En faisant défiler, je voulais cacher le clavier
2. J'avais beaucoup de vues EditText et je ne voulais pas l'écrire pour chacune d'entre elles
(Je getActivity () car j'écris ceci dans un fragment et non une activité)

    ScrollView scroll = (ScrollView)view.findViewById(R.id.layout_scroll);
    scroll.setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // Check if the view with focus is EditText
            if (getActivity().getCurrentFocus() instanceof EditText)
            {
                EditText ed = (EditText)getActivity().getCurrentFocus();
                if (ed.hasFocus()) {

                    // Hide the keyboard
                    InputMethodManager inputManager = (InputMethodManager)
                            getActivity().getSystemService(Context.INPUT_METHOD_SERVICE); 
                    inputManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
                            InputMethodManager.HIDE_NOT_ALWAYS);
                    // Clear the focus
                    ed.clearFocus();
                }
            }
            return false;
        }

    });

2
2017-08-14 07:06



Mon correctif à ce bug le plus horrible, (notant que ceci est pré API11 seulement où ils ont modifié la méthode de fling pour ne pas être stupide).

L'ancienne méthode de fling trouve le focus suivant sur lequel elle ira .. ce qui n'est pas vraiment utile. Les autres versions de cette classe ne fonctionnent pas vraiment car elles arrêtent de se concentrer lorsque l'utilisateur traverse véritablement le formulaire à partir du clavier.

public class NonFocusingScrollView extends ScrollView {

    private boolean mBlockRequestFocusOnFling = false;

    public NonFocusingScrollView(Context context) {
        super(context);
    }

    public NonFocusingScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public NonFocusingScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public ArrayList<View> getFocusables(int direction) {
        if(mBlockRequestFocusOnFling)
            return new ArrayList<View>();
        return super.getFocusables(direction);
    }

    @Override
    public void requestChildFocus(View child, View focused) {
        if(!mBlockRequestFocusOnFling)
        super.requestChildFocus(child, focused);
    }


    @Override
    public void fling(int velocityY) {
        mBlockRequestFocusOnFling = true;
        super.fling(velocityY);
        mBlockRequestFocusOnFling = false;
    }
}

2
2017-12-04 17:55



Nous pouvons écrire un ScrollView personnalisé et remplacer le onScrollChanged méthode et effacer le focus de la vue ciblée et éventuellement masquer le clavier.

@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    View v = getFocusedChild();
    if (v != null) {
        InputMethodManager imm = (InputMethodManager) getContext()
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
        v.clearFocus();
    }
    super.onScrollChanged(l, t, oldl, oldt);
}

1
2017-12-30 23:56



Une autre version du code de thomas88wp:

ScrollView scroll = (ScrollView)getActivity().findViewById(R.id.scrollView_addNewBill);
    scroll.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View arg0, MotionEvent arg1) {        
            View focussedView = getCurrentFocus(); 
            if( focussedView != null ) focussedView.clearFocus();
                
            return false;
    }
});

1
2018-04-04 13:17