Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android detect soft keyboard closing

I am struggling with this matter for a couple of hours and I cannot find a way to determine if the keyboard is shown or not.

I have seen multiple questions and answer about this matter which was depended on changing in height of container layout. so it cannot be possible to detect the opening of keyboard exactly when (for example) an Edittext get the focused and as a result, change in full height layout and its views is inevitable.

Solution 1 : I solved this problem by removing focus from all of EditText s and change the visibility of the views which I don't need them to be shown when Edittext get focused (make available space to prevent disorder of views) so I have enough time to remove redundant views.

but it is not possible to detect when the keyboard is asked to be closed to make views visible.

if I use the common method which I mentioned in 2nd paragraph to detect closing of the keyboard it will fail my "solution 1".

the only idea I have now is to detect keyboard closing by monitoring the key which is responsible for keyboard closure. bot i cannot detect it in onKeyDown method.

enter image description here

so how can I monitor this key?

any guide and idea will be appreciated. Thanks in advance.

Final Solution :
thanks to @Nick Cardoso , my final solution is a combination of using onTouchListener to detect the keyboard openness and Nick's solution of closing.

this is onTouchListener for Edittexts :

    View.OnTouchListener TouchListener = new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN)
        {
            Container.getViewTreeObserver().removeOnGlobalLayoutListener(gll);
            recyclerView.setVisibility(View.GONE);
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Container.getViewTreeObserver().addOnGlobalLayoutListener(gll);
                }
            }, 100);
        }
        return false;
    }
};


ViewTreeObserver.OnGlobalLayoutListener gll = new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        Rect measureRect = new Rect();
        Container.getWindowVisibleDisplayFrame(measureRect);
        int keypadHeight = Container.getRootView().getHeight() - measureRect.bottom;

        if (keypadHeight > 0) {
            // keyboard is opened
        } else {
            recyclerView.setVisibility(View.VISIBLE);
        }
    }
};

here Container is the root view of the layout.

like image 399
M.Armoun Avatar asked Mar 19 '17 21:03

M.Armoun


Video Answer


1 Answers

There is (ridiculously) no simple, reliable way to do this. It can however be achieved in two parts, with a layout listener as suggested here. It's a little bit of a hack but it works:

mRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        Rect measureRect = new Rect(); //you should cache this, onGlobalLayout can get called often
        mRootView.getWindowVisibleDisplayFrame(measureRect);
        // measureRect.bottom is the position above soft keypad
        int keypadHeight = mRootView.getRootView().getHeight() - measureRect.bottom;

        if (keypadHeight > 0) {
            // keyboard is opened 
            mIsKeyboardVisible = true;
            mMyDependentView.setVisibility(View.GONE);
        } else {
            //store keyboard state to use in onBackPress if you need to
            mIsKeyboardVisible = false;
            mMyDependentView.setVisibility(View.VISIBLE);
        }
    }
});
like image 191
Nick Cardoso Avatar answered Oct 21 '22 20:10

Nick Cardoso