Android鍵盤(pán)處理-監(jiān)聽(tīng)鍵盤(pán)狀態(tài)并實(shí)現(xiàn)QQ拉出式彈出回復(fù)框。

在做一些人性化的交互設(shè)計(jì)的時(shí)候,能夠獲取Android 鍵盤(pán)的顯示與隱藏狀態(tài)對(duì)我們有很大的幫助,但是Android 官方文檔中并沒(méi)有明確的給出 ,鍵盤(pán)顯示與隱藏的監(jiān)聽(tīng),但是我們還是可以通過(guò)計(jì)算當(dāng)前應(yīng)用的高度變化來(lái)獲取鍵盤(pán)的狀態(tài)。手機(jī)QQ對(duì)于鍵盤(pán)的處理就非常好,有著以下的幾點(diǎn)人性化設(shè)計(jì):

QQ效果圖
  • 滑動(dòng)時(shí)隱藏鍵盤(pán)
  • 點(diǎn)擊除鍵盤(pán)區(qū)域隱藏鍵盤(pán)
  • 當(dāng)滾動(dòng)到底部時(shí)繼續(xù)拉動(dòng)彈出鍵盤(pán)

** 本文將一步一步講解實(shí)現(xiàn)上述三種設(shè)計(jì) **

1.首先獲取鍵盤(pán)顯示隱藏狀態(tài)

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

 // 軟鍵盤(pán)的顯示狀態(tài)
private boolean ShowKeyboard;
private ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {

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


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

** 需要特別指出的是,在某些手機(jī)上,比如華為mate8,底部會(huì)出現(xiàn)一個(gè)可以隨時(shí)隱藏與顯示的一行虛擬按鍵(Android雜亂生態(tài)的無(wú)奈??),所以我們要定義一個(gè)最小鍵盤(pán)高度。 **

//給最外層布局添加布局變化監(jiān)聽(tīng)
layoutMain.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);

這樣根據(jù)ShowKeyboard值的變化 就能判斷鍵盤(pán)的顯示與隱藏了。

2.實(shí)現(xiàn)點(diǎn)擊其他區(qū)域隱藏鍵盤(pán)

這里利用的就是焦點(diǎn),點(diǎn)擊其他區(qū)域,鍵盤(pán)會(huì)失去焦點(diǎn),這個(gè)時(shí)候我們可以強(qiáng)制隱藏鍵盤(pán),因?yàn)镋ditText 焦點(diǎn)已經(jīng)缺失,某些隱藏鍵盤(pán)的方法可能失效。

        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.實(shí)現(xiàn)滑動(dòng)隱藏鍵盤(pán),以及滑動(dòng)到底部拉出鍵盤(pán)

這里主要實(shí)現(xiàn)方法是監(jiān)聽(tīng)用戶手勢(shì),同時(shí)判斷鍵盤(pán)狀態(tài),判斷webView是否滑動(dòng)到底部了。

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    if (e1 == null || e2 == null) {
        return false;
    }
    //判斷滑動(dòng)距離,以及速度,如果鍵盤(pán)顯示中,隱藏鍵盤(pán)。
    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的現(xiàn)高度
    float webViewCurrentHeight = (mWebView.getHeight() + mWebView.getScrollY());
    // 這里是判斷 鍵盤(pán)是否顯示 滑動(dòng)距離,以及是否滑動(dòng)到底部。
    if (!ShowKeyboard && e1.getY() - e2.getY() > getScreenHeight(mContext)  / 10 && webViewContentHeight - webViewCurrentHeight <= 10) {

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

注意手勢(shì)監(jiān)聽(tīng),不要遺忘以下操作:

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);
}

最后看一下實(shí)現(xiàn)的效果圖:


實(shí)現(xiàn)效果圖

源碼地址:AndroidKeyboard

技術(shù)博客:Wells'Note

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,901評(píng)論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,164評(píng)論 4 61
  • 這里說(shuō)的筆記本,不是筆記本電腦,而是傳統(tǒng)的紙質(zhì)筆記本。職場(chǎng)中很多人已經(jīng)不用紙質(zhì)筆記本了,他們說(shuō),「現(xiàn)在都什么時(shí)代了...
    AaronWu閱讀 5,533評(píng)論 17 98
  • 【龜茲:漢語(yǔ)拼音:qiūcí,龜茲語(yǔ):Kutsi,維語(yǔ):Küsen】 前秦建元十八年(382年)苻堅(jiān)之大將呂光滅龜...
    鄧文偉閱讀 1,190評(píng)論 0 4
  • 醒來(lái)查初試成績(jī)。分不高,排名還可以。 所以,又該回學(xué)校繼續(xù)與學(xué)術(shù)死磕了。 其實(shí)還是挺想直接步入江湖的。 總覺(jué)得人生...
    汪規(guī)矩閱讀 256評(píng)論 0 0

友情鏈接更多精彩內(nèi)容