Saltar al contenido

¿Cómo verificar la visibilidad del teclado del software en Android?

Esta es la contestación más acertada que te podemos aportar, sin embargo obsérvala detenidamente y valora si se adapta a tu trabajo.

Solución:

NUEVA RESPUESTAagregado el 25 de enero de 2012

Desde que escribí la respuesta a continuación, alguien me indicó la existencia de ViewTreeObserver y sus amigos, API que han estado al acecho en el SDK desde la versión 1.

En lugar de requerir un tipo de diseño personalizado, una solución mucho más simple es darle a la vista raíz de su actividad una ID conocida, digamos @+id/activityRootenganche un GlobalLayoutListener en ViewTreeObserver y, a partir de ahí, calcule la diferencia de tamaño entre la vista raíz de su actividad y el tamaño de la ventana:

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() 
    @Override
    public void onGlobalLayout() 
        int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
        if (heightDiff > dpToPx(this, 200))  // if more than 200 dp, it's probably a keyboard...
            // ... do something here
        
     
);

Usando una utilidad como:

public static float dpToPx(Context context, float valueInDp) 
    DisplayMetrics metrics = context.getResources().getDisplayMetrics();
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics);

¡Fácil!

Nota:
Su aplicación debe establecer esta bandera en el Manifiesto de Android android:windowSoftInputMode="adjustResize" de lo contrario, la solución anterior no funcionará.

RESPUESTA ORIGINAL

Sí, es posible, pero es mucho más difícil de lo que debería ser.

Si necesito preocuparme por cuándo aparece y desaparece el teclado (que es bastante frecuente), entonces lo que hago es personalizar mi clase de diseño de nivel superior en una que anula onMeasure(). La lógica básica es que si el diseño se encuentra llenando significativamente menos que el área total de la ventana, entonces probablemente se muestre un teclado virtual.

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.LinearLayout;

/*
 * LinearLayoutThatDetectsSoftKeyboard - a variant of LinearLayout that can detect when 
 * the soft keyboard is shown and hidden (something Android can't tell you, weirdly). 
 */

public class LinearLayoutThatDetectsSoftKeyboard extends LinearLayout 

    public LinearLayoutThatDetectsSoftKeyboard(Context context, AttributeSet attrs) 
        super(context, attrs);
    

    public interface Listener 
        public void onSoftKeyboardShown(boolean isShowing);
    
    private Listener listener;
    public void setListener(Listener listener) 
        this.listener = listener;
    

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
        int height = MeasureSpec.getSize(heightMeasureSpec);
        Activity activity = (Activity)getContext();
        Rect rect = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
        int statusBarHeight = rect.top;
        int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
        int diff = (screenHeight - statusBarHeight) - height;
        if (listener != null) 
            listener.onSoftKeyboardShown(diff>128); // assume all soft keyboards are at least 128 pixels high
        
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);       
    

    

Luego en tu clase de Actividad…

public class MyActivity extends Activity implements LinearLayoutThatDetectsSoftKeyboard.Listener 

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        ...
        LinearLayoutThatDetectsSoftKeyboard mainLayout = (LinearLayoutThatDetectsSoftKeyboard)findViewById(R.id.main);
        mainLayout.setListener(this);
        ...
    


    @Override
    public void onSoftKeyboardShown(boolean isShowing) 
        // do whatever you need to do here
    

    ...

Así que espero que esto ayude a alguien.

La nueva respuesta que dio Reuben Scratton es excelente y realmente eficiente, pero realmente solo funciona si configura su windowSoftInputMode para ajustar el tamaño. Si lo configura para ajustar Pan, todavía no es posible detectar si el teclado está visible o no usando su fragmento de código. Para evitar esto, hice esta pequeña modificación en el código anterior.

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() 
@Override
public void onGlobalLayout() 
    Rect r = new Rect();
    //r will be populated with the coordinates of your view that area still visible.
    activityRootView.getWindowVisibleDisplayFrame(r);
   
    int heightDiff = activityRootView.getRootView().getHeight() - r.height();
    if (heightDiff > 0.25*activityRootView.getRootView().getHeight())  // if more than 25% of the screen, its probably a keyboard...
        ... do something here
    
 
); 

¡Ha sido una eternidad en términos de computadora, pero esta pregunta sigue siendo increíblemente relevante!

Así que tomé las respuestas anteriores y las combiné y refiné un poco…

public interface OnKeyboardVisibilityListener 


    void onVisibilityChanged(boolean visible);


public final void setKeyboardListener(final OnKeyboardVisibilityListener listener) 
    final View activityRootView = ((ViewGroup) getActivity().findViewById(android.R.id.content)).getChildAt(0);

    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() 

        private boolean wasOpened;

        private final int DefaultKeyboardDP = 100;

        // From @nathanielwolf answer...  Lollipop includes button bar in the root. Add height of button bar (48dp) to maxDiff
        private final int EstimatedKeyboardDP = DefaultKeyboardDP + (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? 48 : 0);

        private final Rect r = new Rect();

        @Override
        public void onGlobalLayout() 
            // Convert the dp to pixels.
            int estimatedKeyboardHeight = (int) TypedValue
                    .applyDimension(TypedValue.COMPLEX_UNIT_DIP, EstimatedKeyboardDP, activityRootView.getResources().getDisplayMetrics());

            // Conclude whether the keyboard is shown or not.
            activityRootView.getWindowVisibleDisplayFrame(r);
            int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
            boolean isShown = heightDiff >= estimatedKeyboardHeight;

            if (isShown == wasOpened) 
                Log.d("Keyboard state", "Ignoring global layout change...");
                return;
            

            wasOpened = isShown;
            listener.onVisibilityChanged(isShown);
        
    );

Funciona para mi 🙂

NOTA:
Si notas que el PredeterminadoTecladoDP no se ajusta a su dispositivo juegue con el valor y publique un comentario para que todos sepan cuál debería ser el valor… ¡finalmente obtendremos el valor correcto para todos los dispositivos!

Para obtener más detalles, consulte la implementación en Cyborg

Sección de Reseñas y Valoraciones

Agradecemos que quieras auxiliar nuestra función fijando un comentario o valorándolo te lo agradecemos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *