安卓软键盘监听

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

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

时间: 2024-10-21 20:36:32

安卓软键盘监听的相关文章

完美解决android软键盘监听

最近在做应用性能调优,发现在一个包含有输入框的Activity中,当软键盘弹出的时候,如果直接finish掉此Activity,那么在返回到上一个Activity时,界面的渲染会由于软键盘没有及时的收起而出现卡顿的情况. 很不友好. 于是,本着geek的精神,做就做到极致,就尝试着对这一块做优化. 借助网上一些知识的分享,同时结合自己的理解,最终应用到项目中. 直接上代码.. 首先,在manifest文件中声明此Activity的windowSoftInputMode属性, 1 android:

完美解决android软键盘监听1

最近在做应用性能调优,发现在一个包含有输入框的Activity中,当软键盘弹出的时候,如果直接finish掉此Activity,那么在返回到上一个Activity时,界面的渲染会由于软键盘没有及时的收起而出现卡顿的情况. 很不友好. 于是,本着geek的精神,做就做到极致,就尝试着对这一块做优化. 借助网上一些知识的分享,同时结合自己的理解,最终应用到项目中. 直接上代码.. 首先,在manifest文件中声明此Activity的windowSoftInputMode属性,      andro

Android之键盘监听的运行机理【看清键盘监听的本质】【入门版】

以EditText为例: 1.Activity本身也有按键监听 editText按键监听与Activity按键监听关系: Activity本身也有按键监听 而且分按下和松开两个事件监听 editText按键监听不分按下,和松开,准确的说:它把这两个事件放在了一个监听事件里了 return false ,editText按键监听事件执行完之后,会向下传第,即接着执行Activity的按键监听 return true :终止向下传递,不会执行Activity的按键监听 2.软键盘不能响应按键监听(只

Android之如何设置键盘监听

5.设置键盘监听[以EditText为例] username.setOnKeyListener(new OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { // TODO Auto-generated method stub switch (keyCode) { case KeyEvent.KEYCODE_1: Toast.makeText(MainActivity.thi

C#全局键盘监听(Hook)的使用

一.为什么需要全局键盘监听? 在某些情况下应用程序需要实现快捷键执行特定功能,例如大家熟知的QQ截图功能Ctrl+Alt+A快捷键,只要QQ程序在运行(无论是拥有焦点还是处于后台运行状态),都可以按下快捷键使用此功能... 这个时候在程序中添加键盘监听肯定不能满足需求了,当用户焦点不在App上时(如最小化,或者用户在处理其它事物等等)键盘监听就失效了 二.怎样才能实现全局键盘监听? 这里需要用到Windows API,源码如下:(可以作为一个工具类[KeyboardHook.cs]收藏起来) u

使用HTML+CSS,jQuery编写的简易计算器后续(添加了键盘监听)

之前发布了一款简易的计算器,今天做了一下修改,添加了键盘监听事件,不用再用鼠标点点点啦 JS代码: var yunSuan = 0;// 运算符号,0-无运算;1-加法;2-减法;3-乘法;4-除法 var change = 0;// 属于运算符后需要清空上一数值 var num1 = 0;// 运算第一个数据 var num2 = 0;// 运算第二个数据 var cunChuValue = 0;// 存储的数值 $(function() { $(".number").click(f

JPanel添加键盘监听事件

因为在自己的游戏需求中谢了要用键盘控制飞机的移动,所以用到键盘监听事件,但是使用了JPanel之后添加了键盘监听事件,按相应的方向键飞机并没有反应.但是如果是为JFrame的内容面板加则会有反应. 为了使得能在JPanel里头使用键盘事件解决方法如下: 1.在JPanel里头添加键盘监听 this.addKeyListener(new KeyAdapter(){ public void keyPressed(KeyEvent e) { switch(e.getKeyCode()){ case K

【转】【C#】全局键盘监听

using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Reflection; namespace 梦琪动漫屋 { /// <summary> /// 键盘钩子/// </summary> class KeyboardHook { public ev

iOS键盘监听以及获取键盘高度

在文本输入时,界面会弹出键盘.有时,当文本输入框过低,被键盘遮挡,使用户无法看见输入框文本内容,这就使得用户体验过低. 所以需要我们对键盘进行监控并获取键盘高度,调节界面或文本框高度进行处理.如下图,文本输入框过低的情况: 像这样的情况,如若未作处理,输入框就会被键盘遮挡.这时,我们需要监听键盘事件,获取键盘高度,对文本框视图进行高度调整: 1 #import "ViewController.h" 2 3 @interface ViewController ()<UITextFi