Android 關于軟鍵盤的三個故事

前言

有輸入框的地方

就有軟鍵盤

那是一種洪鸭,會呼吸的痛

第一個故事

留言板

錯誤的打開方式

錯誤的打開姿勢.gif

仔細觀察會發(fā)現间影,當軟鍵盤彈出時 background膛锭、recyclerview搀罢、toolbar軟鍵盤頂上去了腋粥!這樣的交互簡直不能忍晦雨,對用戶來說也非常突兀架曹。

正確的打開方式

正確的打開姿勢.gif

軟鍵盤彈出只是遮蓋了 background 一部分,background 沒有被壓縮闹瞧。

實現

1. AndroidMainifest.xml 配置文件

<activity
      android:name=".MainActivity"
      android:windowSoftInputMode="adjustResize">

2. activity_main.xml 布局文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent">


  <!-- 關鍵處绑雄,用 ScrollView 包裹 ImageView -->
  <ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:adjustViewBounds="true" 
      android:scaleType="centerCrop"
      android:src="@mipmap/bg_leave_msg_board" />

  </ScrollView>

  <!-- Toolbar-->
  <include layout="@layout/view_msg_board_app_bar_layout" />

  <!-- Recyclerview-->
  <geeklub.org.hellovass.endless_recyclerview.widget.HVEndlessRecyclerView
    android:id="@+id/rv_msg_board"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />


  <!-- 輸入框-->
  <geeklub.org.messageboarddemo.widget.LeaveMessageBoard
    android:id="@+id/leave_msg_board"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    android:background="@android:color/white"
    app:layout_behavior="geeklub.org.messageboarddemo.LeaveMessageViewBehavior" />

</android.support.design.widget.CoordinatorLayout>


目瞪口呆,為什么這樣搞定了奥邮?

android:windowSoftInputMode 屬性

Value Description
adjustPan 軟鍵盤彈出時万牺,Activity 主窗口不會調整大小留出空間給軟鍵盤。相反洽腺,window 的內容將自動移動以便當前焦點不被鍵盤覆蓋(用戶總是能看到輸入內容的部分)
adjustResize 軟鍵盤彈出時脚粟,對 Activity 主窗口調整大小以留出軟鍵盤的空間

很明顯,錯誤的姿勢.gif 中使用的是第一種屬性蘸朋。

android:windowSoftInputMode = adjustResize 時, Activity 究竟做了什么?

簡單自定義 ImageView核无、ScrollView,打印出關鍵信息

public class HVImageView extends ImageView {

  private static final String TAG = HVImageView.class.getSimpleName();

  //  省略部分代碼...

  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    Log.i(TAG, "onMeasure,height -->" + MeasureSpec.getSize(heightMeasureSpec));
  }

  @Override protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout(changed, l, t, r, b);
    Log.i(TAG, "onLayout,left -->" + l + ",top -->>" + t + ", right -->>" + r + ",bottom -->>" + b);
  }

  @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    Log.i(TAG, "onSizeChanged,width -->"
        + w
        + ",height -->>"
        + h
        + ", oldWidth -->>"
        + oldw
        + ",oldHeight -->>"
        + oldh);
  }
}

//  省略自定義 HVScrollView 代碼

bg_leave_msg_board.jpg
背景圖片(width = 1080px,height = 1917px)
HVImageView 的 log 信息
第一次啟動時
第一次啟動
軟鍵盤彈出時
軟鍵盤彈出時
軟鍵盤隱藏時
軟鍵盤隱藏時

從 log 中可以看出度液,從第一次啟動后 ImageView 的onSizeChanged 就不再執(zhí)行厕宗。軟鍵盤無論隱藏或彈出,bottom 的值一直是 2130px堕担。

HVScrollView 的 log 信息
第一次啟動時
第一次啟動
鍵盤彈出時
鍵盤彈出時
鍵盤隱藏時
鍵盤隱藏時

從 log 中可以看出已慢,ScrollView 的 onSizeChanged 是一直會被調用的。鍵盤彈出時霹购,height:1776px->1072px; 鍵盤隱藏時佑惠,height:1072px ->1776px。

分析
思路
  1. ImageView 的長寬比應該與背景圖的長寬比(1080px / 1917px = 0.5634)相同齐疙。背景圖需要完整顯示在 ImageView膜楷,并且占滿 ImageView。

  2. windowSoftInputMode 設置為 adjustResize贞奋, Activity 主窗口調整大小時 ImageView 的 height 需要保持不變赌厅。

利用 adjustViewBounds 屬性解決第一個問題
ImageView 的 adjustViewBounds 屬性

設置為 true 的時候調整 ImageView 的邊界來保持 drawable 的長寬比

此時轿塔,ImageView 的 height = 屏幕的寬度(1200px) / 圖片長寬比(0.56) = 2130px特愿。

使用 ScrollView 包裹 ImageView 解決第二個問題

ScrollView 的 onSizeChanged 方法會在軟鍵盤彈出、隱藏時被調用勾缭,而 ImageView 的 onSizeChanged 不會被調用揍障,height 也就不會變化了。

軟鍵盤彈出時俩由,ScrollView 高度減小毒嫡,ImageView 的高度不變(這點很重要),我們能看到的背景圖區(qū)域就縮小了幻梯,背景圖被軟鍵盤覆蓋兜畸。

同理努释,軟鍵盤隱藏時也一樣。

到這里膳叨,疑問也差不多解答完了...

補充得到軟鍵盤高度的幾種方法

其實這個問題和背景圖被壓縮并沒有一毛錢關系洽洁,但是,如果要做到 QQ 聊天頁面相近的體驗——鍵盤彈出時菲嘴,將 recyclerview/listview 滾動對應的距離(鍵盤的高度),這時候汰翠,如果能 SDK 里直接提供了這樣的方法該多好啊龄坪。然而,并沒有复唤!

方法一

 /**
   * 得到虛擬按鍵的高度
   *
   * @return 虛擬按鍵的高度
   */
  @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) public static int getSupportNavigationBarHeight(
      Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

    // 獲取可用的高度
    DisplayMetrics defaultDisplayMetrics = new DisplayMetrics();
    windowManager.getDefaultDisplay().getMetrics(defaultDisplayMetrics);
    int usableHeight = defaultDisplayMetrics.heightPixels;

    // 獲取實際的高度
    DisplayMetrics realDisplayMetrics = new DisplayMetrics();
    windowManager.getDefaultDisplay().getRealMetrics(realDisplayMetrics);
    int realHeight = realDisplayMetrics.heightPixels;

    return realHeight > usableHeight ? realHeight - usableHeight : 0;
  }

  /**
   * 得到當前軟鍵盤的高度
   *
   * @return 軟鍵盤的高度
   */
  public static int getSoftInputHeight(Activity activity) {
    Rect rect = new Rect();

    activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);

    int screenHeight = activity.getWindow().getDecorView().getRootView().getHeight();

    int softInputHeight = screenHeight - rect.bottom;

    // Android LOLLIPOP 以上的版本才有虛擬按鍵
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      softInputHeight -= getSupportNavigationBarHeight(activity);
    }

    return softInputHeight;
  }

參考鏈接

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末健田,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子佛纫,更是在濱河造成了極大的恐慌妓局,老刑警劉巖腾窝,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赁炎,死亡現場離奇詭異迅诬,居然都是意外死亡逞怨,警方通過查閱死者的電腦和手機疆柔,發(fā)現死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門刑顺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來隶校,“玉大人夺姑,你說我怎么就攤上這事蜈漓∧鹿穑” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵融虽,是天一觀的道長享完。 經常有香客問我,道長有额,這世上最難降的妖魔是什么般又? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮谆吴,結果婚禮上倒源,老公的妹妹穿的比我還像新娘。我一直安慰自己句狼,他們只是感情好笋熬,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著腻菇,像睡著了一般胳螟。 火紅的嫁衣襯著肌膚如雪昔馋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天糖耸,我揣著相機與錄音秘遏,去河邊找鬼。 笑死嘉竟,一個胖子當著我的面吹牛邦危,可吹牛的內容都是我干的。 我是一名探鬼主播舍扰,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼倦蚪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了边苹?” 一聲冷哼從身側響起陵且,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎个束,沒想到半個月后慕购,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡茬底,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年沪悲,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桩警。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡可训,死狀恐怖,靈堂內的尸體忽然破棺而出捶枢,到底是詐尸還是另有隱情握截,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布烂叔,位于F島的核電站谨胞,受9級特大地震影響,放射性物質發(fā)生泄漏蒜鸡。R本人自食惡果不足惜胯努,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望逢防。 院中可真熱鬧叶沛,春花似錦、人聲如沸忘朝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至溉箕,卻和暖如春晦墙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肴茄。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工晌畅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人寡痰。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓抗楔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親氓癌。 傳聞我的和親對象是個殘疾皇子谓谦,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內容