Android: всплывающее окно с ошибкой в EditText не сдвигается вниз, когда клавиатура уходит
У меня есть активность, которая отображает несколько EditTexts на экране для ввода пользователем. Чтобы убедиться, что мягкая клавиатура не закрывает мои поля, когда она отображается, я установил свойство
android:windowSoftInputMode="adjustPan"
для моей активности в манифесте. Я проверяю содержимое EditText, когда 1. Вид теряет фокус 2. Когда пользователь выполняет действие 'Enter'. После проверки, если значение недействительно, я звоню
setError(CharSequence error)
в EditText, который вызывает всплывающее отображение, содержащее ошибку, в которую я прошел. Проблема заключается в том, что EditText перемещается вверх, когда отображается мягкая клавиатура, и всплывающее окно отображается в это время (подтверждение не выполнено), popup не следует EditText вниз, когда клавиатура уходит, она остается там, где она была впервые показана.
Любые идеи о том, как это исправить? Это ошибка в Android?
Ответы
Ответ 1
Если это так, как вы описали, я думаю, что это может быть подлинная ошибка, поэтому стоит записать ее на сайт Android Source.
Так что, очевидно, я могу думать только о том, как работать с хаком!
Отменить, когда клавиатура исчезнет:
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK &&
event.getAction() == KeyEvent.ACTION_UP) {
revalidateEditText();
return false;
}
return super.dispatchKeyEvent(event);
}
public void revalidateEditText(){
// Dismiss your origial error dialog
setError(null);
// figure out which EditText it is, you already have this code
// call your validator like in the Q
validate(editText); // or whatever your equivalent is
}
Это приведет к пересмотру вашего EditText, отменит ваш диалог ошибок и повторно отобразит его.
Как этот звук?
Вдохновленный: Получить ключевое событие в EditText
Ответ 2
Вы также можете создать свой собственный метод EditText и переопределить onKeyPreIme (int keyCode, событие KeyEvent)
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
clearFocus();
return false;
}
}
Ответ 3
Для меня это помогло обернуть макет в ScrollView
. После этого вся прокрутка setError-box работала нормально.
Ответ 4
Вы пробовали проверить свой вид, т.е. вызывать метод invalidate() вашего представления.
попробуйте editText.invalidate();
Спасибо.
Ответ 5
Я нашел РЕШЕНИЕ!
Вот код:
import android.content.Context;
import android.os.Handler;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
/**
* Created by Jaume Colom Ferrer on 14/12/2015
*/
public class EditTextPopUpFixed extends AppCompatEditText {
private static final int TIME_SLEEP = 500;
private Context ctx;
private EditTextListener mListener;
private int backTimes = 0;
public EditTextPopUpFixed(Context context) {
super(context);
ctx = context;
}
public EditTextPopUpFixed(Context context, AttributeSet attrs) {
super(context, attrs);
ctx = context;
}
public EditTextPopUpFixed(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
ctx = context;
}
public void setEditTextListener(EditTextListener lis) {
mListener = lis;
this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
backTimes = 0;
return false;
}
});
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK)
backTimes++;
if (backTimes == 3) {
backTimes = 0;
mListener.close();
return true;
}
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_ENTER) {
InputMethodManager mgr = (InputMethodManager) ctx.getSystemService(Context.INPUT_METHOD_SERVICE);
if (mgr.isActive()) {
mgr.hideSoftInputFromWindow(this.getWindowToken(), 0);
boolean mustRevalidate = getError() != null;
setError(null);
if (mListener != null && mustRevalidate) {
Handler han = new Handler();
han.postDelayed(new Runnable() {
@Override
public void run() {
mListener.revalidateEditText();
}
}, TIME_SLEEP);
}
} else {
backTimes = 0;
super.onKeyPreIme(keyCode, event);
}
return true;
}
return false;
}
public interface EditTextListener {
void revalidateEditText(); //Revalidates the EditText to refresh the Popup (Must revalidate the EditText in its implementation)
void close(); // Method to close the activity or fragment (Must finish activity or go back in its implementation)
}
}
Вы можете использовать этот Custom EditText, чтобы решить эту проблему. Он обновляет ошибку после открытия/закрытия клавиатуры, и ваше всплывающее окно всегда будет отображаться правильно.
Вы должны реализовать close (finish или onBackPressed) и повторно использовать методы edittext в своем классе.