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?

marque
la source

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"/>
Morgan Christiansson
la source
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).

Joe
la source
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
1
définissez-le par programme: stackoverflow.com/questions/6138330/…
Nick Franceschina
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.

argent
la source
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é

Luc
la source
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>
floydaddict
la source
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();
}
Quelqu'un quelque part
la source
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.

Eric Mill
la source
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.

MinceMan
la source
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 )

Lee Yi Hong
la source
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 :)

Rishabh Saxena
la source
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>
rallat
la source
2
android: windowSoftInputMode = "adjustPan" sur toute activité dans le manifeste Android
rallye le
43

Solution simple: utilisation in AndroidManifestin Activitytag

android:windowSoftInputMode="stateAlwaysHidden"
Sergey Sheleg
la source
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é ...

Zeus
la source
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"/>
Babar Sanah
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
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.

jakeneff
la source
28

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

La source

prgmrDev
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 :)

Sid
la source
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();
Jack Slater
la source
21

Ajoutez la onCreateméthode suivante:

this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Vishal Raj
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
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;
}
Takhion
la source
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).

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

Écrivez cette ligne dans votre disposition parentale ...

 android:focusableInTouchMode="true"
Vishal Vaishnav
la source
réponse dupliquée
Ricardo A.
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

marque
la source
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.

développeur android
la source
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.

Lumis
la source
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);

la source
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"/>
atul
la source
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>
Tarit Ray
la source
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();
Compaq LE2202x
la source
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.

drei01
la source