Desativar teclado virtual no NumberPicker

168

Estou tentando desativar o teclado virtual ao usar um NumberPicker para inserir valores numéricos (por razões estéticas). Este é o meu layout-xml-code:

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

E, finalmente, este é o código em que tento bloquear o teclado no 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); 

Infelizmente, o teclado virtual ainda aparece ao clicar em um NumberPicker. Alguma ideia?

damaxxed
fonte

Respostas:

475

Só encontrei isso e funciona como um encanto:

myNumberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

Você também pode definir isso em XML:

android:descendantFocusability="blocksDescendants" 
Andrew Webber
fonte
1
A menos que esteja faltando alguma coisa, isso remove a capacidade de digitar um valor para o NumberPicker. Não é necessariamente uma coisa ruim, dependendo de como você está usando o selecionador, mas parece ser uma limitação da solução.
Freniedherring
76
Você também pode definir isso em XML: android: descendantFocusability = "blocksDescendants"
Ben Clayton
1
Aaah, bloqueia descendentes, é claro. Muito obrigado :)
Lev
Solução incrível, me salvou!
Hamzeh Soboh 7/01/19
56

Versão XML da resposta de Andrew Webber

android:descendantFocusability="blocksDescendants"

Exemplo

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

Depois de ler o código-fonte com / android / internal / widget / NumberPicker.java, cheguei à seguinte solução:

// 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
fonte
Sim, tive que editar diretamente as visualizações filho do NumberPicker. A API do Android às vezes é muito escassa.
Damaxxed
6

Apenas aprimorei os ans do @MaxVogler (por isso, se não quisermos votar neste voto também no @MaxVogler) e faça dele um hack robusto. Também não precisamos ligar setOnFocusChangeListenere setInputType. Apenas setFocusablefalso irá fazer.

Abaixo está uma API auxiliar para ativar / desativar o recurso

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
fonte
4

Aqui está outra maneira de fazer isso, que permite ao usuário editar um número, se quiser - apenas suprime o teclado virtual inicialmente. Use NumberPicker.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS)para suprimir o teclado virtual quando a interface aparecer pela primeira vez, conforme as respostas acima. Em seguida, instale seu diálogo ou atividade View.OnTouchListener, chame setOnTouchListener(this)seu NumberPickere, em sua implementação, onTouch(View v,MotionEvent e)redefina a focalização descendente do numberpicker para seu valor normal e, em seguida, retorne false.

Retornar false significa que o toque ainda é processado pelo NumberPicker, o que significa que, se o usuário tocar na caixa de edição, o teclado virtual será ativado. Isso é exatamente o que eu queria enfrentar o mesmo problema - ter o teclado virtual com a caixa de diálogo quando é exibida pela primeira vez é desagradável, pois muda a caixa de diálogo depois que aparece.

public class GetBufferDialog extends DialogFragment implements View.OnTouchListener {

depois de criar o Diálogo no onCreateDialog()método e encontrar o NumberPicker:

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

e aqui está o método OnTouch:

public boolean onTouch(View v, MotionEvent event) {
    m_numberpicker.setDescendantFocusability(m_oldFocus);
    return false;
}
Dave Haines
fonte
1
só que este me ajudou a resolver o meu problema, obrigado pela sua abordagem
smoothumut
2

O mais simples que encontrei para trabalhar foi:

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

Se você deseja apenas ocultar o teclado do software ao carregar a visualização com o seletor de números, mas ainda assim deseja que os usuários possam editar depois que a visualização é carregada, não deve bloquear a focagem descendente. Em vez disso, evite que o seletor de números seja o primeiro item focado em sua exibição.

Veja esta resposta para detalhes.

Com base na resposta acima:

    <!-- 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
fonte
1

Não sei por que ele funciona, mas definir OnClickListener que não faz nada impede que o teclado seja exibido (pirulito)

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

* chamando isso:

  • não bloqueia a focabilidade descendente (numberpicker será editável)

  • ocultará a entrada suave ao criar

  • antes (entrada de processamento), getValue () permitirá obter o valor adequado


ceph3us
fonte
0

Código de trabalho programaticamente:

mp.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);

XML:

android:descendantFocusability="blocksDescendants" 
Vinayak
fonte