如何監聽軟鍵盤的彈出、隱藏(親測可用)
阿新 • • 發佈:2019-02-01
看了N多文章,終於找到了答案
第一步
注意:必須設定
android:windowSoftInputMode="adjustResize"
原理
注意下面的activityRootView對應的R.id.activityRoot,是你整個佈局的根佈局
原理就是通過判斷手機螢幕的高度與你的根佈局的高度的差值,作為判斷軟鍵盤,彈起、消失的依據
因為當 android:windowSoftInputMode=”adjustResize”`時,軟鍵盤彈出時,會壓縮你的根佈局的顯示高度。根據這個高度的前後變化,來反映軟鍵盤的彈出和隱藏但是,通過列印log可以發現當你的activity的主題使用了FullScreen之後你的根佈局的高度,在軟鍵盤彈出、隱藏時,就不變了,所以無法通過上述方法,判斷監聽軟鍵盤事件,至於怎麼解決的,看第二篇文章即可
如果你的activity不是採用FullScreen,使用第一種方法就可以
程式碼
直接在Activity裡新增即可
final View activityRootView = findViewById(R.id.activityRoot); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight(); if
上面用到的dp轉px方法
public static float dpToPx(Context context, float valueInDp) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics); }
第二步
注意:必須設定
android:windowSoftInputMode="adjustResize"很顯然,通過寫了一個類AndroidBug5497Workaround,使得上文說到的“你的根佈局的高度”,在軟鍵盤彈出、隱藏時候,發生了改變,從而監聽了軟鍵盤彈出、隱藏的事件
至於為什麼加入這個類,會得到這個效果,我暫時還沒有研究
寫一個類
public class AndroidBug5497Workaround { // For more information, see https://code.google.com/p/android/issues/detail?id=5497 // To use this class, simply invoke assistActivity() on an Activity that already has its content view set. public static void assistActivity (Activity activity) { new AndroidBug5497Workaround(activity); } private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; private AndroidBug5497Workaround(Activity activity) { FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard/4)) { // keyboard probably just became visible frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; } else { // keyboard probably just became hidden frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom - r.top); } }
在你的Activity裡只需呼叫下面一句話即可
AndroidBug5497Workaround.assistActivity(this);
下面貼出所有程式碼
manifest.xml
...... <activity android:theme="@style/AppTheme" android:name=".Main3Activity" ★android:windowSoftInputMode="adjustResize"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> ......
MainActivity(忽略我列印的那些log)
public class Main3Activity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main3); AndroidBug5497Workaround.assistActivity(this); final LinearLayout activityRootView = (LinearLayout) findViewById(R.id.activity_main3); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight(); if (heightDiff > dpToPx(Main3Activity.this, 150)) { // if more than 200 dp, it's probably a keyboard... // ... do something here Log.e("hhh","show------------"); Log.e("hhh","-----activityRootView.getRootView().getHeight()"+activityRootView.getRootView().getHeight()); Log.e("hhh","-----activityRootView.getHeight()"+activityRootView.getHeight()); Log.e("hhh","heightDiff------------"+heightDiff); findViewById(R.id.ivv).setVisibility(View.GONE); }else { Log.e("hhh","hidden============="); Log.e("hhh","=====activityRootView.getRootView().getHeight()"+activityRootView.getRootView().getHeight()); Log.e("hhh","=====activityRootView.getHeight()"+activityRootView.getHeight()); Log.e("hhh","heightDiff====="+heightDiff); findViewById(R.id.ivv).setVisibility(View.VISIBLE); } } }); } public static float dpToPx(Context context, float valueInDp) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, valueInDp, metrics); } }
神奇類 AndroidBug5497Workaround
package com.demo.ruanjianpandemo; import android.app.Activity; import android.graphics.Rect; import android.view.View; import android.view.ViewTreeObserver; import android.widget.FrameLayout; public class AndroidBug5497Workaround { // For more information, see https://code.google.com/p/android/issues/detail?id=5497 // To use this class, simply invoke assistActivity() on an Activity that already has its content view set. public static void assistActivity (Activity activity) { new AndroidBug5497Workaround(activity); } private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; private AndroidBug5497Workaround(Activity activity) { FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard/4)) { // keyboard probably just became visible frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; } else { // keyboard probably just became hidden frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom - r.top); } }
佈局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main3" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.demo.ruanjianpandemo.Main3Activity"> <ImageView android:id="@+id/ivv" android:src="@mipmap/ic_launcher" android:layout_width="match_parent" android:layout_height="300dp" /> <com.demo.ruanjianpandemo.MyEditText android:id="@+id/myedittext" android:layout_width="match_parent" android:layout_height="wrap_content" /> <com.demo.ruanjianpandemo.MyEditText android:id="@+id/myedittext1" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>