Apakah ada cara di Android untuk mendeteksi apakah perangkat lunak (alias "lunak") keyboard terlihat di layar?
Apakah ada cara di Android untuk mendeteksi apakah perangkat lunak (alias "lunak") keyboard terlihat di layar?
Jawaban:
Tidak ada cara langsung - lihat http://groups.google.com/group/android-platform/browse_thread/thread/1728f26f2334c060/5e4910f0d9eb898a di mana Dianne Hackborn dari tim Android telah menjawab. Namun, Anda dapat mendeteksinya secara tidak langsung dengan memeriksa apakah ukuran jendela berubah di #onMeasure. Lihat Bagaimana memeriksa visibilitas papan ketik perangkat lunak di Android? .
Ini bekerja untuk saya. Mungkin ini selalu merupakan cara terbaik untuk semua versi .
Akan lebih efektif untuk membuat properti visibilitas keyboard dan mengamati perubahan ini tertunda karena metode onGlobalLayout memanggil berkali-kali. Juga baik untuk memeriksa rotasi perangkat dan windowSoftInputMode
tidak adjustNothing
.
boolean isKeyboardShowing = false;
void onKeyboardVisibilityChanged(boolean opened) {
print("keyboard " + opened);
}
// ContentView is the root view of the layout of this activity/fragment
contentView.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
contentView.getWindowVisibleDisplayFrame(r);
int screenHeight = contentView.getRootView().getHeight();
// r.bottom is the position above soft keypad or device button.
// if keypad is shown, the r.bottom is smaller than that before.
int keypadHeight = screenHeight - r.bottom;
Log.d(TAG, "keypadHeight = " + keypadHeight);
if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
// keyboard is opened
if (!isKeyboardShowing) {
isKeyboardShowing = true
onKeyboardVisibilityChanged(true)
}
}
else {
// keyboard is closed
if (isKeyboardShowing) {
isKeyboardShowing = false
onKeyboardVisibilityChanged(false)
}
}
}
});
contentView
dinyatakan?
coba ini:
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isAcceptingText()) {
writeToLog("Software Keyboard was shown");
} else {
writeToLog("Software Keyboard was not shown");
}
Saya membuat kelas sederhana yang dapat digunakan untuk ini: https://github.com/ravindu1024/android-keyboardlistener . Cukup salin ke proyek Anda dan gunakan sebagai berikut:
KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
@Override
public void onToggleSoftKeyboard(boolean isVisible)
{
Log.d("keyboard", "keyboard visible: "+isVisible);
}
});
rootView
hanyalah tampilan yang menunjuk ke tampilan root saya dalam hal ini relative layout
:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/addresses_confirm_root_view"
android:background="@color/WHITE_CLR">
RelativeLayout rootView = (RelativeLayout) findViewById(R.id.addresses_confirm_root_view);
getViewTreeObserver()
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();
if (heightDiff > 100) {
Log.e("MyActivity", "keyboard opened");
} else {
Log.e("MyActivity", "keyboard closed");
}
}
});
1
. Tidak penting. Hanya ini yang harus kurang dari panjang keyboard sebenarnya
Saya menggunakan ini sebagai dasar: http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android
/**
* To capture the result of IMM hide/show soft keyboard
*/
public class IMMResult extends ResultReceiver {
public int result = -1;
public IMMResult() {
super(null);
}
@Override
public void onReceiveResult(int r, Bundle data) {
result = r;
}
// poll result value for up to 500 milliseconds
public int getResult() {
try {
int sleep = 0;
while (result == -1 && sleep < 500) {
Thread.sleep(100);
sleep += 100;
}
} catch (InterruptedException e) {
Log.e("IMMResult", e.getMessage());
}
return result;
}
}
Kemudian tulis metode ini:
public boolean isSoftKeyboardShown(InputMethodManager imm, View v) {
IMMResult result = new IMMResult();
int res;
imm.showSoftInput(v, 0, result);
// if keyboard doesn't change, handle the keypress
res = result.getResult();
if (res == InputMethodManager.RESULT_UNCHANGED_SHOWN ||
res == InputMethodManager.RESULT_UNCHANGED_HIDDEN) {
return true;
}
else
return false;
}
Anda kemudian dapat menggunakan ini untuk menguji semua bidang (EditText, AutoCompleteTextView, dll) yang mungkin telah membuka papan tombol softkey:
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
if(isSoftKeyboardShown(imm, editText1) | isSoftKeyboardShown(imm, autocompletetextview1))
//close the softkeyboard
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
Agaknya bukan solusi yang ideal, tetapi itu menyelesaikan pekerjaan.
Anda dapat menggunakan hasil panggilan balik dari showSoftInput () dan hideSoftInput () untuk memeriksa status keyboard. Rincian lengkap dan kode contoh di
http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android
Anda dapat merujuk ke jawaban ini - https://stackoverflow.com/a/24105062/3629912
Itu bekerja untuk saya setiap saat.
adb shell dumpsys window InputMethod | grep "mHasSurface"
Ini akan mengembalikan true, jika keyboard perangkat lunak terlihat.
Jadi setelah lama bermain-main dengan AccessibilityServices, insets jendela, deteksi ketinggian layar, dll, saya pikir saya menemukan cara untuk melakukan ini.
Penafian: menggunakan metode tersembunyi di Android, artinya mungkin tidak konsisten. Namun, dalam pengujian saya, sepertinya berhasil.
Metode ini adalah InputMethodManager # getInputMethodWindowVisibleHeight () , dan sudah ada sejak Lollipop (5.0).
Panggilan yang mengembalikan ketinggian, dalam piksel, dari keyboard saat ini. Secara teori, papan ketik tidak boleh setinggi 0 piksel, jadi saya melakukan pemeriksaan ketinggian sederhana (di Kotlin):
val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
if (imm.inputMethodWindowVisibleHeight > 0) {
//keyboard is shown
else {
//keyboard is hidden
}
Saya menggunakan Android Hidden API untuk menghindari refleksi ketika saya memanggil metode tersembunyi (saya melakukan itu banyak untuk aplikasi yang saya kembangkan, yang sebagian besar merupakan aplikasi peretasan / penyetel), tetapi ini harus dimungkinkan dengan refleksi juga:
val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
val windowHeightMethod = InputMethodManager::class.java.getMethod("getInputMethodWindowVisibleHeight")
val height = windowHeightMethod.invoke(imm) as Int
//use the height val in your logic
Ini jauh lebih rumit untuk persyaratan yang saya butuhkan. Semoga ini bisa membantu:
Di MainActivity:
public void dismissKeyboard(){
InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mSearchBox.getWindowToken(), 0);
mKeyboardStatus = false;
}
public void showKeyboard(){
InputMethodManager imm =(InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
mKeyboardStatus = true;
}
private boolean isKeyboardActive(){
return mKeyboardStatus;
}
Nilai boolean primitif default untuk mKeyboardStatus akan diinisialisasi ke false .
Kemudian periksa nilainya sebagai berikut, dan lakukan tindakan jika perlu:
mSearchBox.requestFocus();
if(!isKeyboardActive()){
showKeyboard();
}else{
dismissKeyboard();
}
Ini akan berfungsi jika Anda perlu memeriksa status keyboard:
fun Activity.isKeyboardOpened(): Boolean {
val r = Rect()
val activityRoot = getActivityRoot()
val visibleThreshold = dip(UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP)
activityRoot.getWindowVisibleDisplayFrame(r)
val heightDiff = activityRoot.rootView.height - r.height()
return heightDiff > visibleThreshold;
}
fun Activity.getActivityRoot(): View {
return (findViewById<ViewGroup>(android.R.id.content)).getChildAt(0);
}
Di mana UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP
= 100 dan dip () adalah fungsi anko yang mengonversi dpToPx:
fun dip(value: Int): Int {
return (value * Resources.getSystem().displayMetrics.density).toInt()
}
Saya melakukan ini dengan menetapkan GlobalLayoutListener, sebagai berikut:
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightView = activityRootView.getHeight();
int widthView = activityRootView.getWidth();
if (1.0 * widthView / heightView > 3) {
//Make changes for Keyboard not visible
} else {
//Make changes for keyboard visible
}
}
});
Coba kode ini benar-benar berfungsi jika KeyboardShown ditampilkan, maka fungsi ini mengembalikan nilai sebenarnya ....
private final String TAG = "TextEditor";
private TextView mTextEditor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_editor);
mTextEditor = (TextView) findViewById(R.id.text_editor);
mTextEditor.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
isKeyboardShown(mTextEditor.getRootView());
}
});
}
private boolean isKeyboardShown(View rootView) {
/* 128dp = 32dp * 4, minimum button height 32dp and generic 4 rows soft keyboard */
final int SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD = 128;
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
/* heightDiff = rootView height - status bar height (r.top) - visible frame height (r.bottom - r.top) */
int heightDiff = rootView.getBottom() - r.bottom;
/* Threshold size: dp to pixels, multiply with display density */
boolean isKeyboardShown = heightDiff > SOFT_KEYBOARD_HEIGHT_DP_THRESHOLD * dm.density;
Log.d(TAG, "isKeyboardShown ? " + isKeyboardShown + ", heightDiff:" + heightDiff + ", density:" + dm.density
+ "root view height:" + rootView.getHeight() + ", rect:" + r);
return isKeyboardShown;
}
Dalam kasus saya, saya hanya punya satu EditText
untuk mengatur tata letak saya jadi saya datang dengan solusi ini . Ini bekerja dengan baik, pada dasarnya itu adalah kebiasaan EditText
yang mendengarkan fokus dan mengirimkan siaran lokal jika fokus berubah atau jika tombol kembali / selesai ditekan. Agar berhasil, Anda perlu menempatkan boneka View
di tata letak Anda android:focusable="true"
dan android:focusableInTouchMode="true"
karena ketika Anda menelepon clearFocus()
fokus akan dipindahkan ke tampilan fokus pertama. Contoh tampilan dummy:
<View
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true"/>
Info tambahan
Solusi yang mendeteksi perbedaan dalam perubahan tata letak tidak bekerja dengan baik karena sangat tergantung pada kepadatan layar, karena 100px bisa banyak di perangkat tertentu dan tidak ada di beberapa orang lain Anda bisa mendapatkan hasil positif palsu. Vendor yang berbeda juga memiliki keyboard yang berbeda.
Di Android Anda dapat mendeteksi melalui shell ADB. Saya menulis dan menggunakan metode ini:
{
JSch jsch = new JSch();
try {
Session session = jsch.getSession("<userName>", "<IP>", 22);
session.setPassword("<Password>");
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
ChannelExec channel = (ChannelExec)session.openChannel("exec");
BufferedReader in = new BufferedReader(new
InputStreamReader(channel.getInputStream()));
channel.setCommand("C:/Android/android-sdk/platform-tools/adb shell dumpsys window
InputMethod | findstr \"mHasSurface\"");
channel.connect();
String msg = null;
String msg2 = " mHasSurface=true";
while ((msg = in.readLine()) != null) {
Boolean isContain = msg.contains(msg2);
log.info(isContain);
if (isContain){
log.info("Hiding keyboard...");
driver.hideKeyboard();
}
else {
log.info("No need to hide keyboard.");
}
}
channel.disconnect();
session.disconnect();
} catch (JSchException | IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
final View activityRootView = findViewById(R.id.rootlayout);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
activityRootView.getWindowVisibleDisplayFrame(r);
int screenHeight = activityRootView.getRootView().getHeight();
Log.e("screenHeight", String.valueOf(screenHeight));
int heightDiff = screenHeight - (r.bottom - r.top);
Log.e("heightDiff", String.valueOf(heightDiff));
boolean visible = heightDiff > screenHeight / 3;
Log.e("visible", String.valueOf(visible));
if (visible) {
Toast.makeText(LabRegister.this, "I am here 1", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(LabRegister.this, "I am here 2", Toast.LENGTH_SHORT).show();
}
}
});
Jawaban dari @iWantScala bagus tetapi tidak bekerja untuk saya
rootView.getRootView().getHeight()
selalu memiliki nilai yang sama
salah satu caranya adalah dengan mendefinisikan dua vars
private int maxRootViewHeight = 0;
private int currentRootViewHeight = 0;
tambahkan pendengar global
rootView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
currentRootViewHeight = rootView.getHeight();
if (currentRootViewHeight > maxRootViewHeight) {
maxRootViewHeight = currentRootViewHeight;
}
}
});
lalu periksa
if (currentRootViewHeight >= maxRootViewHeight) {
// Keyboard is hidden
} else {
// Keyboard is shown
}
bekerja dengan baik
Akhirnya ada cara langsung mulai dari Android R berdasarkan Kotlin sekarang.
val imeInsets = view.rootWindowInsets.getInsets(Type.ime())
if (imeInsets.isVisible) {
//Ime is visible
//Lets move our view by the height of the IME
view.translationX = imeInsets.bottom }
Saya punya masalah serupa. Saya perlu bereaksi terhadap tombol Enter di layar (yang menyembunyikan keyboard). Dalam hal ini Anda dapat berlangganan OnEditorAction dari tampilan teks dengan keyboard yang terbuka - jika Anda memiliki beberapa kotak yang dapat diedit, maka berlanggananlah semuanya.
Di Aktivitas Anda, Anda memiliki kontrol penuh atas keyboard, jadi Anda tidak akan menghadapi masalah apakah keyboard dibuka atau tidak, jika Anda mendengarkan semua acara pembukaan dan penutupan.
Ada metode langsung untuk mengetahuinya. Dan, itu tidak membutuhkan perubahan tata letak.
Jadi ini berfungsi dalam mode layar penuh imersif juga.
Tapi, sayangnya, itu tidak berfungsi di semua perangkat. Jadi, Anda harus mengujinya dengan perangkat Anda.
Caranya adalah Anda mencoba menyembunyikan atau menampilkan keyboard lunak dan menangkap hasil dari percobaan itu.
Jika berfungsi dengan benar maka keyboard tidak benar-benar ditampilkan atau disembunyikan. Kami hanya meminta negara.
Agar tetap terkini, Anda cukup mengulangi operasi ini, misalnya setiap 200 milidetik, menggunakan Handler.
Implementasi di bawah ini hanya melakukan satu pemeriksaan.
Jika Anda melakukan beberapa pemeriksaan, maka Anda harus mengaktifkan semua tes (_keyboardVisible).
public interface OnKeyboardShowHide
{
void onShowKeyboard( Object param );
void onHideKeyboard( Object param );
}
private static Handler _keyboardHandler = new Handler();
private boolean _keyboardVisible = false;
private OnKeyboardShowHide _keyboardCallback;
private Object _keyboardCallbackParam;
public void start( OnKeyboardShowHide callback, Object callbackParam )
{
_keyboardCallback = callback;
_keyboardCallbackParam = callbackParam;
//
View view = getCurrentFocus();
if (view != null)
{
InputMethodManager imm = (InputMethodManager) getSystemService( Activity.INPUT_METHOD_SERVICE );
imm.hideSoftInputFromWindow( view.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY, _keyboardResultReceiver );
imm.showSoftInput( view, InputMethodManager.SHOW_IMPLICIT, _keyboardResultReceiver );
}
else // if (_keyboardVisible)
{
_keyboardVisible = false;
_keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
}
}
private ResultReceiver _keyboardResultReceiver = new ResultReceiver( _keyboardHandler )
{
@Override
protected void onReceiveResult( int resultCode, Bundle resultData )
{
switch (resultCode)
{
case InputMethodManager.RESULT_SHOWN :
case InputMethodManager.RESULT_UNCHANGED_SHOWN :
// if (!_keyboardVisible)
{
_keyboardVisible = true;
_keyboardCallback.onShowKeyboard( _keyboardCallbackParam );
}
break;
case InputMethodManager.RESULT_HIDDEN :
case InputMethodManager.RESULT_UNCHANGED_HIDDEN :
// if (_keyboardVisible)
{
_keyboardVisible = false;
_keyboardCallback.onHideKeyboard( _keyboardCallbackParam );
}
break;
}
}
};
Berikut adalah solusi untuk mengetahui apakah papan tombol softkey terlihat.
Beberapa keyboard populer memiliki kata kunci tertentu di Nama kelasnya:
Dari ActivityManager.RunningServiceInfo, periksa pola di atas di ClassNames. Juga, ActivityManager.RunningServiceInfo clientPackage = android, menunjukkan bahwa keyboard terikat ke sistem.
Informasi yang disebutkan di atas dapat dikombinasikan untuk cara yang ketat untuk mengetahui apakah keyboard lunak terlihat.
Seperti yang Anda ketahui, papan ketik Perangkat Lunak android hanya akan terlihat bila ada kemungkinan pengetikan. Dengan kata lain, Keyboard hanya dapat terlihat bila EditText terfokus. itu berarti Anda bisa mendapatkan cuaca Keyboard terlihat atau tidak dengan menggunakan OnFocusChangeListener .
//Declare this Globally
public boolean isKeyBoardVisible = false;
//In OnCreate *[For Activity]*, OnCreateView *[For Fragment]*
text_send.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
isKeyBoardVisible = true;
else
isKeyBoardVisible = false;
}
});
Sekarang Anda dapat menggunakan variabel isKeyBoardVisible di mana saja di kelas untuk mendapatkan cuaca keyboard Terbuka atau Tidak. Itu bekerja dengan baik untuk saya.
Catatan: Proses ini tidak berfungsi ketika Keyboard dibuka secara terprogram menggunakan InputMethodManager karena itu tidak memanggil OnFocusChangeListener.
Saya mengonversi jawaban ke kotlin, semoga ini membantu pengguna kotlin.
private fun checkKeyboardVisibility() {
var isKeyboardShowing = false
binding.coordinator.viewTreeObserver.addOnGlobalLayoutListener {
val r = Rect()
binding.coordinator.getWindowVisibleDisplayFrame(r)
val screenHeight = binding.coordinator.rootView.height
// r.bottom is the position above soft keypad or device button.
// if keypad is shown, the r.bottom is smaller than that before.
val keypadHeight = screenHeight - r.bottom
if (keypadHeight > screenHeight * 0.15) { // 0.15 ratio is perhaps enough to determine keypad height.
// keyboard is opened
if (!isKeyboardShowing) {
isKeyboardShowing = true
}
} else {
// keyboard is closed
if (isKeyboardShowing) {
isKeyboardShowing = false
}
}
}
}
Ini bekerja dengan menyesuaikan Tidak ada bendera aktivitas dan siklus hidup yang digunakan. Juga dengan Kotlin:
/**
* This class uses a PopupWindow to calculate the window height when the floating keyboard is opened and closed
*
* @param activity The parent activity
* The root activity that uses this KeyboardManager
*/
class KeyboardManager(private val activity: AppCompatActivity) : PopupWindow(activity), LifecycleObserver {
private var observerList = mutableListOf<((keyboardTop: Int) -> Unit)>()
/** The last value of keyboardTop */
private var keyboardTop: Int = 0
/** The view that is used to calculate the keyboard top */
private val popupView: View?
/** The parent view */
private var parentView: View
var isKeyboardShown = false
private set
/**
* Create transparent view which will be stretched over to the full screen
*/
private fun createFullScreenView(): View {
val view = LinearLayout(activity)
view.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)
view.background = ColorDrawable(Color.TRANSPARENT)
return view
}
init {
this.popupView = createFullScreenView()
contentView = popupView
softInputMode = LayoutParams.SOFT_INPUT_ADJUST_RESIZE or LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
inputMethodMode = INPUT_METHOD_NEEDED
parentView = activity.findViewById(android.R.id.content)
width = 0
height = LayoutParams.MATCH_PARENT
popupView.viewTreeObserver.addOnGlobalLayoutListener {
val rect = Rect()
popupView.getWindowVisibleDisplayFrame(rect)
val keyboardTop = rect.bottom
if (this.keyboardTop != keyboardTop) {
isKeyboardShown = keyboardTop < this.keyboardTop
this.keyboardTop = keyboardTop
observerList.forEach { it(keyboardTop) }
}
}
activity.lifecycle.addObserver(this)
}
/**
* This must be called after the onResume of the Activity or inside view.post { } .
* PopupWindows are not allowed to be registered before the onResume has finished
* of the Activity
*/
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun start() {
parentView.post {
if (!isShowing && parentView.windowToken != null) {
setBackgroundDrawable(ColorDrawable(0))
showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0)
}
}
}
/**
* This manager will not be used anymore
*/
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun close() {
activity.lifecycle.removeObserver(this)
observerList.clear()
dismiss()
}
/**
* Set the keyboard top observer. The observer will be notified when the keyboard top has changed.
* For example when the keyboard is opened or closed
*
* @param observer The observer to be added to this provider
*/
fun registerKeyboardTopObserver(observer: (keyboardTop: Int) -> Unit) {
observerList.add(observer)
}
}
Metode yang berguna untuk menjaga tampilan selalu di atas keyboard
fun KeyboardManager.updateBottomMarginIfKeyboardShown(
view: View,
activity: AppCompatActivity,
// marginBottom of view when keyboard is hide
marginBottomHideKeyboard: Int,
// marginBottom of view when keybouard is shown
marginBottomShowKeyboard: Int
) {
registerKeyboardTopObserver { bottomKeyboard ->
val bottomView = ViewUtils.getFullViewBounds(view).bottom
val maxHeight = ScreenUtils.getFullScreenSize(activity.windowManager).y
// Check that view is within the window size
if (bottomView < maxHeight) {
if (bottomKeyboard < bottomView) {
ViewUtils.updateMargin(view, bottomMargin = bottomView - bottomKeyboard +
view.marginBottom + marginBottomShowKeyboard)
} else ViewUtils.updateMargin(view, bottomMargin = marginBottomHideKeyboard)
}
}
}
Di mana getFullViewBounds
fun getLocationOnScreen(view: View): Point {
val location = IntArray(2)
view.getLocationOnScreen(location)
return Point(location[0], location[1])
}
fun getFullViewBounds(view: View): Rect {
val location = getLocationOnScreen(view)
return Rect(location.x, location.y, location.x + view.width,
location.y + view.height)
}
Di mana getFullScreenSize
fun getFullScreenSize(wm: WindowManager? = null) =
getScreenSize(wm) { getRealSize(it) }
private fun getScreenSize(wm: WindowManager? = null, block: Display.(Point) -> Unit): Point {
val windowManager = wm ?: App.INSTANCE.getSystemService(Context.WINDOW_SERVICE)
as WindowManager
val point = Point()
windowManager.defaultDisplay.block(point)
return point
}
Di mana updateMargin
fun updateMargin(
view: View,
leftMargin: Int? = null,
topMargin: Int? = null,
rightMargin: Int? = null,
bottomMargin: Int? = null
) {
val layoutParams = view.layoutParams as ViewGroup.MarginLayoutParams
if (leftMargin != null) layoutParams.leftMargin = leftMargin
if (topMargin != null) layoutParams.topMargin = topMargin
if (rightMargin != null) layoutParams.rightMargin = rightMargin
if (bottomMargin != null) layoutParams.bottomMargin = bottomMargin
view.layoutParams = layoutParams
}
Saya melakukan ini sebagai berikut, tetapi hanya relevan jika tujuan Anda adalah untuk menutup / membuka keyboad.
tutup contoh: (memeriksa apakah keyboard sudah ditutup, jika tidak - menutup)
imm.showSoftInput(etSearch, InputMethodManager.HIDE_IMPLICIT_ONLY, new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
if (resultCode != InputMethodManager.RESULT_UNCHANGED_HIDDEN)
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
});
a mungkin menggunakan:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d(
getClass().getSimpleName(),
String.format("conf: %s", newConfig));
if (newConfig.hardKeyboardHidden != hardKeyboardHidden) {
onHardwareKeyboardChange(newConfig.hardKeyboardHidden);
hardKeyboardHidden = newConfig.hardKeyboardHidden;
}
if (newConfig.keyboardHidden != keyboardHidden) {
onKeyboardChange(newConfig.keyboardHidden);
keyboardHidden = newConfig.hardKeyboardHidden;
}
}
public static final int KEYBOARDHIDDEN_UNDEFINED = 0;
public static final int KEYBOARDHIDDEN_NO = 1;
public static final int KEYBOARDHIDDEN_YES = 2;
public static final int KEYBOARDHIDDEN_SOFT = 3;
//todo
private void onKeyboardChange(int keyboardHidden) {
}
//todo
private void onHardwareKeyboardChange(int hardKeyboardHidden) {
}
Saya menulis sampel .
Repositori ini dapat membantu mendeteksi status keyboard tanpa asumsi bahwa "keyboard harus lebih dari X bagian layar"
Jika Anda mendukung apis untuk AndroidR di aplikasi Anda, maka Anda dapat menggunakan metode di bawah ini.
In kotlin :
var imeInsets = view.rootWindowInsets.getInsets(Type.ime())
if (imeInsets.isVisible) {
view.translationX = imeInsets.bottom
}
Catatan: Ini hanya tersedia untuk AndroidR dan versi Android di bawah ini perlu mengikuti beberapa jawaban lain atau saya akan memperbaruinya untuk itu.