Có cách nào trong Android để phát hiện nếu bàn phím phần mềm (còn gọi là "mềm") hiển thị trên màn hình không?
Có cách nào trong Android để phát hiện nếu bàn phím phần mềm (còn gọi là "mềm") hiển thị trên màn hình không?
Câu trả lời:
Không có cách nào trực tiếp - hãy xem http://groups.google.com/group/android-pl platform / browse_thread / thread / 1728f26f2334c060/5e4910f0d9eb898a nơi Dianne Hackborn từ nhóm Android đã trả lời. Tuy nhiên, bạn có thể phát hiện nó một cách gián tiếp bằng cách kiểm tra xem kích thước cửa sổ có thay đổi trong #onMeasure không. Xem Cách kiểm tra mức độ hiển thị của bàn phím phần mềm trong Android? .
Điều này làm việc cho tôi. Có lẽ đây luôn là cách tốt nhất cho tất cả các phiên bản .
Sẽ rất hiệu quả khi tạo một thuộc tính hiển thị bàn phím và quan sát các thay đổi này bị trì hoãn vì phương thức onGlobalLayout gọi nhiều lần. Ngoài ra nó là tốt để kiểm tra vòng quay thiết bị và windowSoftInputMode
không 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
tuyên bố ở đâu?
thử cái này:
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isAcceptingText()) {
writeToLog("Software Keyboard was shown");
} else {
writeToLog("Software Keyboard was not shown");
}
Tôi đã tạo một lớp đơn giản có thể được sử dụng cho việc này: https://github.com/ravindu1024/android-keyboardlistener . Chỉ cần sao chép nó vào dự án của bạn và sử dụng như sau:
KeyboardUtils.addKeyboardToggleListener(this, new KeyboardUtils.SoftKeyboardToggleListener()
{
@Override
public void onToggleSoftKeyboard(boolean isVisible)
{
Log.d("keyboard", "keyboard visible: "+isVisible);
}
});
rootView
chỉ là một khung nhìn trỏ đến khung nhìn gốc của tôi trong trường hợp này 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
. Không vấn đề. Chỉ điều này phải nhỏ hơn chiều dài thực của bàn phím
Tôi đã sử dụng điều này như là một cơ sở: 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;
}
}
Sau đó viết phương pháp này:
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;
}
Sau đó, bạn có thể sử dụng điều này để kiểm tra tất cả các trường (EditText, AutoCompleteTextView, v.v.) có thể đã mở một phím chức năng:
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);
Addmittely không phải là một giải pháp lý tưởng, nhưng nó hoàn thành công việc.
Bạn có thể sử dụng kết quả gọi lại của showSoftInput () và hideSoftInput () để kiểm tra trạng thái của bàn phím. Chi tiết đầy đủ và mã ví dụ tại
http://www.ninthavenue.com.au/how-to-check-if-the-software-keyboard-is-shown-in-android
Bạn có thể tham khảo câu trả lời này - https://stackoverflow.com/a/24105062/3629912
Nó làm việc cho tôi mọi lúc.
adb shell dumpsys window InputMethod | grep "mHasSurface"
Nó sẽ trả về true, nếu bàn phím phần mềm hiển thị.
Vì vậy, sau một thời gian dài chơi xung quanh với AccessService, chèn cửa sổ, phát hiện chiều cao màn hình, v.v., tôi nghĩ rằng tôi đã tìm ra cách để làm điều này.
Tuyên bố từ chối trách nhiệm: nó sử dụng một phương thức ẩn trong Android, có nghĩa là nó có thể không nhất quán. Tuy nhiên, trong thử nghiệm của tôi, nó dường như hoạt động.
Phương thức này là InputMethodManager # getInputMethodWindowVisibleHeight () và nó đã tồn tại từ Lollipop (5.0).
Gọi mà trả về chiều cao, tính bằng pixel, của bàn phím hiện tại. Về lý thuyết, bàn phím không nên cao 0 pixel, vì vậy tôi đã thực hiện kiểm tra chiều cao đơn giản (trong Kotlin):
val imm by lazy { context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager }
if (imm.inputMethodWindowVisibleHeight > 0) {
//keyboard is shown
else {
//keyboard is hidden
}
Tôi sử dụng API ẩn của Android để tránh phản xạ khi tôi gọi các phương thức ẩn (tôi làm điều đó rất nhiều cho các ứng dụng tôi phát triển, chủ yếu là các ứng dụng hacky / tuner), nhưng điều này cũng có thể xảy ra với sự phản chiếu:
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
Điều này ít phức tạp hơn cho các yêu cầu tôi cần. Hy vọng điều này có thể giúp:
Trên 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;
}
Giá trị boolean nguyên thủy mặc định cho mPalStatus sẽ được khởi tạo thành false .
Sau đó kiểm tra giá trị như sau và thực hiện một hành động nếu cần:
mSearchBox.requestFocus();
if(!isKeyboardActive()){
showKeyboard();
}else{
dismissKeyboard();
}
Điều này sẽ hoạt động nếu bạn cần kiểm tra trạng thái bàn phím:
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);
}
Trong đó UiUtils.KEYBOARD_VISIBLE_THRESHOLD_DP
= 100 và dip () là một func anko chuyển đổi dpToPx:
fun dip(value: Int): Int {
return (value * Resources.getSystem().displayMetrics.density).toInt()
}
Tôi đã làm điều này bằng cách thiết lập GlobalLayoutListener, như sau:
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
}
}
});
Hãy thử mã này, nó thực sự hoạt động nếu KeyboardShown được hiển thị thì hàm này trả về giá trị thực ....
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;
}
Trong trường hợp của tôi, tôi chỉ có một EditText
để quản lý trong bố trí của mình vì vậy tôi đã đưa ra giải pháp này . Nó hoạt động tốt, về cơ bản nó là một tùy chỉnh EditText
nghe lấy nét và gửi một phát sóng cục bộ nếu tiêu điểm thay đổi hoặc nếu nhấn nút quay lại / thực hiện. Để làm việc, bạn cần đặt một hình nộm View
trong bố cục của mình android:focusable="true"
và android:focusableInTouchMode="true"
bởi vì khi bạn gọi clearFocus()
tiêu điểm sẽ được gán lại cho chế độ xem tập trung đầu tiên. Ví dụ về chế độ xem giả:
<View
android:layout_width="1dp"
android:layout_height="1dp"
android:focusable="true"
android:focusableInTouchMode="true"/>
Thông tin bổ sung
Giải pháp phát hiện sự khác biệt trong thay đổi bố cục không hoạt động tốt vì nó phụ thuộc nhiều vào mật độ màn hình, vì 100px có thể có rất nhiều trong một thiết bị nhất định và không có gì ở một số thiết bị khác mà bạn có thể nhận được thông báo sai. Ngoài ra các nhà cung cấp khác nhau có bàn phím khác nhau.
Trong Android, bạn có thể phát hiện thông qua trình bao ADB. Tôi đã viết và sử dụng phương pháp này:
{
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();
}
}
});
Trả lời của @iWantScala rất tuyệt nhưng không hiệu quả với tôi
rootView.getRootView().getHeight()
luôn có cùng giá trị
một cách là xác định hai vars
private int maxRootViewHeight = 0;
private int currentRootViewHeight = 0;
thêm người nghe toàn cầu
rootView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
currentRootViewHeight = rootView.getHeight();
if (currentRootViewHeight > maxRootViewHeight) {
maxRootViewHeight = currentRootViewHeight;
}
}
});
sau đó kiểm tra
if (currentRootViewHeight >= maxRootViewHeight) {
// Keyboard is hidden
} else {
// Keyboard is shown
}
hoạt động tốt
Cuối cùng cũng có một cách trực tiếp bắt đầu từ Android R dựa trên Kotlin.
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 }
Tôi đã có một vấn đề tương tự. Tôi cần phải phản ứng với nút Enter trên màn hình (ẩn bàn phím). Trong trường hợp này, bạn có thể đăng ký OnEditorAction của chế độ xem văn bản mà bàn phím đã phản đối - nếu bạn có nhiều hộp có thể chỉnh sửa, sau đó đăng ký vào tất cả chúng.
Trong Hoạt động của bạn, bạn có toàn quyền kiểm soát bàn phím, do đó, bạn sẽ không phải đối mặt với vấn đề liệu bàn phím có được mở hay không, nếu bạn lắng nghe tất cả các sự kiện mở và đóng.
Có một phương pháp trực tiếp để tìm ra điều này. Và, nó không yêu cầu thay đổi bố cục.
Vì vậy, nó hoạt động trong chế độ toàn màn hình nhập vai, quá.
Nhưng, thật không may, nó không hoạt động trên tất cả các thiết bị. Vì vậy, bạn phải kiểm tra nó với (các) thiết bị của bạn.
Mẹo nhỏ là bạn cố gắng ẩn hoặc hiển thị bàn phím mềm và nắm bắt kết quả của lần thử đó.
Nếu nó hoạt động chính xác thì bàn phím không thực sự được hiển thị hoặc ẩn. Chúng tôi chỉ yêu cầu nhà nước.
Để luôn cập nhật, bạn chỉ cần lặp lại thao tác này, ví dụ cứ sau 200 mili giây, sử dụng Trình xử lý.
Việc thực hiện dưới đây chỉ là một kiểm tra duy nhất.
Nếu bạn thực hiện nhiều kiểm tra, thì bạn nên kích hoạt tất cả các bài kiểm tra (_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;
}
}
};
Đây là một cách giải quyết để biết nếu phím chức năng có thể nhìn thấy.
Một số bàn phím phổ biến có các từ khóa nhất định trong classNames của chúng:
Từ ActivityManager.RastyServiceInfo, hãy kiểm tra các mẫu trên trong ClassNames. Ngoài ra, ActivityManager.RastyServiceInfo ' clientPackage = android, chỉ ra rằng bàn phím bị ràng buộc với hệ thống.
Các thông tin được đề cập ở trên có thể được kết hợp theo một cách nghiêm ngặt để tìm hiểu xem có thể nhìn thấy bàn phím mềm hay không.
Như bạn có thể biết bàn phím Phần mềm Android sẽ chỉ hiển thị khi có thể xảy ra sự cố gõ. Nói cách khác, Bàn phím chỉ hiển thị khi EditText được tập trung. điều đó có nghĩa là bạn có thể nhận được thời tiết Bàn phím có thể nhìn thấy hay không bằng cách sử dụng OnF FocusChangeListener .
//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;
}
});
Bây giờ bạn có thể sử dụng isKeyBoardVisible biến ở bất cứ đâu trong lớp để theo dõi thời tiết bàn phím có mở hay không. Nó làm việc tốt cho tôi.
Lưu ý: Quá trình này không hoạt động khi Bàn phím được mở bằng lập trình bằng InputMethodManager vì điều đó không gọi OnF FocusChangeListener.
Tôi đã chuyển đổi câu trả lời cho kotlin, hy vọng điều này sẽ giúp cho người dùng 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
}
}
}
}
Nó hoạt động với cờ điều chỉnh Hoạt động và các sự kiện vòng đời được sử dụng. Ngoài ra với 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)
}
}
Phương pháp hữu ích để giữ chế độ xem luôn ở phía trên bàn phím
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)
}
}
}
Trường hợp getFullViewBound
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)
}
Trường hợp 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
}
Nơi cập nhậtMargin
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
}
Tôi đã làm điều này như sau, nhưng chỉ có liên quan nếu mục tiêu của bạn là đóng / mở keyboad.
đóng ví dụ: (kiểm tra xem bàn phím đã đóng chưa, nếu không - đóng)
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 có thể đang sử dụng:
@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) {
}
Tôi đã viết mẫu .
Kho lưu trữ này có thể giúp phát hiện trạng thái bàn phím mà không giả định rằng "bàn phím phải nhiều hơn một phần X của màn hình"
Nếu bạn hỗ trợ apis cho AndroidR trong ứng dụng của mình thì bạn có thể sử dụng phương pháp dưới đây.
In kotlin :
var imeInsets = view.rootWindowInsets.getInsets(Type.ime())
if (imeInsets.isVisible) {
view.translationX = imeInsets.bottom
}
Lưu ý: Điều này chỉ có sẵn cho AndroidR và bên dưới phiên bản Android cần phải làm theo một số câu trả lời khác hoặc tôi sẽ cập nhật nó cho điều đó.