1. 程式人生 > >如何監聽軟鍵盤的彈出、隱藏(親測可用)

如何監聽軟鍵盤的彈出、隱藏(親測可用)

看了N多文章,終於找到了答案

第一步

注意:必須設定
android:windowSoftInputMode="adjustResize"

原理

注意下面的activityRootView對應的R.id.activityRoot,是你整個佈局的根佈局
原理就是通過判斷手機螢幕的高度與你的根佈局的高度的差值,作為判斷軟鍵盤,彈起、消失的依據
因為當 android:windowSoftInputMode=”adjustResize”`時,軟鍵盤彈出時,會壓縮你的根佈局的顯示高度。根據這個高度的前後變化,來反映軟鍵盤的彈出和隱藏

但是,通過列印log可以發現當你的activity的主題使用了FullScreen之後你的根佈局的高度,在軟鍵盤彈出、隱藏時,就不變了,所以無法通過上述方法,判斷監聽軟鍵盤事件,至於怎麼解決的,看第二篇文章即可

如果你的activity不是採用FullScreen,使用第一種方法就可以

程式碼

  1. 直接在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
    (heightDiff > dpToPx(this, 200)) { // 顯示軟鍵盤 }else{ //隱藏軟鍵盤 } } });
  2. 上面用到的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,使得上文說到的“你的根佈局的高度”,在軟鍵盤彈出、隱藏時候,發生了改變,從而監聽了軟鍵盤彈出、隱藏的事件
至於為什麼加入這個類,會得到這個效果,我暫時還沒有研究

  1. 寫一個類

    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);
        }
    
    }
  2. 在你的Activity裡只需呼叫下面一句話即可

    AndroidBug5497Workaround.assistActivity(this);

下面貼出所有程式碼

  1. 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>
         ......
  2. 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);
        }
    }
    
  3. 神奇類 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);
            }
    
        }
    
  4. 佈局

    <?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>