SoftKeyboard открыть и закрыть прослушиватель в деятельности в Android?
Я Activity
где есть 5 EditText
. Когда пользователь нажимает на первый EditText
затем откройте программную клавиатуру, чтобы ввести в нее некоторое значение. Я хочу установить некоторые другие View
видимость Gone
когда экранная клавиатура открыта, когда пользователь нажимает на первый EditText
и когда мягкая клавиатура закрывается от того же EditText
на задней прессе, то я хочу установить некоторые другие View
видимость виден.
есть ли слушатель или обратный вызов или какой-либо Хак, когда мягкая клавиатура открывается при первом нажатии EditText
в Android?
20 ответов:
это работает только когда
android:windowSoftInputMode
вашей активности установлено значениеadjustResize
в манифесте. Вы можете использовать прослушиватель макета, чтобы увидеть, изменяется ли корневой макет вашего действия с помощью клавиатуры.я использую что-то вроде следующего базового класса для моей деятельности:
public class BaseActivity extends Activity { private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight(); int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop(); LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(BaseActivity.this); if(heightDiff <= contentViewTop){ onHideKeyboard(); Intent intent = new Intent("KeyboardWillHide"); broadcastManager.sendBroadcast(intent); } else { int keyboardHeight = heightDiff - contentViewTop; onShowKeyboard(keyboardHeight); Intent intent = new Intent("KeyboardWillShow"); intent.putExtra("KeyboardHeight", keyboardHeight); broadcastManager.sendBroadcast(intent); } } }; private boolean keyboardListenersAttached = false; private ViewGroup rootLayout; protected void onShowKeyboard(int keyboardHeight) {} protected void onHideKeyboard() {} protected void attachKeyboardListeners() { if (keyboardListenersAttached) { return; } rootLayout = (ViewGroup) findViewById(R.id.rootLayout); rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener); keyboardListenersAttached = true; } @Override protected void onDestroy() { super.onDestroy(); if (keyboardListenersAttached) { rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener); } } }
в следующем примере деятельности использует это, чтобы скрыть представление, когда клавиатура отображается и показать его снова, когда клавиатура скрыта.
макет xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/rootLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ScrollView android:id="@+id/scrollView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > <!-- omitted for brevity --> </ScrollView> <LinearLayout android:id="@+id/bottomContainer" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <!-- omitted for brevity --> </LinearLayout> </LinearLayout>
и активность:
public class TestActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_activity); attachKeyboardListeners(); } @Override protected void onShowKeyboard(int keyboardHeight) { // do things when keyboard is shown bottomContainer.setVisibility(View.GONE); } @Override protected void onHideKeyboard() { // do things when keyboard is hidden bottomContainer.setVisibility(View.VISIBLE); } }
Как отметил Викрам в комментариях, обнаружение того, отображается ли softkeyboard или исчезла, возможно только с некоторыми уродливыми Хак-кодами.
хватит установите прослушиватель фокуса на edittext:
yourEditText.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { //got focus } else { //lost focus } } });
кусок пирога с удивительной библиотекой KeyboardVisibilityEvent: https://android-arsenal.com/details/1/2519
KeyboardVisibilityEvent.setEventListener( getActivity(), new KeyboardVisibilityEventListener() { @Override public void onVisibilityChanged(boolean isOpen) { // some code depending on keyboard visiblity status } });
версия SDK поддержки минимальная 14 для 2.0.0
Деятельность:
final View activityRootView = findViewById(R.id.activityRoot); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect r = new Rect(); activityRootView.getWindowVisibleDisplayFrame(r); int heightDiff = view.getRootView().getHeight() - (r.bottom - r.top); if (heightDiff > 100) { //enter your code here }else{ //enter code for hid } } });
Для Фрагмент:
view = inflater.inflate(R.layout.live_chat_fragment, null); view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect r = new Rect(); //r will be populated with the coordinates of your view that area still visible. view.getWindowVisibleDisplayFrame(r); int heightDiff = view.getRootView().getHeight() - (r.bottom - r.top); if (heightDiff > 500) { // if more than 100 pixels, its probably a keyboard... } } });
Яп-ы ответ не будет работать для AppCompatActivity. Вместо этого получите высоту строки состояния и панели навигации и т. д. и сравните с размером окна вашего приложения.
вот так:
private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // navigation bar height int navigationBarHeight = 0; int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { navigationBarHeight = getResources().getDimensionPixelSize(resourceId); } // status bar height int statusBarHeight = 0; resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { statusBarHeight = getResources().getDimensionPixelSize(resourceId); } // display window size for the app layout Rect rect = new Rect(); getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); // screen height - (user app height + status + nav) ..... if non-zero, then there is a soft keyboard int keyboardHeight = rootLayout.getRootView().getHeight() - (statusBarHeight + navigationBarHeight + rect.height()); if (keyboardHeight <= 0) { onHideKeyboard(); } else { onShowKeyboard(keyboardHeight); } } };
вы можете попробовать это:
private void initKeyBoardListener() { // Минимальное значение клавиатуры. Threshold for minimal keyboard height. final int MIN_KEYBOARD_HEIGHT_PX = 150; // Окно верхнего уровня view. Top-level window decor view. final View decorView = getWindow().getDecorView(); // Регистрируем глобальный слушатель. Register global layout listener. decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { // Видимый прямоугольник внутри окна. Retrieve visible rectangle inside window. private final Rect windowVisibleDisplayFrame = new Rect(); private int lastVisibleDecorViewHeight; @Override public void onGlobalLayout() { decorView.getWindowVisibleDisplayFrame(windowVisibleDisplayFrame); final int visibleDecorViewHeight = windowVisibleDisplayFrame.height(); if (lastVisibleDecorViewHeight != 0) { if (lastVisibleDecorViewHeight > visibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX) { Log.d("Pasha", "SHOW"); } else if (lastVisibleDecorViewHeight + MIN_KEYBOARD_HEIGHT_PX < visibleDecorViewHeight) { Log.d("Pasha", "HIDE"); } } // Сохраняем текущую высоту view до следующего вызова. // Save current decor view height for the next call. lastVisibleDecorViewHeight = visibleDecorViewHeight; } }); }
использовать этот класс,
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 (verheye.francesco@gmail.com) */ 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 (dominguez.israel@gmail.com) */ @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(); } } } }
на
Android Manifest
,android:windowSoftInputMode="adjustResize"
- это необходимо./* Somewhere else in your code */ RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use the layout root InputMethodManager im = (InputMethodManager)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() { // Code here } @Override public void onSoftKeyboardShow() { // Code here } }); /* Open or close the soft keyboard easily */ softKeyboard.openSoftKeyboard(); softKeyboard.closeSoftKeyboard(); /* Prevent memory leaks:*/ @Override public void onDestroy() { super.onDestroy(); softKeyboard.unRegisterSoftKeyboardCallback(); }
P. S-полностью взято из здесь.
различная реализация прослушивателя с мягкой клавиатурой, которая не зависит от изменения размера окна и поэтому также хорошо работает в многооконном мире. конечно, у него есть свои причуды, но imo они ничто по сравнению с полной разбитостью, которая является многооконным и оконным размером-обнаружение вместе.
были бы признательны идеи для улучшения!
Если вы можете, попробуйте расширить EditText и переопределить метод onKeyPreIme.
@Override public void setOnEditorActionListener(final OnEditorActionListener listener) { mEditorListener = listener; //keep it for later usage super.setOnEditorActionListener(listener); } @Override public boolean onKeyPreIme(final int keyCode, final KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { if (mEditorListener != null) { //you can define and use custom listener, //OR define custom R.id.<imeId> //OR check event.keyCode in listener impl //* I used editor action because of ButterKnife @ mEditorListener.onEditorAction(this, android.R.id.closeButton, event); } } return super.onKeyPreIme(keyCode, event); }
Как вы можете расширить его:
- реализовать onfocus прослушивания и объявить "onKeyboardShown"
- объявить 'onKeyboardHidden'
Я думаю, что пересчет высоты экрана не на 100% успешно, как упоминалось ранее. Чтобы быть ясным, переопределение "onKeyPreIme" не вызывается методами "скрыть программную клавиатуру", но если вы делаете это где угодно, вы должны делать "onKeyboardHidden" логику там и не создавать комплексных решений.
другой подход был бы проверить, когда пользователь перестал печатать...
когда TextEdit находится в фокусе (пользователь / набирал), вы можете скрыть представления (слушатель фокуса)
и используйте обработчик + Runnable и прослушиватель изменения текста, чтобы закрыть клавиатуру (независимо от ее видимости) и показать представления после некоторой задержки.
главное, чтобы обратить внимание будет задержка вы используете, который будет зависеть от содержания этих TextEdits.
Handler timeoutHandler = new Handler(); Runnable typingRunnable = new Runnable() { public void run() { // current TextEdit View view = getCurrentFocus(); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); // reset focus view.clearFocus(); // close keyboard (whether its open or not) imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.RESULT_UNCHANGED_SHOWN); // SET VIEWS VISIBLE } }; editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { // SET VIEWS GONE // reset handler timeoutHandler.removeCallbacks(typingRunnable); timeoutHandler.postDelayed(typingRunnable, TYPING_TIMEOUT); } } }); editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // Reset Handler... timeoutHandler.removeCallbacks(typingRunnable); } @Override public void afterTextChanged(Editable s) { // Reset Handler Cont. if (editText.getText().toString().trim().length() > 0) { timeoutHandler.postDelayed(typingRunnable, TYPING_TIMEOUT); } } });
public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.mainactivity); attachKeyboardListeners(); .... yourEditText1.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { yourEditText2.setVisibility(View.GONE); yourEditText3.setVisibility(View.GONE); yourEditText4.setVisibility(View.GONE); yourEditText5.setVisibility(View.GONE); } else { yourEditText2.setVisibility(View.VISIBLE); yourEditText3.setVisibility(View.VISIBLE); yourEditText4.setVisibility(View.VISIBLE); yourEditText5.setVisibility(VISIBLE); } } }); } }
к сожалению, у меня нет достаточно высокой репутации, чтобы прокомментировать ответ Яапа Ван Хенгстума. Но я прочитал несколько комментариев людей, имеющих проблему, что
contentViewTop
всегда0
иonShowKeyboard(...)
всегда вызывается.у меня была такая же проблема, и я понял, что проблема у меня была. Я использовал
AppCompatActivity
вместо "нормальной"Activity
. В данном случаеWindow.ID_ANDROID_CONTENT
относится кContentFrameLayout
, а неFrameLayout
с правым верхним значением. В моем случае это было нормально использовать "нормально"Activity
, если вам нужно использовать другой тип активности (я только что протестировалAppCompatActivity
, может быть, это также проблема с другими acitivy-типами, такими какFragmentActivity
), вы должны получить доступ кFrameLayout
, который является предкомContentFrameLayout
.
по делу
adjustResize
и FragmentActivity принятое решение от @Jaap не работает для меня.вот мое решение:
private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { private int contentDiff; private int rootHeight; @Override public void onGlobalLayout() { View contentView = getWindow().findViewById(Window.ID_ANDROID_CONTENT); if (rootHeight != mDrawerLayout.getRootView().getHeight()) { rootHeight = mDrawerLayout.getRootView().getHeight(); contentDiff = rootHeight - contentView.getHeight(); return; } int newContentDiff = rootHeight - contentView.getHeight(); if (contentDiff != newContentDiff) { if (contentDiff < newContentDiff) { onShowKeyboard(newContentDiff - contentDiff); } else { onHideKeyboard(); } contentDiff = newContentDiff; } } };
когда клавиатуру
rootLayout.getHeight() < rootLayout.getRootView().getHeight() - getStatusBarHeight()
верно, иначе скрыть
private boolean isKeyboardShown = false; private int prevContentHeight = 0; private ViewGroup contentLayout; private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int contentHeight = contentLayout.getHeight(); int rootViewHeight = contentLayout.getRootView().getHeight(); if (contentHeight > 0) { if (!isKeyboardShown) { if (contentHeight < prevContentHeight) { isKeyboardShown = true; onShowKeyboard(rootViewHeight - contentHeight); } } else { if (contentHeight > prevContentHeight) { isKeyboardShown = false; onHideKeyboard(); } } prevContentHeight = contentHeight; } } };
Я немного изменил принятый ответ Яапа. Но в моем случае, есть несколько предположений, таких как
android:windowSoftInputMode=adjustResize
и клавиатура не отображается в начале, когда приложение запускается. А также, я предполагаю, что экран в отношении соответствует высоте родителя.
contentHeight > 0
эта проверка позволяет мне узнать, скрыт ли экран "относительно" или показан для применения прослушивания событий клавиатуры для этого конкретного экрана. Также я передаю вид макета относительно экрана вattachKeyboardListeners(<your layout view here>)
в метод. Каждый раз, когда меняется высота экрана относительно, Я сохраняю его вprevContentHeight
переменная, чтобы проверить позже, отображается ли клавиатура или скрыта.для меня, до сих пор это работало довольно хорошо. Я надеюсь, что это работает и для других.
ответ "Яап Ван Хенгстум" работает для меня, но нет необходимости устанавливать "android:windowSoftInputMode", как он только что сказал!
Я сделал его меньше(теперь он просто определяет, что я хочу, на самом деле событие при показе и скрытии клавиатуры):
private ViewTreeObserver.OnGlobalLayoutListener keyboardLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = rootLayout.getRootView().getHeight() - rootLayout.getHeight(); int contentViewTop = getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop(); if(heightDiff <= contentViewTop){ onHideKeyboard(); } else { onShowKeyboard(); } } }; private boolean keyboardListenersAttached = false; private ViewGroup rootLayout; protected void onShowKeyboard() {} protected void onHideKeyboard() {} protected void attachKeyboardListeners() { if (keyboardListenersAttached) { return; } rootLayout = (ViewGroup) findViewById(R.id.CommentsActivity); rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(keyboardLayoutListener); keyboardListenersAttached = true; } @Override protected void onDestroy() { super.onDestroy(); if (keyboardListenersAttached) { rootLayout.getViewTreeObserver().removeGlobalOnLayoutListener(keyboardLayoutListener); } }
и просто не забудьте добавить этот
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_comments); attachKeyboardListeners();}
этот код прекрасно работает
используйте этот класс для корневого представления:
public class KeyboardConstraintLayout extends ConstraintLayout { private KeyboardListener keyboardListener; private EditText targetEditText; private int minKeyboardHeight; private boolean isShow; public KeyboardConstraintLayout(Context context) { super(context); minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); //128dp } public KeyboardConstraintLayout(Context context, AttributeSet attrs) { super(context, attrs); minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); // 128dp } public KeyboardConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); minKeyboardHeight = getResources().getDimensionPixelSize(R.dimen.keyboard_min_height); // 128dp } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (!isInEditMode()) { Activity activity = (Activity) getContext(); @SuppressLint("DrawAllocation") Rect rect = new Rect(); getWindowVisibleDisplayFrame(rect); int statusBarHeight = rect.top; int keyboardHeight = activity.getWindowManager().getDefaultDisplay().getHeight() - (rect.bottom - rect.top) - statusBarHeight; if (keyboardListener != null && targetEditText != null && targetEditText.isFocused()) { if (keyboardHeight > minKeyboardHeight) { if (!isShow) { isShow = true; keyboardListener.onKeyboardVisibility(true); } }else { if (isShow) { isShow = false; keyboardListener.onKeyboardVisibility(false); } } } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } public boolean isShowKeyboard() { return isShow; } public void setKeyboardListener(EditText targetEditText, KeyboardListener keyboardListener) { this.targetEditText = targetEditText; this.keyboardListener = keyboardListener; } public interface KeyboardListener { void onKeyboardVisibility (boolean isVisible); }
}
и установите прослушиватель клавиатуры в действие или фрагмент:
rootLayout.setKeyboardListener(targetEditText, new KeyboardConstraintLayout.KeyboardListener() { @Override public void onKeyboardVisibility(boolean isVisible) { } });
это будет работать без каких-либо изменений в вашей деятельности
android:windowSoftInputMode
Шаг 1: расширьте класс EditText и переопределите эти два:
@Override public void setOnEditorActionListener(final OnEditorActionListener listener) { mEditorListener = listener; super.setOnEditorActionListener(listener); } @Override public boolean onKeyPreIme(final int keyCode, final KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { if (mEditorListener != null) { mEditorListener.onEditorAction(this, android.R.id.closeButton, event); } } return super.onKeyPreIme(keyCode, event); }
Шаг 2: Создайте эти два в своей деятельности:
private void initKeyboard() { final AppEditText editText = findViewById(R.id.some_id); editText.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { setKeyboard(hasFocus); } }); editText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (event == null || event.getKeyCode() == KeyEvent.KEYCODE_BACK) { editText.clearFocus(); } return false; } }); } public void setKeyboard(boolean isShowing) { // do something }
*** помните, чтобы сделать
clearFocus
РАБОТА, Вы должны сделать родителя или первого ребенка в родительской иерархии focusable.setFocusableInTouchMode(true); setFocusable(true);
вы можете использовать мою функцию расширения Rx (Kotlin).
/** * @return [Observable] to subscribe on keyboard visibility changes. */ fun Activity.keyboardVisibilityChanges(): Observable<Boolean> { // flag indicates whether keyboard is open var isKeyboardOpen = false val notifier: PublishSubject<Boolean> = PublishSubject.create() // approximate keyboard height val approximateKeyboardHeight = 100.fromDpToPx() // device screen height val screenHeight: Int = Resources.getSystem().displayMetrics.heightPixels val visibleDisplayFrame = Rect() with(window.decorView) { viewTreeObserver.addOnDrawListener { getWindowVisibleDisplayFrame(visibleDisplayFrame) val keyboardHeight = screenHeight - (visibleDisplayFrame.bottom - visibleDisplayFrame.top) val keyboardOpen = keyboardHeight >= approximateKeyboardHeight val hasChanged = isKeyboardOpen xor keyboardOpen if (hasChanged) { isKeyboardOpen = keyboardOpen notifier.onNext(keyboardOpen) } } } return notifier }
Это не работает как хотелось бы...
... видели, как многие используют вычисления размера для проверки ...
Я хотел определить, был ли он открыт или нет и нашел
isAcceptingText()
таким образом, это действительно не отвечает на вопрос, поскольку он не касается открытия или закрытия, а скорее открыт или закрыт, поэтому это связанный код, который может помочь другим в различных сценариях...
в деятельности
if (((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).isAcceptingText()) { Log.d(TAG,"Software Keyboard was shown"); } else { Log.d(TAG,"Software Keyboard was not shown"); }
in фрагмент
if (((InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE)).isAcceptingText()) { Log.d(TAG,"Software Keyboard was shown"); } else { Log.d(TAG,"Software Keyboard was not shown"); }