Comment empêcher EditText de se concentrer au démarrage de l'activité dans Android


2874

J'ai un Activitysous Android, avec deux éléments:

  1. EditText
  2. ListView

Lorsque mon Activitydémarre, le a EditTextimmédiatement le focus d'entrée (curseur clignotant). Je ne veux aucun contrôle pour avoir le focus d'entrée au démarrage. J'ai essayé:

EditText.setSelected(false);
EditText.setFocusable(false);

Pas de chance. Comment puis-je convaincre le EditTextde ne pas se sélectionner lui-même au Activitydémarrage?

Réponses:


2593

Excellentes réponses de Luc et Mark mais un bon exemple de code manque. L'ajout de la balise android:focusableInTouchMode="true"et android:focusable="true"de la disposition parent (par exemple LinearLayoutou ConstraintLayout) comme dans l'exemple suivant résoudra le problème.

<!-- Dummy item to prevent AutoCompleteTextView from receiving focus -->
<LinearLayout
    android:focusable="true" 
    android:focusableInTouchMode="true"
    android:layout_width="0px" 
    android:layout_height="0px"/>

<!-- :nextFocusUp and :nextFocusLeft have been set to the id of this component
to prevent the dummy from receiving focus again -->
<AutoCompleteTextView android:id="@+id/autotext"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content"
    android:nextFocusUp="@id/autotext" 
    android:nextFocusLeft="@id/autotext"/>

711
Qu'en est-il de la mise en page parentandroid:focusableInTouchMode="true" !
Muhammad Babar

28
Parfait! Merci ... Une chose à noter est que l'élément factice doit être PLACÉ DROIT AVANT l'élément focalisable !!! J'avais un TextView entre mon mannequin et le EditText et la méthode n'a pas fonctionné!
maddob

25
définir android: focusableInTouchMode = "true" pour la disposition parent était la bonne approche merci @Muhammad Babar
sujith s

7
Excellent code, m'a beaucoup aidé :) Pour essayer de l'améliorer, il en android:focusableInTouchMode="true"couvre android:focusable="true"+ un peu plus, donc dans ce cas, il android:focusable="true"n'est pas nécessaire et peut être supprimé. De plus, la vue factice peut être une vue au lieu d'une présentation linéaire. Cela économise de la puissance de traitement + vous évite certains avertissements. Ainsi, ma recommandation remplace le point de vue factice par<View android:focusableInTouchMode="true" android:layout_width="0px" android:layout_height="0px"/>
Jacob R

20
@PietroRea Android a des comportements ennuyeux de mise au point automatique qui sont intégrés dans le comportement de base de sa structure d'application. Si vous lui dites qu'un texte d'édition relâche ou perd le focus, il décide automatiquement où va le focus. Sans nouvel objet vers lequel le focus doit être transféré, il sélectionne le premier élément pouvant être mis au point dans la mise en page même lorsque cet élément est celui qui vient d'effacer son focus! C'est un peu fou et frustrant, mais il y a peut-être une raison valable pour ce type de comportement.
Mariage Weston

1676

Le problème réel est-il que vous ne voulez tout simplement pas qu'il se concentre du tout? Ou vous ne voulez pas qu'il montre le clavier virtuel suite à la mise au point du EditText? Je ne vois pas vraiment de problème avec le EditTextfocus sur le démarrage, mais c'est certainement un problème d'avoir la fenêtre softInput ouverte lorsque l'utilisateur n'a pas explicitement demandé de se concentrer sur le EditText(et d'ouvrir le clavier en conséquence).

Si c'est le problème du clavier virtuel, consultez la documentation de l' AndroidManifest.xml élément <activité> .

android:windowSoftInputMode="stateHidden" - cachez-le toujours lorsque vous entrez dans l'activité.

ou android:windowSoftInputMode="stateUnchanged"- ne le modifiez pas (par exemple, ne le montrez pas s'il n'est pas déjà affiché, mais s'il était ouvert lors de l'entrée dans l'activité, laissez-le ouvert).


24
pourtant le curseur est toujours dans le premier EditText de la mise en page - même si le clavier n'est pas affiché
martyglaubitz

39
@Anderson: Rien dans la réponse n'implique que cela empêcherait EditTextd'obtenir le focus. Il indique en fait clairement que c'est ainsi que vous empêchez le clavier logiciel IME de s'ouvrir automatiquement sur le focus; car il est plus probable que le plus gros problème soit le clavier virtuel qui surgit de manière inattendue, pas la mise au point elle-même. Si votre problème est lié à la EditTextconcentration réelle, utilisez la réponse de quelqu'un d'autre.
Joe


3
Ne faites pas cela sur une activité avec un appareil photo - cela rompt le timing du flash (ne me demandez pas pourquoi)
Daniel Wilson

1
@Joe, cette question ne concerne pas le masquage du clavier au démarrage. Une telle question a été posée ici stackoverflow.com/questions/18977187/…
user924

1141

Une solution plus simple existe. Définissez ces attributs dans votre disposition parent:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainLayout"
    android:descendantFocusability="beforeDescendants"
    android:focusableInTouchMode="true" >

Et maintenant, lorsque l'activité démarre, cette mise en page principale sera mise en évidence par défaut.

De plus, nous pouvons supprimer le focus des vues enfant lors de l'exécution (par exemple, après avoir terminé l'édition enfant) en redonnant le focus à la disposition principale, comme ceci:

findViewById(R.id.mainLayout).requestFocus();

Bon commentaire de Guillaume Perrot :

android:descendantFocusability="beforeDescendants"semble être la valeur par défaut (la valeur entière est 0). Cela fonctionne simplement en ajoutant android:focusableInTouchMode="true".

Vraiment, nous pouvons voir que l' beforeDescendantsensemble est défini par défaut dans la ViewGroup.initViewGroup()méthode (Android 2.2.2). Mais pas égal à 0.ViewGroup.FOCUS_BEFORE_DESCENDANTS = 0x20000;

Merci à Guillaume.


1
Il est important de définir ces attributs sur le parent direct de la vue, ce qui permet de se concentrer sur la création d'activité, sinon cela ne fonctionnera pas.
tomrozb

4
Juste une solution parfaite. Fonctionne pour les deux: 1.Désactivation de la mise au point automatique, et 2. Désactivation de l'ouverture automatique du clavier virtuel
Rencontrez

Agréable. Il n'a pas besoin d'être un parent direct. Je l'ai mis au niveau racine de la mise en page et cela semble bien fonctionner.
Kurotsuki

@DanielWilson quand voudriez-vous un scrollview comme parent direct d'un edittext?
Mark Buikema

Vous devez travailler avec une entrée logicielle de
Prêt Android

427

La seule solution que j'ai trouvée est:

  • Créer un LinearLayout (je ne sais pas si d'autres types de Layouts fonctionneront)
  • Définissez les attributs android:focusable="true"etandroid:focusableInTouchMode="true"

Et ils EditTextn'obtiendront pas l'attention après le début de l'activité


Facile!! J'ai initialement ajouté ces propriétés à la vue parent, ce qui a échoué, puis je les ai définies dans une autre disposition et j'ai bien fonctionné. Merci!!
Rino

Cela fonctionne également avec ConstraintLayout.
Hawklike

86

Le problème semble provenir d'une propriété que je ne peux voir que dans XML formla disposition.

Assurez-vous de supprimer cette ligne à la fin de la déclaration dans les EditTextbalises XML:

<requestFocus />

Cela devrait donner quelque chose comme ça:

<EditText
   android:id="@+id/emailField"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:inputType="textEmailAddress">

   //<requestFocus /> /* <-- without this line */
</EditText>

78

en utilisant les informations fournies par d'autres affiches, j'ai utilisé la solution suivante:

dans la mise en page XML

<!-- Dummy item to prevent AutoCompleteTextView from receiving focus -->
<LinearLayout
    android:id="@+id/linearLayout_focus"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:layout_width="0px"
    android:layout_height="0px"/>

<!-- AUTOCOMPLETE -->
<AutoCompleteTextView
    android:id="@+id/autocomplete"
    android:layout_width="200dip"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dip"
    android:inputType="textNoSuggestions|textVisiblePassword"/>

dans onCreate ()

private AutoCompleteTextView mAutoCompleteTextView;
private LinearLayout mLinearLayout;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mylayout);

    //get references to UI components
    mAutoCompleteTextView = (AutoCompleteTextView) findViewById(R.id.autocomplete);
    mLinearLayout = (LinearLayout) findViewById(R.id.linearLayout_focus);
}

et enfin, dans onResume ()

@Override
protected void onResume() {
    super.onResume();

    //do not give the editbox focus automatically when activity starts
    mAutoCompleteTextView.clearFocus();
    mLinearLayout.requestFocus();
}

74

Essayez clearFocus () au lieu de setSelected(false). Chaque vue dans Android a à la fois une focalisation et une sélection, et je pense que vous souhaitez simplement effacer la mise au point.


Cela semble prometteur, mais à quel stade du cycle de vie de l'activité doit-il être appelé? Si je l'appelle dans onCreate (), le EditText a toujours le focus. Doit-il être appelé dans onResume () ou dans un autre emplacement? Merci!
Mark

8
J'ai combiné la réponse acceptée avec cette réponse. J'ai appelé myEditText.clearFocus(); myDummyLinearLayout.requestFocus();le onResumede l'activité. Cela a garanti que le EditText ne gardait pas le focus lorsque le téléphone était tourné.
teedyay

71

Les éléments suivants empêcheront edittext de prendre le focus lors de sa création, mais saisissez-le lorsque vous les toucherez.

<EditText
    android:id="@+id/et_bonus_custom"
    android:focusable="false" />

Vous définissez donc focusable sur false dans le xml, mais la clé se trouve dans le java, auquel vous ajoutez l'écouteur suivant:

etBonus.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        v.setFocusable(true);
        v.setFocusableInTouchMode(true);
        return false;
    }
});

Parce que vous retournez faux, c'est-à-dire que vous ne consommez pas l'événement, le comportement de mise au point se déroulera comme d'habitude.


6
Mais cela ne gagnera jamais en concentration à l'avenir, comment arrêter la concentration uniquement pour le début (début de l'activité) ??
Jayesh

1
OnTouchListener est appelé avant les autres actions tactiles. Ainsi, en activant la mise au point au toucher, la mise au point standard se produit au premier contact. Le clavier apparaîtra et tout.
MinceMan

1
Je pense que c'est la meilleure façon de le faire. De plus, le code factice magique xml mumbo-jumbo ci-dessus n'a PAS fonctionné pour un ensemble complexe de textes d'édition ... Si cela fonctionne, je voterai définitivement.
Radu

Mais si vous avez plusieurs textes d'édition, il se concentrera sur le texte d'édition suivant et ouvrira le clavier, il est donc préférable d'ajouter android: windowSoftInputMode = "stateAlwaysHidden" dans le manifeste pour une activité particulière.
Karan sharma

Remarque: sur Android P, le système n'accroche plus la mise au point par défaut. Cela signifie que ce hack n'est pas nécessaire à partir de P.
MinceMan

65

J'avais essayé plusieurs réponses individuellement mais le focus est toujours sur EditText. Je n'ai réussi à le résoudre qu'en utilisant ensemble deux des solutions ci-dessous.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/mainLayout"
  android:descendantFocusability="beforeDescendants"
  android:focusableInTouchMode="true" >

(Référence de Silver https://stackoverflow.com/a/8639921/15695 )

et retirer

 <requestFocus />

à EditText

(Référence de floydaddict https://stackoverflow.com/a/9681809 )


1
J'ai dû ajouter edittext.clearFocus () en plus de ce qui précède pour le faire fonctionner :)
Nav

57

Réponse tardive mais la plus simple, ajoutez simplement ceci dans la disposition parent du XML.

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

Votez si cela vous a aidé! Happy Coding :)


2
a parfaitement fonctionné pour moi. une autre chose à noter est, n'ajoutez pas ces lignes à la vue de défilement. Cela ne fonctionnera pas en mode défilement. Mais fonctionnait parfaitement avec une disposition linéaire.
Karthic Srinivasan

46

Aucune de ces solutions n'a fonctionné pour moi. La façon dont je corrige la mise au point automatique était:

<activity android:name=".android.InviteFriendsActivity" android:windowSoftInputMode="adjustPan">
    <intent-filter >
    </intent-filter>
</activity>

2
android: windowSoftInputMode = "adjustPan" sur toute activité dans le manifeste Android
rallye le

43

Solution simple: utilisation in AndroidManifestin Activitytag

android:windowSoftInputMode="stateAlwaysHidden"

6
À strictement parler, cela ne résout pas le problème. l'OP a déclaré: "Je ne veux pas qu'un contrôle ait le focus d'entrée au démarrage." Votre solution ne cache que le clavier, il y a une différence subtile.
katzenhut

@katzenhut yep, c'est exactement mon problème avec cette réponse. Se concentrer sur mon edittext ouvre une activité PlaceAutoComplete, donc cette réponse est incomplète
Zach

Cette réponse serait complète si la question était: Comment puis-je toujours m'assurer que mon activité n'affiche jamais de clavier. Qui n'est pas.
Martin Marconcini

37

Vous pouvez simplement mettre « focusable » et « focalisable en mode tactile » à la valeur réelle sur le premier TextViewdu layout. De cette façon, lorsque l'activité commencera, le TextViewsera concentré mais, en raison de sa nature, vous ne verrez rien de concentré sur l'écran et, bien sûr, aucun clavier ne sera affiché ...


fonctionne parfaitement pour moi, seulement je mets la valeur sur la mise en page la plus à l'extérieur de mon activité et non sur la première vue de texte
Maverick1st

36

Ce qui suit a fonctionné pour moi Manifest. Écrire ,

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

1
Cela ne dé-concentre pas le champ de texte: il masque simplement le clavier. Vous obtiendrez toujours un indice qui est poussé hors du champ, et tous les sélecteurs d'état de couleur afficheront l'état "concentré = vrai".
A. Rager

31

Je devais effacer le focus de tous les domaines par programme. Je viens d'ajouter les deux déclarations suivantes à ma définition de mise en page principale.

myLayout.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
myLayout.setFocusableInTouchMode(true);

C'est ça. Correction de mon problème instantanément. Merci, Silver, de m'avoir pointé dans la bonne direction.


28

Ajoutez android:windowSoftInputMode="stateAlwaysHidden"la balise d'activité du Manifest.xmlfichier.

La source


1
Cela ne dé-concentre pas le champ de texte: il masque simplement le clavier. Vous obtiendrez toujours un indice qui est poussé hors du champ, et tous les sélecteurs d'état de couleur afficheront l'état "concentré = vrai".
A. Rager

25

Si vous avez une autre vision de votre activité comme un ListView, vous pouvez également faire:

ListView.requestFocus(); 

dans votre onResume()pour vous concentrer sur le editText.

Je sais que cette question a été répondue, mais fournit simplement une solution alternative qui a fonctionné pour moi :)


22

Essayez ceci avant votre premier champ modifiable:

<TextView  
        android:id="@+id/dummyfocus" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        android:text="@string/foo"
        />

----

findViewById(R.id.dummyfocus).setFocusableInTouchMode(true);
findViewById(R.id.dummyfocus).requestFocus();

21

Ajoutez la onCreateméthode suivante:

this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

1
Cela ne dé-concentre pas le champ de texte: il masque simplement le clavier. Vous obtiendrez toujours un indice qui est poussé hors du champ, et tous les sélecteurs d'état de couleur afficheront l'état "concentré = vrai".
A. Rager

17

Étant donné que je n'aime pas polluer le XML avec quelque chose qui est lié à la fonctionnalité, j'ai créé cette méthode qui "de manière transparente" vole le focus de la première vue focalisable et s'assure ensuite de se retirer si nécessaire!

public static View preventInitialFocus(final Activity activity)
{
    final ViewGroup content = (ViewGroup)activity.findViewById(android.R.id.content);
    final View root = content.getChildAt(0);
    if (root == null) return null;
    final View focusDummy = new View(activity);
    final View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener()
    {
        @Override
        public void onFocusChange(View view, boolean b)
        {
            view.setOnFocusChangeListener(null);
            content.removeView(focusDummy);
        }
    };
    focusDummy.setFocusable(true);
    focusDummy.setFocusableInTouchMode(true);
    content.addView(focusDummy, 0, new LinearLayout.LayoutParams(0, 0));
    if (root instanceof ViewGroup)
    {
        final ViewGroup _root = (ViewGroup)root;
        for (int i = 1, children = _root.getChildCount(); i < children; i++)
        {
            final View child = _root.getChildAt(i);
            if (child.isFocusable() || child.isFocusableInTouchMode())
            {
                child.setOnFocusChangeListener(onFocusChangeListener);
                break;
            }
        }
    }
    else if (root.isFocusable() || root.isFocusableInTouchMode())
        root.setOnFocusChangeListener(onFocusChangeListener);

    return focusDummy;
}

15

Tard, mais peut-être utile. Créer un EditText factice en haut de votre mise en page puis appelez myDummyEditText.requestFocus()auonCreate()

<EditText android:id="@+id/dummyEditTextFocus" 
android:layout_width="0px"
android:layout_height="0px" />

Cela semble se comporter comme je m'y attendais. Pas besoin de gérer les changements de configuration, etc. J'en avais besoin pour une activité avec une longue TextView (instructions).


Pourquoi ne pas simplement le faire avec la vue racine elle-même?
CJBS


13

Oui, j'ai fait la même chose - créer une disposition linéaire «factice» qui se concentre initialement. De plus, j'ai défini les ID de focus `` suivant '' pour que l'utilisateur ne puisse plus le concentrer après avoir fait défiler une fois:

<LinearLayout 'dummy'>
<EditText et>

dummy.setNextFocusDownId(et.getId());

dummy.setNextFocusUpId(et.getId());

et.setNextFocusUpId(et.getId());

beaucoup de travail juste pour se débarrasser de se concentrer sur une vue ..

Merci


12

Pour moi, ce qui a fonctionné sur tous les appareils est le suivant:

    <!-- fake first focusable view, to allow stealing the focus to itself when clearing the focus from others -->

    <View
    android:layout_width="0px"
    android:layout_height="0px"
    android:focusable="true"
    android:focusableInTouchMode="true" />

Il suffit de mettre cela en vue avant la vue focalisée problématique, et c'est tout.


10

La chose la plus simple que j'ai faite est de mettre l'accent sur une autre vue dans onCreate:

    myView.setFocusableInTouchMode(true);
    myView.requestFocus();

Cela a empêché le clavier logiciel d'apparaître et aucun curseur ne clignotait dans EditText.


10

C'est la solution parfaite et la plus simple, je l'utilise toujours dans mon application.

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);

Cela ne dé-concentre pas le champ de texte: il masque simplement le clavier. Vous obtiendrez toujours un indice qui est poussé hors du champ, et tous les sélecteurs d'état de couleur afficheront l'état "concentré = vrai".
A. Rager

9
<TextView
    android:id="@+id/TextView01"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:singleLine="true"
    android:ellipsize="marquee"
    android:marqueeRepeatLimit="marquee_forever"
    android:focusable="true"
    android:focusableInTouchMode="true"
    style="@android:style/Widget.EditText"/>

8

Écrivez ce code dans le Manifestfichier Activityoù vous ne souhaitez pas ouvrir le clavier.

android:windowSoftInputMode="stateHidden"

Fichier manifeste:

 <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.projectt"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="24" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
         <activity
            android:name=".Splash"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".Login"
            **android:windowSoftInputMode="stateHidden"**
            android:label="@string/app_name" >
        </activity>

    </application>

</manifest>

2
Cela ne dé-concentre pas le champ de texte: il masque simplement le clavier. Vous obtiendrez toujours un indice qui est poussé hors du champ, et tous les sélecteurs d'état de couleur afficheront l'état "concentré = vrai".
A. Rager

7

À onCreatevotre activité, ajoutez simplement une utilisation clearFocus()sur votre élément EditText. Par exemple,

edittext = (EditText) findViewById(R.id.edittext);
edittext.clearFocus();

Et si vous souhaitez détourner le focus vers un autre élément, utilisez- requestFocus()le. Par exemple,

button = (Button) findViewById(R.id.button);
button.requestFocus();

6

J'utilise le code suivant pour empêcher un EditText de voler le focus lorsque mon bouton est enfoncé.

addButton.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
        View focused = internalWrapper.getFocusedChild();
        focused.setVisibility(GONE);
        v.requestFocus();
        addPanel();
        focused.setVisibility(VISIBLE);
    }
});

Fondamentalement, masquez le texte modifié, puis affichez-le à nouveau. Cela fonctionne pour moi car le EditText n'est pas en vue, donc peu importe qu'il s'affiche.

Vous pouvez essayer de le cacher et de le montrer successivement pour voir si cela l'aide à perdre le focus.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.