Android軟鍵盤與工具面板的切換

小蝸牛06 8年前發布 | 10K 次閱讀 安卓開發 Android開發 移動開發

老規矩,效果圖先上

我是效果圖

點擊輸入框,軟鍵盤彈起

點擊Switch按鈕時,軟鍵盤與面板進行切換

觸碰空白處,軟鍵盤與面板均隱藏

這個效果的關鍵點是獲取軟鍵盤的高度(我們用變量KeyboardHeight代表軟鍵盤的高度),將面板的高度設置為KeyboardHeight,那么切換時,輸入框在屏幕的位置就巋然不動了,看似簡單,實際上要獲取KeyboardHeight要花些許功夫。

先上布局。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_chat_room"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.hayukleung.kps.ChatRoomActivity"
    >
  <ScrollView
      android:id="@+id/kps_content"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_above="@+id/kps_bottom"
      >
  </ScrollView>
  <LinearLayout
      android:id="@+id/kps_bottom"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_alignParentBottom="true"
      android:orientation="vertical"
      >
    <RelativeLayout
        android:id="@+id/kps_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
      <EditText
          android:id="@+id/kps_text"
          android:layout_width="match_parent"
          android:layout_height="40dp"
          android:layout_centerVertical="true"
          android:layout_toLeftOf="@+id/kps_switch_panel"
          />
      <Button
          android:id="@+id/kps_switch_panel"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_alignParentEnd="true"
          android:layout_centerVertical="true"
          android:text="switch\npanel and keyboard"
          android:textSize="10sp"
          />
    </RelativeLayout>
    <View
        android:id="@+id/kps_panel"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/colorPrimary"
        />
  </LinearLayout>
</RelativeLayout>

Android Screen Size

從上圖可以得出KeyboardHeight與屏幕各部分尺寸值得算術關系,我們逐一將它們計算出來。

軟鍵盤的彈起

首先我們要了解Android軟鍵盤彈起時Activity的布局變化情況,設置SOFT_INPUT_ADJUST_RESIZE,Activity的布局會根據軟鍵盤的高度壓縮自己,設置SOFT_INPUT_ADJUST_PAN,Activity的布局只會保證輸入框焦點出的位置不被軟鍵盤遮擋,將布局往上推 最小 的距離。我們計算軟鍵盤的做法就是利用 SOFT_INPUT_ADJUST_RESIZE 的特點,軟鍵盤彈起時Activity設置為SOFT_INPUT_ADJUST_RESIZE。這樣就可以得到Activity的布局高度的變化值,這個值就與軟鍵盤的高度有關了。

/**

  • 顯示鍵盤 */ private void showKeyboard() { mInputMethodManager.showSoftInput(mKpsText, SHOW_IMPLICIT); setSoftInputMode(SOFT_INPUT_STATE_UNCHANGED | SOFT_INPUT_ADJUST_RESIZE); } /**
  • 隱藏鍵盤 */ private void hideKeyboard() { mInputMethodManager.hideSoftInputFromWindow(mKpsText.getWindowToken(), HIDE_NOT_ALWAYS); setSoftInputMode(SOFT_INPUT_STATE_UNCHANGED | SOFT_INPUT_ADJUST_PAN); } /**
  • 動態更改軟鍵盤模式 *
  • Desired operating mode for any soft input area. May be any combination of: *
  • <ul>
  • <li> One of the visibility states
  • {@link #SOFT_INPUT_STATE_UNSPECIFIED},
  • {@link #SOFT_INPUT_STATE_UNCHANGED},
  • {@link #SOFT_INPUT_STATE_HIDDEN},
  • {@link #SOFT_INPUT_STATE_VISIBLE},
  • {@link #SOFT_INPUT_STATE_ALWAYS_HIDDEN},
  • {@link #SOFT_INPUT_STATE_ALWAYS_VISIBLE}.
  • <li> One of the adjustment options
  • {@link #SOFT_INPUT_ADJUST_NOTHING},
  • {@link #SOFT_INPUT_ADJUST_UNSPECIFIED},
  • {@link #SOFT_INPUT_ADJUST_RESIZE},
  • {@link #SOFT_INPUT_ADJUST_PAN}. *
  • @param mode */ private void setSoftInputMode(int mode) { getWindow().setSoftInputMode(mode); }</code></pre>

    要監聽Activity高度的變化,可以對Activity的根布局設置OnGlobalLayoutListener監聽。一旦布局的大小發生變化就會執行里面的onGlobalLayout方法,我們會在該方法完成對軟鍵盤高度的計算。一開始軟鍵盤未彈起時,該方法會一直空轉,一旦彈起,我們就拿到了數據完成計算,完成了計算及時移除該監聽,避免不必要的性能損耗。

    // mActivityChatRoom是根布局Layout,軟鍵盤彈起時會引起它的布局大小變化,對它進行布局變化監聽
    mActivityChatRoom.getViewTreeObserver()
     .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
       private int keyboardHeight = 0;
       private boolean hasNavigationBar = true;
       @Override public void onGlobalLayout() {
         // TODO 計算StatusBarHeight
         // TODO 計算ActionBarHeight
         // TODO 計算NavigationBarHeight
         // TODO 計算ScreenHeight
         // TODO 計算ActivityHeight
         // TODO 計算KeyboardHeight
         if (0 < keyboardHeight) {
           // 成功計算得到KeyboardHeight,及時移除監聽
           mActivityChatRoom.getViewTreeObserver()
             .removeOnGlobalLayoutListener(this);
         }
       }
     });

    StatusBarHeight

    Rect rect = new Rect();
    getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
    int statusBarHeight = rect.top;

    ActionBarHeight

    TypedValue tv = new TypedValue();
    getTheme().resolveAttribute(R.attr.actionBarSize, tv, true);
    int actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, getResources().getDisplayMetrics());

    NavigationBarHeight

    Resources resources = getResources();
    int navigationBarHeight = resources.getDimensionPixelSize(resources.getIdentifier("navigation_bar_height","dimen", "android"));

    計算NavigationBarHeight時需要注意,我們的手機如果不存在NavigationBar,這個值算出來并不是0,所以不能簡單的通過該值判斷手機是否存在NavigationBar,需要進行一步額外的判斷。具體是,鍵盤未彈起時計算得到的KeyboardHeight應該是0,如果計算出來的值是-NavigationBarHeight,說明該手機沒有NavigationBar,這時候將NavigationBar不存在的布爾狀態記錄下來,等到軟鍵盤彈起計算高度時就根據該布爾量忽略掉NavigationBarHeight。

    ScreenHeight & ActivityHeight

    // mActivityChatRoom是根布局Layout
    int screenHeight = mActivityChatRoom.getRootView().getHeight();
    int activityHeight = mActivityChatRoom.getHeight();

    KeyboardHeight

    keyboardHeight = screenHeight - activityHeight - statusBarHeight - actionBarHeight - navigationBarHeight;
    if (0 == keyboardHeight + navigationBarHeight) {
    // 不存在navigation bar
    hasNavigationBar = false;
    }
    keyboardHeight += hasNavigationBar ? 0 : navigationBarHeight;
    ViewGroup.LayoutParams params = mKpsPanel.getLayoutParams();
    params.height = keyboardHeight;mKpsPanel.setLayoutParams(params);

     

     

    來自:http://www.jianshu.com/p/46a5dfe96a66

     

 本文由用戶 小蝸牛06 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!