Saya memiliki di Activity
mana ada 5 EditText
s. Ketika pengguna mengklik yang pertama EditText
, keyboard lunak terbuka untuk memasukkan beberapa nilai di dalamnya. Saya ingin mengatur View
visibilitas orang lain ke Gone
saat soft keyboard terbuka dan juga saat pengguna mengklik yang pertama EditText
dan juga saat soft keyboard menutup dari yang sama EditText
saat tombol kembali ditekan. Kemudian saya ingin mengatur View
visibilitas orang lain menjadi terlihat.
Apakah ada pendengar atau panggilan balik atau peretasan apa pun ketika keyboard lunak terbuka dari klik pertama EditText
di Android?
trying to detect the virtual keyboard height in Android.
X
danY
lokasi jatuh pada / di atas keyboard =>SecurityException
=> decrementY
dan coba lagi => sampai tidak ada pengecualian yang dilemparkan =>Y
nilai saat ini adalah ketinggian keyboard. 2. jika keyboard tidak terbuka => noSecurityException
.SecurityException
dilempar => keyboard terbuka. Jika tidak, keyboard ditutup.EditText
bukan yang lainEditText
. Bagaimana saya bisa membedakan ini?Jawaban:
Ini hanya berfungsi jika
android:windowSoftInputMode
aktivitas Anda disetel keadjustResize
dalam manifes. Anda bisa menggunakan pendengar tata letak untuk melihat apakah tata letak akar aktivitas Anda diubah ukurannya oleh keyboard.Saya menggunakan sesuatu seperti kelas dasar berikut untuk aktivitas saya:
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); } } }
Contoh aktivitas berikut menggunakan ini untuk menyembunyikan tampilan saat keyboard ditampilkan dan menampilkannya lagi saat keyboard disembunyikan.
Tata letak 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>
Dan aktivitasnya:
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); } }
sumber
rootLayout = (ViewGroup) findViewById(R.id.rootLayout);
dari?Sepotong kue dengan perpustakaan KeyboardVisibilityEvent yang mengagumkan
KeyboardVisibilityEvent.setEventListener( getActivity(), new KeyboardVisibilityEventListener() { @Override public void onVisibilityChanged(boolean isOpen) { // write your code } });
Penghargaan untuk Yasuhiro SHIMIZU
sumber
Seperti yang ditunjukkan Vikram di komentar, mendeteksi apakah softkeyboard ditampilkan atau telah menghilang hanya mungkin dilakukan dengan beberapa peretasan yang buruk.
Mungkin cukup dengan menetapkan pendengar fokus pada teks editan :
yourEditText.setOnFocusChangeListener(new OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { //got focus } else { //lost focus } } });
sumber
setOnFocusChangeListener
listener akan dipanggil lalu saya tekan kembali lalu tutup keyboard & tapi tidak klik view lain, sekarang lagi saya klik edittext yang sama yang sudah fokus lalu apa yang akan terjadi?onFocusChange()
tidak akan dipanggil.Untuk Aktivitas:
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 } } });
Untuk Fragmen:
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... } } });
sumber
android:windowSoftInputMode="adjustResize"
dimanifestasikan?Jawaban Jaap tidak akan berfungsi untuk AppCompatActivity. Alih-alih, dapatkan tinggi Status Bar dan bilah Navigasi, dll. Dan bandingkan dengan ukuran jendela aplikasi Anda.
Seperti:
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); } } };
sumber
Kamu bisa mencobanya:
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; } }); }
sumber
Kode di bawah ini berfungsi untuk saya,
mainLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (mainLayout != null) { int heightDiff = mainLayout.getRootView().getHeight() - mainLayout.getHeight(); if (heightDiff > dpToPx(getActivity(), 200)) { //keyboard is open } else { //keyboard is hide } } } });
sumber
Anda dapat menggunakan fungsi ekstensi Rx saya (Kotlin).
/** * @return [Observable] to subscribe of keyboard visibility changes. */ fun AppCompatActivity.keyboardVisibilityChanges(): Observable<Boolean> { // flag indicates whether keyboard is open var isKeyboardOpen = false val notifier: BehaviorSubject<Boolean> = BehaviorSubject.create() // approximate keyboard height val approximateKeyboardHeight = dip(100) // device screen height val screenHeight: Int = getScreenHeight() val visibleDisplayFrame = Rect() val viewTreeObserver = window.decorView.viewTreeObserver val onDrawListener = ViewTreeObserver.OnDrawListener { window.decorView.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) } } val lifeCycleObserver = object : GenericLifecycleObserver { override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event?) { if (source.lifecycle.currentState == Lifecycle.State.DESTROYED) { viewTreeObserver.removeOnDrawListener(onDrawListener) source.lifecycle.removeObserver(this) notifier.onComplete() } } } viewTreeObserver.addOnDrawListener(onDrawListener) lifecycle.addObserver(lifeCycleObserver) return notifier .doOnDispose { viewTreeObserver.removeOnDrawListener(onDrawListener) lifecycle.removeObserver(lifeCycleObserver) } .onTerminateDetach() .hide() }
Contoh:
(context as AppCompatActivity) .keyboardVisibilityChanges() .subscribeBy { isKeyboardOpen -> // your logic }
sumber
dip()
dangetScreenHeight()
Jika Anda bisa, coba untuk memperluas EditText dan mengganti metode '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); }
Bagaimana Anda bisa memperpanjangnya:
Menurut saya, penghitungan ulang ketinggian layar tidak 100% berhasil seperti yang disebutkan sebelumnya. Agar jelas, menimpa 'onKeyPreIme' tidak dipanggil pada metode 'sembunyikan keyboard lunak secara terprogram', TETAPI jika Anda melakukannya di mana saja, Anda harus melakukan logika 'onKeyboardHidden' di sana dan tidak membuat solusi yang komprehensif.
sumber
Ini akan bekerja tanpa perlu mengubah aktivitas Anda
android:windowSoftInputMode
langkah 1: perluas kelas EditText dan timpa keduanya:
@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); }
langkah 2: buat keduanya dalam aktivitas Anda:
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 }
*** Ingat untuk membuat
clearFocus
pekerjaan, Anda harus membuat orang tua atau anak pertama dalam hierarki induk dapat difokuskan.setFocusableInTouchMode(true); setFocusable(true);
sumber
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); } } }); } }
sumber
setOnFocusChangeListener
listener akan dipanggil lalu saya tekan kembali lalu tutup keyboard & tapi tidak klik view lain, sekarang lagi saya klik edittext yang sama yang sudah fokus lalu apa yang akan terjadi?onfocus
pendengar waktu tidak pernah memanggil itu Saya tidak melihat yang Anda sarankanGunakan kelas ini,
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(); } } } }
Di
Android Manifest
,android:windowSoftInputMode="adjustResize"
perlu./* 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(); }
PS - Sepenuhnya diambil dari sini .
sumber
Untuk kasus
adjustResize
dan FragmentActivity, solusi yang diterima dari @Jaap tidak berfungsi untuk saya.Inilah solusi saya:
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; } } };
sumber
Pendekatan yang berbeda adalah memeriksa ketika pengguna berhenti mengetik ...
Saat TextEdit berada dalam fokus (pengguna sedang / sedang mengetik) Anda dapat menyembunyikan tampilan (pendengar fokus)
dan gunakan Handler + Runnable dan pemroses perubahan teks untuk menutup keyboard (terlepas dari visibilitasnya) dan menampilkan tampilan setelah beberapa penundaan.
Hal utama yang harus diperhatikan adalah penundaan yang Anda gunakan, yang akan bergantung pada konten TextEdits ini.
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); } } });
sumber
Kode ini bekerja dengan sangat baik
gunakan kelas ini untuk tampilan root:
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); }
}
dan setel pendengar keyboard dalam aktivitas atau fragmen:
rootLayout.setKeyboardListener(targetEditText, new KeyboardConstraintLayout.KeyboardListener() { @Override public void onKeyboardVisibility(boolean isVisible) { } });
sumber
Anda dapat menangani visibilitas keyboard dengan mengganti dua metode dalam Aktivitas Anda:
onKeyUp()
danonKeyDown()
informasi lebih lanjut di tautan ini: https://developer.android.com/training/keyboard-input/commandssumber
Sayangnya saya tidak memiliki reputasi yang cukup tinggi untuk mengomentari jawaban Jaap van Hengstum. Tetapi saya membaca beberapa komentar orang, memiliki masalah yang
contentViewTop
selalu0
dan yangonShowKeyboard(...)
selalu disebut.Saya memiliki masalah yang sama dan menemukan masalah yang saya alami. Saya menggunakan
AppCompatActivity
bukan 'normal'Activity
. Dalam hal iniWindow.ID_ANDROID_CONTENT
mengacu padaContentFrameLayout
dan bukan keFrameLayout
dengan nilai atas kanan. Dalam kasus saya, tidak masalah menggunakan 'normal'Activity
, jika Anda harus menggunakan jenis aktivitas lain (saya baru saja mengujiAppCompatActivity
, mungkin ini juga merupakan masalah dengan jenis aktivitas lain sepertiFragmentActivity
), Anda harus mengaksesFrameLayout
, yaitu nenek moyang dariContentFrameLayout
.sumber
saat keyboard ditampilkan
rootLayout.getHeight() < rootLayout.getRootView().getHeight() - getStatusBarHeight()
benar, kalau tidak sembunyikan
sumber
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; } } };
Saya telah mengubah sedikit jawaban yang diterima Jaap. Namun dalam kasus saya, ada beberapa asumsi seperti
android:windowSoftInputMode=adjustResize
dan keyboard tidak muncul di awal saat aplikasi dimulai. Dan juga, saya berasumsi bahwa layar tersebut sesuai dengan tinggi induknya.contentHeight > 0
Pemeriksaan ini memberi saya tahu apakah layar terkait disembunyikan atau ditampilkan untuk menerapkan acara keyboard yang mendengarkan untuk layar khusus ini. Saya juga meneruskan tampilan tata letak layar terkait dalam metodeattachKeyboardListeners(<your layout view here>)
aktivitas utama sayaonCreate()
. Setiap kali ketinggian layar berubah, saya menyimpannya keprevContentHeight
variabel untuk memeriksa nanti apakah keyboard ditampilkan atau disembunyikan.Bagi saya, sejauh ini sudah berhasil dengan baik. Saya berharap ini juga berhasil untuk orang lain.
sumber
Jawaban "Jaap van Hengstum" berfungsi untuk saya, tetapi tidak perlu menyetel "android: windowSoftInputMode" seperti yang baru saja dia katakan!
Saya telah membuatnya lebih kecil (sekarang hanya mendeteksi apa yang saya inginkan, sebenarnya sebuah peristiwa yang menunjukkan dan menyembunyikan keyboard):
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); } }
dan jangan lupa untuk menambahkan ini
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_comments); attachKeyboardListeners();}
sumber
Ini tidak berfungsi seperti yang diinginkan ...
... telah melihat banyak menggunakan perhitungan ukuran untuk memeriksa ...
Saya ingin menentukan apakah itu terbuka atau tidak dan saya menemukannya
isAcceptingText()
jadi ini benar-benar tidak menjawab pertanyaan karena tidak membahas pembukaan atau penutupan melainkan lebih seperti buka atau tutup jadi ini adalah kode terkait yang dapat membantu orang lain dalam berbagai skenario ...
dalam suatu aktivitas
if (((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).isAcceptingText()) { Log.d(TAG,"Software Keyboard was shown"); } else { Log.d(TAG,"Software Keyboard was not shown"); }
dalam sebuah fragmen
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"); }
sumber
periksa dengan kode di bawah ini:
KODE XML:
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/coordinatorParent" style="@style/parentLayoutPaddingStyle" android:layout_width="match_parent" android:layout_height="match_parent"> ................. </android.support.constraint.ConstraintLayout>
KODE JAWA:
//Global Variable android.support.constraint.ConstraintLayout activityRootView; boolean isKeyboardShowing = false; private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener; android.support.constraint.ConstraintLayout.LayoutParams layoutParams; //onCreate or onViewAttached activityRootView = view.findViewById(R.id.coordinatorParent); onGlobalLayoutListener = onGlobalLayoutListener(); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener); //outside oncreate ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener() { return new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { Rect r = new Rect(); activityRootView.getWindowVisibleDisplayFrame(r); int screenHeight = activityRootView.getRootView().getHeight(); int keypadHeight = screenHeight - r.bottom; if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height. if (!isKeyboardShowing) { // keyboard is opened isKeyboardShowing = true; onKeyboardVisibilityChanged(true); } } else { if (isKeyboardShowing) { // keyboard is closed isKeyboardShowing = false; onKeyboardVisibilityChanged(false); } } }//ends here }; } void onKeyboardVisibilityChanged(boolean value) { layoutParams = (android.support.constraint.ConstraintLayout.LayoutParams)topImg.getLayoutParams(); if(value){ int length = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 90, getResources().getDisplayMetrics()); layoutParams.height= length; layoutParams.width = length; topImg.setLayoutParams(layoutParams); Log.i("keyboard " ,""+ value); }else{ int length1 = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 175, getResources().getDisplayMetrics()); layoutParams.height= length1; layoutParams.width = length1; topImg.setLayoutParams(layoutParams); Log.i("keyboard " ,""+ value); } } @Override public void onDetach() { super.onDetach(); if(onGlobalLayoutListener != null) { activityRootView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener); } }
sumber
Saya terlambat tetapi saya baru saja menemukan ketergantungan yang sangat nyaman di luar sana. Dengan menggunakannya, Anda dapat memeriksa visibilitas keyboard serta membuat keyboard "Sembunyikan" dan Tampilkan Kapanpun yang Anda inginkan dengan satu Baris Kode.
implementation 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC2'
Dan kemudian Anda cukup menggunakan segmen kode ini untuk memeriksa visibilitas keyboard.
KeyboardVisibilityEvent.setEventListener(this, new KeyboardVisibilityEventListener() { @Override public void onVisibilityChanged(boolean isOpen) { if (isOpen) Toast.makeText(MainActivity.this, "keyboard opened",Toast.LENGTH_SHORT).show(); else Toast.makeText(MainActivity.this, "keyboard hidden", Toast.LENGTH_SHORT).show(); } });
Kemudian jika Anda ingin Sembunyikan / Tampilkan keyboard kapan saja, Anda cukup menulis salah satu baris ini untuk mencapainya.
UIUtil.showKeyboard(this,edittext_to_be_focused); UIUtil.hideKeyboard(this);
sumber
Ada pendengar keyboard yang ditutup.
Kelas
SearchEditText
diturunkan dariandroid.widget.EditText
kelas. Ada antarmukaSearchEditText.OnKeyboardDismissListener
di kelas ini. Anda dapat melihat dokumentasi:https://developer.android.com/reference/androidx/leanback/widget/SearchEditText
Catatan. Sebelum menggunakan SearchEditText, Anda perlu menyiapkan dependensi Gradle di build.gradle (: app):
implementation 'androidx.leanback:leanback:1.1.0-alpha05'
Mungkin seseorang akan berguna.
Tanggapan rinci:
import androidx.appcompat.app.AppCompatActivity; import androidx.leanback.widget.SearchEditText; import android.os.Bundle; import android.widget.Toast; public class MainActivity extends AppCompatActivity implements SearchEditText.OnKeyboardDismissListener { SearchEditText searchEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); searchEditText = findViewById(R.id.search_edit_text); searchEditText.setOnKeyboardDismissListener(this); } /** * Method invoked when the keyboard is dismissed. */ @Override public void onKeyboardDismiss() { Toast.makeText(this, "The listener worked", Toast.LENGTH_LONG).show(); } }
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.leanback.widget.SearchEditText android:id="@+id/search_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="12dp" android:textSize="20sp" android:focusableInTouchMode="true" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
Catatan: pendengar bekerja dengan:
android:windowSoftInputMode="adjustPan" android:windowSoftInputMode="adjustResize"
sumber