Deshabilitar teclado virtual en NumberPicker

168

Estoy tratando de desactivar el teclado virtual cuando uso un NumberPicker para ingresar valores numéricos (por razones estéticas). Este es mi código xml de diseño:

<?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>

Y finalmente este es el código donde trato de bloquear el teclado en el método 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); 

Lamentablemente, el teclado virtual sigue apareciendo al hacer clic en un NumberPicker. ¿Algunas ideas?

damaxxed
fuente

Respuestas:

475

Acabo de encontrar esto y funciona como un encanto:

myNumberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

También puede configurar esto en XML:

android:descendantFocusability="blocksDescendants" 
Andrew Webber
fuente
1
A menos que me falte algo, esto elimina la capacidad de escribir un valor para NumberPicker. No es necesariamente algo malo, dependiendo de cómo esté utilizando el selector, pero parece ser una limitación de la solución.
frenziedherring
76
También puede configurar esto en XML: android: descendantFocusability = "blocksDescendants"
Ben Clayton
1
Aaah, bloques Descendientes, por supuesto. Muchas gracias :)
Lev
¡Una solución increíble, me salvó!
Hamzeh Soboh
56

Versión XML de la respuesta de Andrew Webber

android:descendantFocusability="blocksDescendants"

Ejemplo

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

Después de leer el código fuente com / android / internal / widget / NumberPicker.java, obtuve la siguiente solución:

// 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);
damaxxed
fuente
Sí, tuve que editar directamente las vistas secundarias de NumberPicker. La API de Android es muy escasa a veces.
damaxxed
6

Simplemente mejoré la respuesta de @MaxVogler (así que si quieres votar este voto también en @MaxVogler) y conviértela en un hack robusto. Además no necesitamos llamar setOnFocusChangeListenery setInputType. Solo setFocusablea falso hará.

A continuación se muestra una API de ayuda para habilitar / deshabilitar la función

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;
        }
    }
}
havexz
fuente
4

Aquí hay otra forma de hacerlo que permite al usuario editar un número si lo desea: simplemente suprime el teclado virtual inicialmente. Use NumberPicker.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS)para suprimir el teclado virtual cuando la interfaz se muestra por primera vez según las respuestas anteriores. Luego obtenga su diálogo o actividad para implementar View.OnTouchListener, llame setOnTouchListener(this)a su NumberPicker, y en su implementación, onTouch(View v,MotionEvent e)restablezca la capacidad de enfoque descendiente del selector numérico a su valor normal, luego devuelva falso.

Devolver falso significa que el TouchPicker aún procesa el toque, lo que significa que si el usuario toca el cuadro de edición, aparece el teclado virtual. Esto es exactamente lo que quería enfrentar con el mismo problema: hacer que el teclado virtual aparezca con el cuadro de diálogo cuando se muestra por primera vez es desagradable ya que cambia el cuadro de diálogo hacia arriba después de que aparece.

public class GetBufferDialog extends DialogFragment implements View.OnTouchListener {

después de crear el Diálogo en el onCreateDialog()método y encontrar el NumberPicker:

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

y aquí está el método OnTouch:

public boolean onTouch(View v, MotionEvent event) {
    m_numberpicker.setDescendantFocusability(m_oldFocus);
    return false;
}
Dave Haines
fuente
1
solo este me ayudó a resolver mi problema, gracias por su enfoque
smoothumut
2

Lo más simple que encontré para trabajar fue:

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

Si solo desea ocultar el teclado del software al cargar la vista con su selector de números, pero aún desea que los usuarios puedan editar después de que se carga la vista, entonces no debe bloquear la capacidad de enfoque descendente. En cambio, solo evite que el selector de números sea el primer elemento enfocado en su vista.

Ver esta respuesta para más detalles.

Basado en la respuesta anterior:

    <!-- 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"/>
eckc
fuente
1

No sé por qué funciona, pero configurar OnClickListener, que no hace nada, impidió que se mostrara el teclado (Lollipop)

numberPicker.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View view) {
  }
});
usuario4215456
fuente
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();
        }
    }
}

* llamando a esto:

  • no bloqueará la capacidad de enfoque descendente (el selector de números será editable)

  • ocultará la entrada suave al crear

  • antes (procesamiento de entrada) getValue () permitirá obtener la walue adecuada


ceph3us
fuente
0

Código de trabajo de forma programática:

mp.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

XML:

android:descendantFocusability="blocksDescendants" 
Vinayak
fuente