J'ai quelques champs EditText dans un ListView. Lorsque je tape sur l'un des champs EditText, le clavier se glisse dans la vue (comme il se doit), mais le champ EditText que j'ai tapé perd le focus. J'ai essayé d'utiliser diverses méthodes InputMethodManager pour faire apparaître le clavier (afin de résoudre le problème plutôt que de le résoudre réellement), mais cela n'a pas fonctionné - le clavier n'était pas visible lorsque l'activité est apparue.
Le type de l’EditText est number
, et lorsque le clavier est enfoncé, c’est un clavier numérique, mais quand il finit de glisser et que l’EditText perd le focus, il devient le clavier alphabétique (ce qui renforce l’idée que l’EditText n’a plus le focus). .
Mes questions sont les suivantes:
1) Comment puis-je faire la sélection de mon champ EditText et le glissement ultérieur du clavier logiciel not faire perdre le focus à mon EditText?
... à défaut ...
2) Comment puis-je faire en sorte que le clavier se mette en place afin qu'il ne glisse jamais (évitant ainsi le comportement que je trouve si désagréable)?
Mon manifeste inclut Android:windowSoftInputMode="stateAlwaysVisible"
, mais le clavier n'apparaît pas tant que je n'ai pas tapé sur un EditText. Cette ignorance de l'attribut 'stateAlwaysVisible' semble ne se produire que dans l'émulateur - sur mon périphérique fourni, elle est honorée. La question 2 ci-dessus fonctionne donc sur le périphérique ... mais pas dans l'émulateur.
Merci pour toute l'aide que vous pourrez fournir!
Voici comment je l'ai fait. La onFocusChangeListener()
est appelée plusieurs fois lorsque vous touchez une EditText
pour y taper du texte. La séquence est:
La cible finit par se concentrer
//////////////////////////////////////////////////////////////////
private final int minDelta = 300; // threshold in ms
private long focusTime = 0; // time of last touch
private View focusTarget = null;
View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
long t = System.currentTimeMillis();
long delta = t - focusTime;
if (hasFocus) { // gained focus
if (delta > minDelta) {
focusTime = t;
focusTarget = view;
}
}
else { // lost focus
if (delta <= minDelta && view == focusTarget) {
focusTarget.post(new Runnable() { // reset focus to target
public void run() {
focusTarget.requestFocus();
}
});
}
}
}
};
Le code ci-dessus fonctionne bien pour les fenêtres contextuelles du clavier. Cependant, il ne détecte pas le pop-up parole-à-texte.
Vous devez changer votre AndroidManifest.xml
Ajoutez Android: windowSoftInputMode = "adjustPan" dans l'activité contenant la vue de liste . Cela résoudra votre problème.
<activity Android:name=".MyEditTextInListView"
Android:label="@string/app_name"
Android:windowSoftInputMode="adjustPan">
Cordialement
Dans mon cas, cela se produit car lorsque ListView est redimensionné, il recrée tous les éléments de la liste (c.-à-d. Qu'il appelle à nouveau getView () pour chaque élément de la liste visible).
Étant donné que EditText se trouve dans la présentation que je retourne de getView (), cela signifie qu'il s'agit d'une instance différente de EditText par rapport à celle qui avait le focus précédemment. Une conséquence secondaire est que, lorsque le clavier logiciel apparaît ou disparaît, j'ai constaté que je perdais le contenu de EditText.
Parce que je voulais que mon point de vue reste entièrement accessible (c'est-à-dire que je souhaite le redimensionner au lieu de le cacher derrière la fenêtre du clavier avec certaines parties inaccessibles), je ne pouvais pas utiliser la réponse de Frank, qui semble par ailleurs être la meilleure approche.
J'ai résolu ce problème en utilisant un OnFocusChangeListener sur le EditText pour enregistrer l'horodatage lorsque le focus était perdu, puis dans getView () lors de la recréation de l'élément de liste. ) pour le restituer à l’EditText en question.
Vous pouvez également récupérer le texte de l'instance précédente de EditText à ce stade et le transférer vers la nouvelle instance.
private class MyAdapter<Type> extends ArrayAdapter<String>
implements OnFocusChangeListener
{
private EditText mText;
private long mTextLostFocusTimestamp;
private LayoutInflater mLayoutInflater;
public MyAdapter(Context context, int resource, int textResourceId, ArrayList<String> data, LayoutInflater li) {
super(context, resource, textResourceId, data);
mLayoutInflater = li;
mTextLostFocusTimestamp = -1;
}
private void reclaimFocus(View v, long timestamp) {
if (timestamp == -1)
return;
if ((System.currentTimeMillis() - timestamp) < 250)
v.requestFocus();
}
@Override public View getView (int position, View convertView, ViewGroup parent)
{
View v = mLayoutInflater.inflate(R.layout.mylayout, parent, false);
EditText newText = (EditText) v.findViewById(R.id.email);
if (mText != null)
newText.setText(mText.getText());
mText = newText;
mText.setOnFocusChangeListener(this);
reclaimFocus(mText, mTextLostFocusTimestamp);
return v;
}
@Override public void onFocusChange(View v, boolean hasFocus) {
if ((v == mText) && !hasFocus)
mTextLostFocusTimestamp = System.currentTimeMillis();
}
}
Si le editText à l'intérieur de listView s'assure simplement que vous gonflez la vue dans la méthode getView de cette manière.
if (convertView == null)
convertView = LayoutInflater.from(context).inflate(R.layout.yourItemListLayout,
parent, false);
Edit: ce travail pour certains mobiles, je n’utilise pas tous la réponse de M. Frank ci-dessus.
Dans AndroidManifest.xml, utilisez adjustNothing dans l’activité contenant les vues.
<activity
Android:name=".ActivityName"
Android:windowSoftInputMode="adjustNothing">
Vous devez tester ce code sur un périphérique avec un clavier matériel toujours visible. Le comportement peut également se produire ici.
Pour éviter cela, vous pouvez avoir le clavier toujours visible .. mais ce n'est pas très facile, comme vous pouvez le voir avec ce fil:
https://groups.google.com/forum/#!topic/Android-developers/FyENeEdmYC0
Théoriquement, vous devrez peut-être créer votre propre clavier Android (bien que vous utilisiez comme base le clavier Android), comme décrit ici: Android: Comment rendre le clavier toujours visible?
Pour ceux qui viennent ici avec Xamarin ou Xamarin.Forms:
J'ai eu le même problème aussi, mais seulement avec Android 5.x - toutes les versions plus récentes, y compris 8.1, ont bien fonctionné.
Evidemment, sheltond avait raison en disant:
Dans mon cas, cela se produit car lorsque ListView est redimensionné, il recrée tous les éléments de la liste (c.-à-d. Qu'il appelle à nouveau getView () pour chaque élément de la liste visible).
Ma liste a également été redimensionnée et non, la solution de Frank de définir windowSoftInputMode="adjustPan"
n’était pas une option pour moi, car cela signifie que le clavier déplace partiellement la liste en dehors de l’écran.
Tout ce que je devais faire après des heures de débogage de focus était de définir la stratégie de mise en cache de cellules de Xamarin Forms ListView:
De
CachingStrategy="RecycleElement"
À
CachingStrategy="RetainElement"
Cela empêchera les cellules d'être recréées. Toutefois, cela pourrait entraîner de mauvaises performances et une consommation de mémoire importante pour les listes volumineuses. Être conscient.
Ajoutez Android: windowSoftInputMode = "adjustResize" dans l'activité contenant la liste ou EditText. Cela résoudra votre problème.
<activity Android:name=".MainActivity"
Android:windowSoftInputMode="adjustResize">
</activity>
Ce gars avait le même problème et plus encore. Il l'a résolu en utilisant un ScrollView et un LinearLayout au lieu d'un ListView.