Désactiver le clavier virtuel sur NumberPicker


168

J'essaie de désactiver le clavier virtuel lors de l'utilisation d'un NumberPicker pour entrer des valeurs numériques (pour des raisons esthétiques). Voici mon code layout-xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/linearLayout2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="30dp"
        android:layout_marginTop="30dp" >

        <NumberPicker
            android:id="@+id/repetitionPicker"
            android:layout_width="40dp"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="@string/repetitions_short_divider"
            android:textAppearance="?android:attr/textAppearanceMedium" />

        <NumberPicker
            android:id="@+id/weightPicker"
            android:layout_width="40dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="40dp" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="@string/pounds"
            android:textAppearance="?android:attr/textAppearanceMedium" />
    </LinearLayout>


    <Button
        android:id="@+id/saveButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/save" />

</LinearLayout>

Et enfin c'est le code où j'essaye de bloquer le clavier dans la méthode onCreate () -:

// hide keyboard
View.OnClickListener disableKeyBoardListener = new View.OnClickListener() {
    public void onClick(View v) {
        ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
                .hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
    }
};

((EditText) weightPicker.getChildAt(1)).setInputType(InputType.TYPE_NULL);
((EditText) repetitionPicker.getChildAt(1)).setInputType(InputType.TYPE_NULL);

((EditText) weightPicker.getChildAt(1)).setOnClickListener(disableKeyBoardListener);
//((EditText) repetitionPicker.getChildAt(1)).setOnClickListener(disableKeyBoardListener);
//weightPicker.setOnClickListener(disableKeyBoardListener);
//repetitionPicker.setOnClickListener(disableKeyBoardListener);     

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

Malheureusement, le clavier virtuel apparaît toujours lorsque vous cliquez sur un NumberPicker. Des idées?

Réponses:


475

Je viens de trouver ceci et cela fonctionne comme un charme:

myNumberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

Vous pouvez également définir cela en XML:

android:descendantFocusability="blocksDescendants" 

1
Sauf si je manque quelque chose, cela supprime la possibilité de taper une valeur pour NumberPicker. Ce n'est pas nécessairement une mauvaise chose, selon la façon dont vous utilisez le sélecteur, mais cela semble être une limitation de la solution.
frenziedherring

76
Vous pouvez également définir ceci dans XML: android: descendantFocusability = "blocksDescendants"
Ben Clayton

1
Aaah, bloque les descendants, bien sûr. Merci beaucoup :)
Lév

Solution incroyable, m'a sauvé!
Hamzeh Soboh

56

Version XML de la réponse d'Andrew Webber

android:descendantFocusability="blocksDescendants"

Exemple

<NumberPicker
        android:id="@+id/your_numberpicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:descendantFocusability="blocksDescendants"/>

7

Après avoir lu le code source com / android / internal / widget / NumberPicker.java, je suis arrivé à la solution suivante:

// Hide soft keyboard on NumberPickers by overwriting the OnFocusChangeListener
OnFocusChangeListener fcl = new OnFocusChangeListener() {
    public void onFocusChange(View v, boolean hasFocus) {
        // Do nothing to suppress keyboard
    }
};

((EditText) numberPicker.getChildAt(1)).setOnFocusChangeListener(fcl);

// Suppress soft keyboard from the beginning
((EditText) numberPicker.getChildAt(1)).setInputType(InputType.TYPE_NULL);

Oui, je devais modifier directement les vues enfants du NumberPicker. L'API Android est parfois très rare.
damaxxed le

6

Simplement amélioré les ans de @MaxVogler (donc si vous ne voulez pas voter ce vote @MaxVogler aussi) et en faire un hack robuste. Nous n'avons pas non plus besoin d'appeler setOnFocusChangeListeneret setInputType. Seul setFocusablele faux fera l'affaire.

Vous trouverez ci-dessous une API d'assistance pour activer / désactiver la fonctionnalité

public static void enableNumberPickerManualEditing(NumberPicker numPicker,
        boolean enable) {
    int childCount = numPicker.getChildCount();

    for (int i = 0; i < childCount; i++) {
        View childView = numPicker.getChildAt(i);

        if (childView instanceof EditText) {
            EditText et = (EditText) childView;
            et.setFocusable(enable);
            return;
        }
    }
}

4

Voici une autre façon de le faire qui permet à l'utilisateur de toujours modifier un numéro s'il le souhaite - cela supprime simplement le clavier virtuel au départ. Utilisez NumberPicker.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS)pour supprimer le clavier virtuel lorsque l'interface s'affiche pour la première fois selon les réponses ci-dessus. Ensuite, demandez à votre boîte de dialogue ou à votre activité de mettre en œuvre View.OnTouchListener, appelez setOnTouchListener(this)votre NumberPicker, et dans votre implémentation, onTouch(View v,MotionEvent e)réinitialisez la focalisabilité descendante de numberpicker à sa valeur normale, puis retournez false.

Renvoyer false signifie que le toucher est toujours traité par NumberPicker, ce qui signifie que si l'utilisateur appuie sur la zone d'édition, le clavier virtuel apparaît. Cela se trouve être exactement ce que je voulais face au même problème - avoir le clavier virtuel avec la boîte de dialogue quand il apparaît pour la première fois est déplaisant car il déplace la boîte de dialogue après son apparition.

public class GetBufferDialog extends DialogFragment implements View.OnTouchListener {

après avoir créé le Dialog dans la onCreateDialog()méthode et avoir trouvé le NumberPicker:

m_oldFocus = m_numberpicker.getDescendantFocusability();
m_numberpicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS); 
m_numberpicker.setOnTouchListener(this);

et voici la méthode OnTouch:

public boolean onTouch(View v, MotionEvent event) {
    m_numberpicker.setDescendantFocusability(m_oldFocus);
    return false;
}

1
seul celui-ci m'a aidé à résoudre mon problème, merci pour votre approche
smoothumut

2

Le plus simple que j'ai trouvé pour travailler était:

numberPicker               = (NumberPicker) myDialogView.findViewById(R.id.myViewId);
EditText numberPickerChild = (EditText) numberPicker.getChildAt(0);
numberPickerChild.setFocusable(false);
numberPickerChild.setInputType(InputType.TYPE_NULL);

2

Si vous souhaitez uniquement masquer le clavier logiciel lors du chargement de la vue avec votre sélecteur de numéro, mais que vous souhaitez toujours que les utilisateurs puissent modifier après le chargement de la vue, vous ne devez pas bloquer la focalisation descendante. Au lieu de cela, empêchez simplement le sélecteur de nombres d'être le premier élément ciblé de votre vue.

Voir cette réponse pour plus de détails.

Basé sur la réponse ci-dessus:

    <!-- Dummy item to prevent Number Picker 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 -->
    <NumberPicker 
        android:id="@+id/number_picker"
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content"
        android:nextFocusUp="@id/number_picker" 
        android:nextFocusLeft="@id/number_picker"/>

1

Je ne sais pas pourquoi cela fonctionne, mais la configuration d'OnClickListener qui ne fait rien n'empêche le clavier de s'afficher (Lollipop)

numberPicker.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
  }
});

0
/**
 * set focus to top level window
 * disposes descendant focus
 * disposes softInput
 * @param context - activity context
 * @param enable - state of focus
 * */
public static void topLevelFocus(Context context, boolean enable){
    if(Activity.class.isAssignableFrom(context.getClass())){
        ViewGroup tlView = (ViewGroup) ((Activity) context).getWindow().getDecorView();
        if(tlView!=null){
            tlView.setFocusable(enable);
            tlView.setFocusableInTouchMode(enable);
            tlView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
            tlView.requestFocus();
        }
    }
}

* appelant ceci:

  • ne bloquera pas la focalisation descendante (le sélecteur de nombre sera modifiable)

  • masquera l'entrée logicielle lors de la création

  • avant (traitement de l'entrée) getValue () permettra d'obtenir une valeur correcte



0

Code de travail par programme :

mp.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

XML:

android:descendantFocusability="blocksDescendants" 
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.