Android鍵盤處理-監聽鍵盤狀態并實現QQ拉出式彈出回復框。

在做一些人性化的交互設計的時候,能夠獲取Android 鍵盤的顯示與隱藏狀態對我們有很大的幫助,但是Android 官方文檔中并沒有明確的給出 ,鍵盤顯示與隱藏的監聽,但是我們還是可以通過計算當前應用的高度變化來獲取鍵盤的狀態。手機QQ對于鍵盤的處理就非常好,有著以下的幾點人性化設計:

QQ效果圖
  • 滑動時隱藏鍵盤
  • 點擊除鍵盤區域隱藏鍵盤
  • 當滾動到底部時繼續拉動彈出鍵盤

** 本文將一步一步講解實現上述三種設計 **

1.首先獲取鍵盤顯示隱藏狀態

獲取鍵盤顯示狀態的原理是:首先利用getRootView().getHeight() 獲取屏幕高度,在利用getWindowVisibleDisplayFrame 獲取應用顯示區域,但是這個區域不包含虛擬按鍵的區域(虛擬鍵盤、手機底部虛擬按鍵),我們根據前者與后者之差與狀態欄高度的比較來判斷鍵盤的顯示與隱藏狀態。

 // 軟鍵盤的顯示狀態
private boolean ShowKeyboard;
private ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
        // 應用可以顯示的區域。此處包括應用占用的區域,包括標題欄不包括狀態欄
        Rect r = new Rect();
        layoutMain.getWindowVisibleDisplayFrame(r);
        // 鍵盤最小高度
        int minKeyboardHeight = 150;
        // 獲取狀態欄高度
        int statusBarHeight = getStatusBarHeight(mContext);
        // 屏幕高度,不含虛擬按鍵的高度
        int screenHeight = layoutMain.getRootView().getHeight();
        // 在不顯示軟鍵盤時,height等于狀態欄的高度
        int height = screenHeight - (r.bottom - r.top);


        if (ShowKeyboard) {
            // 如果軟鍵盤是彈出的狀態,并且height小于等于狀態欄高度,
            // 說明這時軟鍵盤已經收起
            if (height - statusBarHeight < minKeyboardHeight) {
                ShowKeyboard = false;
                Toast.makeText(mContext,"鍵盤隱藏了",Toast.LENGTH_SHORT).show();
            }
        } else {
            // 如果軟鍵盤是收起的狀態,并且height大于狀態欄高度,
            // 說明這時軟鍵盤已經彈出
            if (height - statusBarHeight > minKeyboardHeight) {
                ShowKeyboard = true;
                Toast.makeText(mContext,"鍵盤顯示了",Toast.LENGTH_SHORT).show();
            }
        }
    }
};

** 需要特別指出的是,在某些手機上,比如華為mate8,底部會出現一個可以隨時隱藏與顯示的一行虛擬按鍵(Android雜亂生態的無奈??),所以我們要定義一個最小鍵盤高度。 **

//給最外層布局添加布局變化監聽
layoutMain.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);

這樣根據ShowKeyboard值的變化 就能判斷鍵盤的顯示與隱藏了。

2.實現點擊其他區域隱藏鍵盤

這里利用的就是焦點,點擊其他區域,鍵盤會失去焦點,這個時候我們可以強制隱藏鍵盤,因為EditText 焦點已經缺失,某些隱藏鍵盤的方法可能失效。

        inputText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View v, boolean hasFocus) {
            if (!hasFocus) {
                InputMethodManager imm = (InputMethodManager) mContext
                        .getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.hideSoftInputFromWindow(layoutMain.getWindowToken(), 0);
            }
        }
    });

3.實現滑動隱藏鍵盤,以及滑動到底部拉出鍵盤

這里主要實現方法是監聽用戶手勢,同時判斷鍵盤狀態,判斷webView是否滑動到底部了。

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    if (e1 == null || e2 == null) {
        return false;
    }
    //判斷滑動距離,以及速度,如果鍵盤顯示中,隱藏鍵盤。
    if (Math.abs(e2.getY() - e1.getY()) > flingHeight && Math.abs(velocityY) > flingspeed) {
        if (ShowKeyboard) {
            closeInputMethod(mContext);
        }
    }
    float r= mWebView.getHeight();
    // WebView總高度
    float webViewContentHeight = mWebView.getContentHeight()*mWebView.getScale();
    // WebView的現高度
    float webViewCurrentHeight = (mWebView.getHeight() + mWebView.getScrollY());
    // 這里是判斷 鍵盤是否顯示 滑動距離,以及是否滑動到底部。
    if (!ShowKeyboard && e1.getY() - e2.getY() > getScreenHeight(mContext)  / 10 && webViewContentHeight - webViewCurrentHeight <= 10) {

        popInputMethod(inputText, mContext);
    }
    return false;
}

注意手勢監聽,不要遺忘以下操作:

public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener 

mGestureDetector = new GestureDetector(mContext, this);

 @Override
public boolean dispatchTouchEvent(MotionEvent event) {
    mGestureDetector.onTouchEvent(event);
    return super.dispatchTouchEvent(event);
}

最后看一下實現的效果圖:


實現效果圖

源碼地址:AndroidKeyboard

技術博客:Wells'Note

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,627評論 2 380

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,764評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,179評論 4 61
  • 這里說的筆記本,不是筆記本電腦,而是傳統的紙質筆記本。職場中很多人已經不用紙質筆記本了,他們說,「現在都什么時代了...
    AaronWu閱讀 5,108評論 17 98
  • 【龜茲:漢語拼音:qiūcí,龜茲語:Kutsi,維語:Küsen】 前秦建元十八年(382年)苻堅之大將呂光滅龜...
    鄧文偉閱讀 1,100評論 0 4
  • 醒來查初試成績。分不高,排名還可以。 所以,又該回學校繼續與學術死磕了。 其實還是挺想直接步入江湖的。 總覺得人生...
    汪規矩閱讀 232評論 0 0