Android: Detecta el teclado virtual abierto

Cuando el teclado virtual se abre, quiero una vista de desplazamiento para desplazarse hacia abajo.

Para esto puedo utilizar: fullScroll (View.FOCUS_DOWN);

Pero, ¿cómo desactivo ese comando después de que el evento de apertura de teclado suave se desencadene?

Por este post y este post en android-desarrolladores no parece que es posible hacer lo que quieras. Es posible que desee volver a examinar su caso de uso para lo que está haciendo. Tal vez una de las banderas softInputMode funcionará para usted.

Aquí está mi solución:

1 / Una interfaz sencilla

 public interface KeyboardVisibilityListener { void onKeyboardVisibilityChanged(boolean keyboardVisible); } 

2 / Un método de utilidad (ponerlo donde desee, por ejemplo en una clase llamada KeyboardUtil )

 public static void setKeyboardVisibilityListener(Activity activity, final KeyboardVisibilityListener keyboardVisibilityListener) { final View contentView = activity.findViewById(android.R.id.content); contentView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { private int mPreviousHeight; @Override public void onGlobalLayout() { int newHeight = contentView.getHeight(); if (mPreviousHeight != 0) { if (mPreviousHeight > newHeight) { // Height decreased: keyboard was shown keyboardVisibilityListener.onKeyboardVisibilityChanged(true); } else if (mPreviousHeight < newHeight) { // Height increased: keyboard was hidden keyboardVisibilityListener.onKeyboardVisibilityChanged(false); } else { // No change } } mPreviousHeight = newHeight; } }); } 

3 / Uso de una actividad de esta manera (un buen lugar está en onCreate):

 KeyboardUtil.setKeyboardVisibilityListener(this, mKeyboardVisibilityListener); 

Mirando la fecha, posiblemente usted tiene una solución para su pregunta, de lo contrario:

Aquí está la misma respuesta que hice a otra pregunta relacionada: ¿Hay una manera de decir si el soft-keyboard se muestra?

Pero copia la respuesta completa aquí para evitar enlaces muertos:

Compruebe los cambios de configuración de su actividad

Esto para tu AndroidManifest.xml

Y esto para su clase de actividad http://developer.android.com/reference/android/app/Activity.html#onConfigurationChanged(android.content.res.Configuration)

Deberá @Override el método público onConfigurationChanged (android.content.res.Configuration) de su Actividad para poder manejar, por ejemplo, estos valores:
HardKeyboardHidden ,
Teclado ,
KeyboardHidden

Para todos los valores posibles, consulte http://developer.android.com/reference/android/content/res/Configuration.html.

Verás algo como esto:

 HARDKEYBOARDHIDDEN_NO HARDKEYBOARDHIDDEN_UNDEFINED HARDKEYBOARDHIDDEN_YES KEYBOARDHIDDEN_NO KEYBOARDHIDDEN_UNDEFINED KEYBOARDHIDDEN_YES KEYBOARD_12KEY KEYBOARD_NOKEYS KEYBOARD_QWERTY KEYBOARD_UNDEFINED 

También allí usted podrá leer algo como esto:

 public int hardKeyboardHidden A flag indicating whether the hard keyboard has been hidden. public int keyboard The kind of keyboard attached to the device. public int keyboardHidden A flag indicating whether any keyboard is available. 

ACTUALIZAR:

Aquí hay una muestra específica de lo que estoy hablando:

http://developer.android.com/guide/topics/resources/runtime-changes.html

 @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Checks the orientation of the screen if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show(); } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){ Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show(); } // Checks whether a hardware keyboard is available if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) { Toast.makeText(this, "keyboard visible", Toast.LENGTH_SHORT).show(); } else if (newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) { Toast.makeText(this, "keyboard hidden", Toast.LENGTH_SHORT).show(); } } 

Espero que esto te ayude

La única manera que pude resolver esto es configurar el android de mi actividad: windowSoftInputMode = "adjustResize" e incorporar una "vista de detector" personalizada en el diseño para manejar un cambio de tamaño de contenedor y propagarlo como un evento personalizado (vía un Escuchador) para el teclado suave activado / desactivado.

El siguiente post describe un método para implementarlo: EditText no activa cambios cuando se pulsa de nuevo

Esto funciona para mí

 parent.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { boolean someHasFocus = false; if(host.hasFocus()) someHasFocus = true; if(folder.hasFocus()) someHasFocus = true; if(user.hasFocus()) someHasFocus = true; if(pass.hasFocus()) someHasFocus = true; if(someHasFocus){ if(bottom>oldBottom){ // Keyboard Close viewToHide.setVisibility(View.VISIBLE); }else if(bottom<oldBottom){ // Keyboard Open viewToHide.setVisibility(View.GONE); } }else{ // show viewToHide.setVisibility(View.VISIBLE); } } }); 

Cuando parent es el diseño principal, viewToHide es la vista que se muestra u oculta cuando se muestra el teclado y host, carpeta, usuario y pass son EditText de mi formulario.

Y esto en el manifiesto

 android:windowSoftInputMode="stateHidden|adjustResize" 

Espero que esto ayude

Aquí está mi solución. No necesita android: windowSoftInputMode = "adjustResize"

 public abstract class KeyboardActivity extends Activity { public static final int MIN_KEYBOARD_SIZE = 100; private Window mRootWindow; private View mRootView; private int mKeyboardHeight = -1; private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { public int height; public void onGlobalLayout() { Rect r = new Rect(); View view = mRootWindow.getDecorView(); view.getWindowVisibleDisplayFrame(r); if (height != r.height()) { int diff = height - r.height(); height = r.height(); if (Math.abs(diff) > MIN_KEYBOARD_SIZE) { int diff = height - r.height(); if (height != 0 && Math.abs(diff) > MIN_KEYBOARD_SIZE) { mKeyboardHeight = Math.abs(diff); if (diff > 0) { onKeyboardOpen(); } else { onKeyboardClosed(); } } height = r.height(); } } }; protected abstract void onKeyboardClosed(); protected abstract void onKeyboardOpen(); /** * Should return keyboard height, if keyboard was shown at least once; * @return keyboard height or -1 */ protected int getKeyboardHeight() { return mKeyboardHeight; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mRootWindow = getWindow(); mRootView = mRootWindow.getDecorView().findViewById(android.R.id.content); } @Override protected void onStart() { super.onStart(); mRootView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener); } @Override protected void onStop() { super.onStop(); mRootView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener); } } 

Entonces sólo he extender mi actividad de esta actividad y anular los métodos onKeyboardClosed / onKeyboardOpen.

Para esto lo que solía hacer lo mismo:

  import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; public class SoftKeyboard implements View.OnFocusChangeListener { private static final int CLEAR_FOCUS = 0; private ViewGroup layout; private int layoutBottom; private InputMethodManager im; private int[] coords; private boolean isKeyboardShow; private SoftKeyboardChangesThread softKeyboardThread; private List<EditText> editTextList; private View tempView; // reference to a focused EditText public SoftKeyboard(ViewGroup layout, InputMethodManager im) { this.layout = layout; keyboardHideByDefault(); initEditTexts(layout); this.im = im; this.coords = new int[2]; this.isKeyboardShow = false; this.softKeyboardThread = new SoftKeyboardChangesThread(); this.softKeyboardThread.start(); } public void openSoftKeyboard() { if(!isKeyboardShow) { layoutBottom = getLayoutCoordinates(); im.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT); softKeyboardThread.keyboardOpened(); isKeyboardShow = true; } } public void closeSoftKeyboard() { if(isKeyboardShow) { im.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); isKeyboardShow = false; } } public void setSoftKeyboardCallback(SoftKeyboardChanged mCallback) { softKeyboardThread.setCallback(mCallback); } public void unRegisterSoftKeyboardCallback() { softKeyboardThread.stopThread(); } public interface SoftKeyboardChanged { public void onSoftKeyboardHide(); public void onSoftKeyboardShow(); } private int getLayoutCoordinates() { layout.getLocationOnScreen(coords); return coords[1] + layout.getHeight(); } private void keyboardHideByDefault() { layout.setFocusable(true); layout.setFocusableInTouchMode(true); } /* * InitEditTexts now handles EditTexts in nested views * Thanks to Francesco Verheye ([email protected]) */ private void initEditTexts(ViewGroup viewgroup) { if(editTextList == null) editTextList = new ArrayList<EditText>(); int childCount = viewgroup.getChildCount(); for(int i=0; i<= childCount-1;i++) { View v = viewgroup.getChildAt(i); if(v instanceof ViewGroup) { initEditTexts((ViewGroup) v); } if(v instanceof EditText) { EditText editText = (EditText) v; editText.setOnFocusChangeListener(this); editText.setCursorVisible(true); editTextList.add(editText); } } } /* * OnFocusChange does update tempView correctly now when keyboard is still shown * Thanks to Israel Dominguez ([email protected]) */ @Override public void onFocusChange(View v, boolean hasFocus) { if(hasFocus) { tempView = v; if(!isKeyboardShow) { layoutBottom = getLayoutCoordinates(); softKeyboardThread.keyboardOpened(); isKeyboardShow = true; } } } // This handler will clear focus of selected EditText private final Handler mHandler = new Handler() { @Override public void handleMessage(Message m) { switch(m.what) { case CLEAR_FOCUS: if(tempView != null) { tempView.clearFocus(); tempView = null; } break; } } }; private class SoftKeyboardChangesThread extends Thread { private AtomicBoolean started; private SoftKeyboardChanged mCallback; public SoftKeyboardChangesThread() { started = new AtomicBoolean(true); } public void setCallback(SoftKeyboardChanged mCallback) { this.mCallback = mCallback; } @Override public void run() { while(started.get()) { // Wait until keyboard is requested to open synchronized(this) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } int currentBottomLocation = getLayoutCoordinates(); // There is some lag between open soft-keyboard function and when it really appears. while(currentBottomLocation == layoutBottom && started.get()) { currentBottomLocation = getLayoutCoordinates(); } if(started.get()) mCallback.onSoftKeyboardShow(); // When keyboard is opened from EditText, initial bottom location is greater than layoutBottom // and at some moment equals layoutBottom. // That broke the previous logic, so I added this new loop to handle this. while(currentBottomLocation >= layoutBottom && started.get()) { currentBottomLocation = getLayoutCoordinates(); } // Now Keyboard is shown, keep checking layout dimensions until keyboard is gone while(currentBottomLocation != layoutBottom && started.get()) { synchronized(this) { try { wait(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } currentBottomLocation = getLayoutCoordinates(); } if(started.get()) mCallback.onSoftKeyboardHide(); // if keyboard has been opened clicking and EditText. if(isKeyboardShow && started.get()) isKeyboardShow = false; // if an EditText is focused, remove its focus (on UI thread) if(started.get()) mHandler.obtainMessage(CLEAR_FOCUS).sendToTarget(); } } public void keyboardOpened() { synchronized(this) { notify(); } } public void stopThread() { synchronized(this) { started.set(false); notify(); } } } } 

Y en su Activity o fragment llame a este método en onCreate()

  private void hideAndShowKeyBOrd() { InputMethodManager im = (InputMethodManager) getActivity().getSystemService(Service.INPUT_METHOD_SERVICE); /* Instantiate and pass a callback */ SoftKeyboard softKeyboard; softKeyboard = new SoftKeyboard(mainLayout, im); softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged() { @Override public void onSoftKeyboardHide() { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { } }); } @Override public void onSoftKeyboardShow() { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { if (viewV.getVisibility() == View.VISIBLE) { viewV.setVisibility(View.GONE); } } }); } }); } 

Disfruta tu código

La respuesta de @ BoD funciona bien si elimino la línea siguiente.

 if (mPreviousHeight != 0) { /* other code is same, because mPreviousHeight is 0 when it comes first */ } 
  • Android Cambiar vista de navegación Menú de fondo
  • No se puede importar android.support.design.widget.NavigationView
  • ¿Cómo puedo hacer que `View` llene un` RelativeLayout`?
  • ¿Cómo mostrar una imagen que es más grande que las dimensiones de la pantalla del teléfono?
  • Crash con SurfaceView en Android NDK al pausar / reanudar la aplicación rápidamente
  • Disposición de Android: dos vistas contiguas, de igual anchura, utilizan el ancho total de la pantalla
  • ¿Cómo puedo recuperar el botón de trabajo cuando searchview en Android
  • Cómo configurar el adaptador para searchview en la barra de acciones
  • ¿Cómo agrego un botón a una clase "extends View"?
  • el enlace de datos; la etiqueta de la vista no es correcta, Android
  • Vista de superficie como un mapa de bits en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.