horizontal - scrollview fragment android studio
Android: Detecta softkeyboard abierto (8)
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);
}
}
Luego acabo de extender mi actividad de esta actividad y anular los métodos onKeyboardClosed / onKeyboardOpen.
Cuando se abra el teclado virtual, quiero que la vista de desplazamiento se desplace hacia abajo hasta la parte inferior.
Para esto puedo usar: fullScroll (View.FOCUS_DOWN);
Pero, ¿cómo ejecuto ese comando después de que se desencadene el evento de apertura del teclado virtual?
Aquí está mi solución:
1 / Una interfaz simple
public interface KeyboardVisibilityListener {
void onKeyboardVisibilityChanged(boolean keyboardVisible);
}
2 / Un método de utilidad (póngalo donde desee, por ejemplo, en una clase llamada KeyboardUtil
)
public static void setKeyboardVisibilityListener(Activity activity, KeyboardVisibilityListener keyboardVisibilityListener) {
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 / Usar de una actividad de esta manera (un buen lugar está en onCreate):
KeyboardUtil.setKeyboardVisibilityListener(this, mKeyboardVisibilityListener);
Esto funciona para mi
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);
}
}
});
Donde padre es el diseño principal, viewToHide es la vista que muestra u oculta cuando se muestra el teclado, y el host, la carpeta, el usuario y el pase son el EditText de mi formulario.
Y esto en el manifiesto.
android:windowSoftInputMode="stateHidden|adjustResize"
Espero que esto ayude
La única forma en que pude evitar esto es mediante la configuración de android de mi actividad: windowSoftInputMode = "adjustResize" y luego incrustar una "vista del detector" personalizada en el diseño para manejar un cambio de tamaño de contenedor y propagarlo como un evento personalizado (a través de un Listener) para activar / desactivar el teclado virtual.
La siguiente publicación describe un enfoque para implementarlo: EditText no activa cambios cuando se presiona Atrás
para esto lo que solía hacer igual
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 :)
viendo la fecha, posiblemente tenga una solución para su pregunta, de lo contrario:
Aquí está la misma respuesta que hice a otra pregunta relacionada: ¿Hay alguna forma de saber si se muestra el teclado virtual?
Pero copio la respuesta completa aquí para evitar enlaces muertos:
Por favor revise los cambios de configuración para 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)
Necesitará @ Anular el método público onConfigurationChanged (android.content.res.Configuration) de su Actividad para poder manejar, por ejemplo, estos valores:
Teclado duro oculto ,
teclado
teclado oculto
Para todos los valores posibles, visite http://developer.android.com/reference/android/content/res/Configuration.html
Verás allí 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í podrás 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 respuesta de @BoD funciona bien si elimino la siguiente línea.
if (mPreviousHeight != 0) {
/* other code is same, because
mPreviousHeight is 0 when it comes first */
}
Según esta publicación y esta publicación en los desarrolladores de Android, no parece que sea posible hacer lo que quieres. Es posible que desee volver a examinar su caso de uso para lo que está haciendo. Tal vez una de las banderas softInputMode
funcione para usted.