web-dev-qa-db-fra.com

ScrollView désactiver le focus focus

J'ai un formulaire de saisie simple; c'est un LinearLayout vertical avec EditTexts à l'intérieur d'un ScrollView.

<ScrollView Android:layout_width="fill_parent"
    Android:layout_height="wrap_content">
    <LinearLayout Android:layout_width="fill_parent"
            Android:layout_height="fill_parent"
            Android:orientation="vertical">
            <LinearLayout Android:layout_width="fill_parent"
                  Android:layout_height="wrap_content"
                  Android:padding="10dip"
                  Android:gravity="center_vertical"
                  Android:orientation="horizontal">
                  <TextView style="@style/Text"
                         Android:text="Name"/>
                  <EditText style="@style/EditBox"/>
            </LinearLayout>
            <View style="@style/Divider"/>
            <LinearLayout Android:layout_width="fill_parent"
                  Android:layout_height="wrap_content"
                  Android:padding="10dip"
                  Android:gravity="center_vertical"
                  Android:orientation="horizontal">
                  <TextView style="@style/Text"
                         Android:text="Password"/>
                  <EditText style="@style/EditBox"/>
            </LinearLayout>               
            ... 
     </LinearLayout>
</ScrollView>

Lorsque l'utilisateur fait défiler le formulaire, il déplace automatiquement son focus sur le texte visible EditText. Il est possible de désactiver un tel comportement et de toujours rester concentré sur le texte d'édition actuellement sélectionné au toucher?

Je comprends que cela peut être une fonctionnalité, mais je dois la désactiver.

Merci!

20
AlexKorovyansky

Je pensais juste que je partagerais ma solution à cela. Même si certains commentaires de l'autre réponse indiquent que vous ne pouvez pas remplacer ce comportement, ce n'est pas vrai. Ce comportement cesse dès que vous substituez la méthode onRequestFocusInDescendants(). Créez simplement votre extension ScrollView pour cela:

public class NonFocusingScrollView extends ScrollView {

  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
  protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
    return true;
  }

}

Et tu as fini. La ScrollView ne dérangera plus votre attention.

45
dmon

J'ai eu un tel problème aussi. La seule façon qui m’a aidé est d’allonger la vue par défilement et de remplacer

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

ou

@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
    return true;
}

mais pour surcharger la méthode ViewGroup.requestChildFocus(View child, View focused) comme suit:

    @Override
    public void requestChildFocus(View child, View focused) {
        // avoid scrolling to focused view
        // super.requestChildFocus(child, focused);
    }
14
rus1f1kat0R

Ce qui a fonctionné pour moi a été la combinaison des réponses de @ dmon et de @ waj.

Ne remplacer que onRequestFocusInDescendants() fonctionnait bien lorsque je ne traitais qu'avec EditTexts à l'intérieur de ScrollView, mais lorsque j'ai commencé à ajouter plusieurs types de vues, cela ne fonctionnait pas très bien.

Seule la substitution de getFocusables() ne fonctionnait pas du tout.

Remplacer à la fois onRequestFocusInDescendants() ET getFocusables() semble fonctionner à merveille dans tous les scénarios.

public class FixedFocusScrollView extends ScrollView {

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

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

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

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

  @Override
  protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
    return true;
  }

}
7
Hunter S

J'ai essayé toutes les solutions publiées ici, mais cela ne fonctionnait pas avec certaines versions d'Android ou causait des problèmes tels que le basculement entre le mode tactile et le mode non tactile (lorsque vous cliquez sur les boutons ou utilisez le trackpad).

J'ai finalement trouvé que le remplacement de la méthode getFocusables avait fait l'affaire:

public class FixedFocusScrollView extends ScrollView {

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

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

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

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

}
7
waj

Essayez de couper le problème de la source ( edit: i.e. déplacez-le dans un fichier XML).

Premièrement, il doit y avoir un élément focalisable pour que cela se produise. Faites en sorte que tous les éléments focalisables contenus dans cette liste défilent en éléments non focalisables. Rendez-les accessibles après que la vue soit gonflée et visible.

Android:focusable="false"
Android:focusableInTouchMode="false"
3
valera

J'ai trouvé une autre solution facile qui fonctionne pour mon problème.

J'ai un ScrollView avec un EditText en haut, et après cela, une grande liste de TextViews, RatingBars et Boutons. Les boutons lancent AlertDialogs et lorsqu'ils apparaissent, le ScrollView se place en haut de la page, vers le texte d'édition qui est toujours actif.

Pour le résoudre, j'ai défini dans la méthode onClick de l'Activity requestFocusFromTouch () à la vue sur laquelle vous avez cliqué (dans ce cas, le Button).

public void onClick(View v) {
    v.requestFocusFromTouch();
    ...
}

Alors maintenant, lorsque je clique sur un bouton, le ScrollView se déplace et que ce bouton est placé au centre de l'écran, c'est exactement ce que je voulais.

J'espère que ça aide.

1
Hugo

Cela m’est arrivé aujourd’hui. En fait, j’ajoutais une vue par programme entre certaines vues existantes et Scroll était automatiquement déplacé pour focaliser cette vue. Ce que je viens de faire est le suivant:

container.setFocusable( false );
0
Reinherd

Pour un tel comportement, utilisez nextFocusUp et nextFocusDown.

<EditText
    Android:id="@+id/my_edit_text"
    Android:nextFocusDown="@id/my_edit_text"
    Android:nextFocusUp="@id/my_edit_text"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content">
</EditText>
0
pawelzieba