Check visibility of android keyboard

Asked

Viewed 775 times

2

How do I check whether the android keyboard is visible or not? Some people say to calculate the difference between the size of the Rootview and its general layout of the activity, but for me, it doesn’t work.

Here is an example

final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
    @Override 
    public void onGlobalLayout() { 
        int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
        if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
            ... do something here
        } 
     } 
}); 

Source: https://stackoverflow.com/a/4737265/3046141

Does anyone have any idea how to solve this problem?

Problem solved. Follows the solution.

Softkeyboard.java

/*


* Author: Felipe Herranz ([email protected])
 * Contributors:Francesco Verheye ([email protected])
 *      Israel Dominguez ([email protected])
 */ 
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;


import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

public class SoftKeyboard implements View.OnFocusChangeListener
{
    private static final int CLEAR_FOCUS = 0;

    private ViewGroup layout;
    private int layoutBottom;
    private InputMethodManager im;
    private int[] coords;
    private boolean isKeyboardShow;
    private SoftKeyboardChangesThread softKeyboardThread;
    private List<EditText> editTextList;


    private View tempView; // reference to a focused EditText

    public SoftKeyboard(ViewGroup layout, InputMethodManager im)
    {
        this.layout = layout;
        keyboardHideByDefault();
        initEditTexts(layout);
        this.im = im;
        this.coords = new int[2];
        this.isKeyboardShow = false;
        this.softKeyboardThread = new SoftKeyboardChangesThread();
        this.softKeyboardThread.start();
    }


    public void openSoftKeyboard()
    {
        if(!isKeyboardShow)
        {
            layoutBottom = getLayoutCoordinates();
            im.toggleSoftInput(0, InputMethodManager.SHOW_IMPLICIT);
            softKeyboardThread.keyboardOpened();
            isKeyboardShow = true;
        }
    }

    public void closeSoftKeyboard()
    {
        if(isKeyboardShow)
        {
            im.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
            isKeyboardShow = false;
        }
    }

    public void setSoftKeyboardCallback(SoftKeyboardChanged mCallback)
    {
        softKeyboardThread.setCallback(mCallback);
    }

    public void unRegisterSoftKeyboardCallback()
    {
        softKeyboardThread.stopThread();
    }

    public interface SoftKeyboardChanged 
    {
        public void onSoftKeyboardHide();
        public void onSoftKeyboardShow();   
    }

    private int getLayoutCoordinates()
    {
        layout.getLocationOnScreen(coords);
        return coords[1] + layout.getHeight();
    }

    private void keyboardHideByDefault()
    {
        layout.setFocusable(true);
        layout.setFocusableInTouchMode(true);
    }

    /*
     * InitEditTexts now handles EditTexts in nested views
     * Thanks to Francesco Verheye ([email protected])
     */
    private void initEditTexts(ViewGroup viewgroup) 
    {
        if(editTextList == null)
            editTextList = new ArrayList<EditText>();

        int childCount = viewgroup.getChildCount();
        for(int i=0; i<= childCount-1;i++) 
        {
            View v = viewgroup.getChildAt(i);


            if(v instanceof ViewGroup) 
            {
                initEditTexts((ViewGroup) v);
            }


            if(v instanceof EditText) 
            {
                EditText editText = (EditText) v;
                editText.setOnFocusChangeListener(this);
                editText.setCursorVisible(true);
                editTextList.add(editText);
            }
        }
    }


    /*
     * OnFocusChange does update tempView correctly now when keyboard is still shown
     * Thanks to Israel Dominguez ([email protected])
     */
    @Override
    public void onFocusChange(View v, boolean hasFocus) 
    {
        if(hasFocus) 
        {
            tempView = v;
            if(!isKeyboardShow) 
            {
                layoutBottom = getLayoutCoordinates();
                softKeyboardThread.keyboardOpened();
                isKeyboardShow = true;
            }
        }
    }

    // This handler will clear focus of selected EditText
    private final Handler mHandler = new Handler()
    {
        @Override
        public void handleMessage(Message m)
        {
            switch(m.what)
            {
            case CLEAR_FOCUS:
                if(tempView != null)
                {
                    tempView.clearFocus();
                    tempView = null;
                }
                break;
            }
        }
    };

    private class SoftKeyboardChangesThread extends Thread
    {
        private AtomicBoolean started;
        private SoftKeyboardChanged mCallback;

        public SoftKeyboardChangesThread()
        {
            started = new AtomicBoolean(true);
        }

        public void setCallback(SoftKeyboardChanged mCallback)
        {
            this.mCallback = mCallback;
        }

        @Override
        public void run()
        {
            while(started.get())
            {
                // Wait until keyboard is requested to open
                synchronized(this)
                {
                    try 
                    {
                        wait();
                    } catch (InterruptedException e) 
                    {
                        e.printStackTrace();
                    }
                }

                int currentBottomLocation = getLayoutCoordinates();

                // There is some lag between open soft-keyboard function and when it really appears.
                while(currentBottomLocation == layoutBottom && started.get())
                {
                    currentBottomLocation = getLayoutCoordinates();
                }

                if(started.get())
                    mCallback.onSoftKeyboardShow();

                // When keyboard is opened from EditText, initial bottom location is greater than layoutBottom
                // and at some moment equals layoutBottom.
                // That broke the previous logic, so I added this new loop to handle this.
                while(currentBottomLocation >= layoutBottom && started.get())
                {
                    currentBottomLocation = getLayoutCoordinates();
                }

                // Now Keyboard is shown, keep checking layout dimensions until keyboard is gone
                while(currentBottomLocation != layoutBottom && started.get())
                {
                                        synchronized(this)
                    {
                        try 
                        {
                            wait(500);
                        } catch (InterruptedException e) 
                        {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                    currentBottomLocation = getLayoutCoordinates();
                }

                if(started.get())
                    mCallback.onSoftKeyboardHide();

                // if keyboard has been opened clicking and EditText.
                if(isKeyboardShow && started.get())
                    isKeyboardShow = false;

                // if an EditText is focused, remove its focus (on UI thread)
                if(started.get())
                    mHandler.obtainMessage(CLEAR_FOCUS).sendToTarget();
            }   
        }

        public void keyboardOpened()
        {
            synchronized(this)
            {
                notify();
            }
        }

        public void stopThread()
        {
            synchronized(this)
            {
                started.set(false);
                notify();
            }
        }

    }
}

Softkeyboardhideshow.java

/*
* Android Manifest: android:windowSoftInputMode="adjustResize"
*/


/*
Somewhere else in your code
*/
RelativeLayout mainLayout = findViewById(R.layout.main_layout); // You must use the layout root
InputMethodManager im = (InputMethodManager) getSystemService(Service.INPUT_METHOD_SERVICE);

/*
Instantiate and pass a callback
*/
SoftKeyboard softKeyboard;
softKeyboard = new SoftKeyboard(mainLayout, im);
softKeyboard.setSoftKeyboardCallback(new SoftKeyboard.SoftKeyboardChanged()
{

    @Override
    public void onSoftKeyboardHide() 
    {
        // Code here
    }

    @Override
    public void onSoftKeyboardShow() 
    {
        // Code here
    }   
});

/*
Open or close the soft keyboard easily
*/
softKeyboard.openSoftKeyboard();
softKeyboard.closeSoftKeyboard();


/* Prevent memory leaks:
*/
@Override
public void onDestroy()
{
    super.onDestroy();
    softKeyboard.unRegisterSoftKeyboardCallback();
}

Source: https://gist.github.com/felHR85/6070f643d25f5a0b3674

It worked for me.

  • Thalisson I suggest to put the code of this link as answer, it is clearer to those who have the same problem that this is the solution.

  • I’ll do it now.

  • Thalisson, creates an answer :P It is not clear, looking fast, that the problem is already solved.

1 answer

1

You can check if the Inputmethod is active:

InputMethodManager imm  = (InputMethodManager)getActivity().getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.isActive();

Browser other questions tagged

You are not signed in. Login or sign up in order to post.