1. 程式人生 > >仿微信朋友圈回覆資訊-點選空白處軟鍵盤以及回覆佈局消失

仿微信朋友圈回覆資訊-點選空白處軟鍵盤以及回覆佈局消失

開啟微信朋友圈,點選回覆按鈕,會立馬跳出一個回覆欄和一個軟鍵盤,點選其他空白處這2個又消失了。這種功能我們怎麼實現呢?

類似下面這種功能,由於用的是夜神模擬器,沒有軟鍵盤,大家可以自行腦補,或者去自己的朋友圈看看效果。


思路是這樣的:點選這個回覆狀態列以外的其他區域,讓這個回覆欄目GONE掉,軟鍵盤沒關閉的話,把它關了。

這就涉及到了2個知識點:1、觸屏事件分發機制;

                                       2、得到某個View在螢幕上的位置。

Activity中有2個觸屏事件分發的相關方法:dispatchTouchEvent()和onTouchEven()。

dispatchTouchEvent()是用來分發事件的,onTouchEven()是用來消費事件的。

一般的事件生命週期是這樣的:

1、Activity的dispatchTouchEvent()傳遞給ViewGrouop的dispatchTouchEvent()

2、ViewGrouop的dispatchTouchEvent()傳遞給ViewGrouop的onInterceptTouchEven();

3、ViewGrouop的onInterceptTouchEven()判斷是否攔截事件,不攔截事件的話分發給ChildView(子View);

4、View的dispatchTouchEvent()判斷

View有沒有消費掉這個事件,然後把結果往上傳遞。

我們這是在Activity中點選,所以考慮是用Activity的dispatchTouchEvent()還是onTouchEven()。

onTouchEven()是子View以及ViewGroup都不消費事件的時候,傳遞迴Activity才會觸發的。若是使用者點到了有點選事件的東西(比如上個動圖的搜尋按鈕、回覆按鈕、返回按鈕),那麼這個事件就被消費了。Activity就沒辦法得到這個觸控事件了。所以我們要在Activity的dispatchTouchEvent()方法中做這些邏輯。

然後下面程式碼說的是如何判斷點選的是回覆欄之外的區域。用到的是getLocationInWindow這個方法。

可能有人會問為什麼不用getLoacationOnScreen(),對於這個專案而言,這個回覆欄的父佈局就是最外層的Layout,所以用哪個都是一樣的。

這裡普及下知識:

int[] location = new  int[2] ; view.getLocationInWindow(location); //獲取在當前視窗內的絕對座標 view.getLocationOnScreen(location); //獲取在整個螢幕內的絕對座標 location [0]--->x座標 location [1]--->y座標
  public boolean isShouldHideInput(View v, MotionEvent event)
    {
        if (v != null && (v instanceof RelativeLayout))//這個view就是我們回覆欄的佈局
        {
            int[] leftTop = new int[2];
            v.getLocationInWindow(leftTop);
            int left = leftTop[0];//回覆欄左上角x軸座標
            int top = leftTop[1];//回覆欄左上角y軸座標
            int bottom = top + v.getHeight();//回覆欄右下角x軸座標
            int right = left + v.getWidth();//回覆欄右下角y軸座標
            if (event.getX() > left && event.getX() < right
                    && event.getY() > top && event.getY() < bottom) return false;
            else return true;
        }
        return false;
    }

最後我們就重寫dispatchTouchEvent(),然後當這個回覆欄可見,觸控事件是按下,且當前觸控點在這個回覆欄之外的時候,執行下面的程式碼,回覆欄GONE掉,軟鍵盤關閉。
 @Override
    public boolean dispatchTouchEvent(MotionEvent ev)
    {
        if (rl_bottom.getVisibility() == View.VISIBLE && ev.getAction() == MotionEvent.ACTION_DOWN && isShouldHideInput(rl_bottom, ev))
            {
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm != null)
                {
                    rl_bottom.setVisibility(View.GONE);
                    imm.hideSoftInputFromWindow(rl_bottom.getWindowToken(), 0);
                }
        }
    return super.dispatchTouchEvent(ev);
    }

然後到這裡大家已經懂了吧