安卓软键盘监听

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

SoftKeyboard.java

/*
 * Author: Felipe Herranz (felhr85@gmail.com)
 * Contributors:Francesco Verheye (verheye.francesco@gmail.com)
 *         Israel Dominguez (dominguez.israel@gmail.com)
 */    
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 (verheye.francesco@gmail.com)
     */
    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 (dominguez.israel@gmail.com)
     */
    @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();
            }
        }
            
    }
}
View Code

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();
}
View Code
原文地址:https://www.cnblogs.com/shixm/p/5728448.html