Android 软键盘汇总

来源:互联网 发布:销售订单软件 编辑:程序博客网 时间:2024/06/05 17:35

首先扯点别的:我想问一下,如果一个你喜欢的女生如果把你当弟兄们对待,是什么意思?意思是只能做朋友?
今天记录一下如何监听软键盘的弹出和退出。

监听软键盘的弹起

直接上代码

public class MainActivity extends AppCompatActivity implements ViewTreeObserver.OnGlobalLayoutListener {    private static final String TAG = "MainActivity";    private View activityRootView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        activityRootView =         getWindow().getDecorView().findViewById(android.R.id.content);        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);    }     @Override    public void onGlobalLayout() {        if (isKeyboardShown(activityRootView)) {            Log.e(TAG, "软键盘弹起");        } else {            Log.e(TAG, "软键盘关闭");        }    }  private boolean isKeyboardShown(View rootView) {  DisplayMetrics dm = rootView.getResources().getDisplayMetrics();        //设定一个认为是软键盘弹起的阈值        final int softKeyboardHeight = 100*dm.density;         //得到屏幕可见区域的大小        Rect r = new Rect();        rootView.getWindowVisibleDisplayFrame(r);        //rootView 的bottom和当前屏幕可见区域(包括状态栏)bottom的差值        int heightDiff = rootView.getBottom() - r.bottom;        return heightDiff > softKeyboardHeight;    }    @Override    protected void onDestroy() {        super.onDestroy();    activityRootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);    }}

首先实现ViewTreeObserver.OnGlobalLayoutListener接口,重写onGlobalLayout方法,然后给activityRootView 注册监听addOnGlobalLayoutListener监听

 activityRootView =  getWindow().getDecorView().findViewById(android.R.id.content); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(this);

然后在 isKeyboardShown方法中进行判断,我们设置软件盘弹起的阈值是100乘以当前设备的密度独立像素单位,比如我的手机,1dp=3px;

  private boolean isKeyboardShown(View rootView) {  DisplayMetrics dm = rootView.getResources().getDisplayMetrics();        //设定一个认为是软键盘弹起的阈值        final int softKeyboardHeight = 100*dm.density;         //得到屏幕可见区域的大小        Rect r = new Rect();        rootView.getWindowVisibleDisplayFrame(r);        //rootView 的bottom和当前屏幕可见区域bottom的差值        int heightDiff = rootView.getBottom() - r.bottom;        return heightDiff > softKeyboardHeight;    }

要记得在Activity的onDestroy取消注册OnGlobalLayoutListener

 @Override    protected void onDestroy() {        super.onDestroy();    activityRootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);    }

注意:上面这个方法有个问题。就是当我们在AndroidManifest.xml文件中给Activity指定软键盘的输入模式为adjustResize的时候,无法判断监听键盘弹起。

  <activity            android:name=".activity.TestActivity"            android:windowSoftInputMode="adjustResize">            <intent-filter>                <action android:name="android.intent.action.MAIN"/>                <category android:name="android.intent.category.LAUNCHER"/>            </intent-filter>        </activity>

修改isKeyboardShown方法如下

private boolean isKeyboardShown(View rootView) {        DisplayMetrics dm = rootView.getResources().getDisplayMetrics();        //设定一个认为是软键盘弹起的阈值        final int softKeyboardHeight = (int) (100 * dm.density);        //得到屏幕可见区域的大小        Rect r = new Rect();        rootView.getWindowVisibleDisplayFrame(r);        int heightDiff = dm.heightPixels - r.bottom;        return heightDiff > softKeyboardHeight;    }

注意现在高度差的计算方式,是使用手机屏幕的高度,减去当前可见区域的高度。

int heightDiff = dm.heightPixels - r.bottom;

我的手机屏幕高度是1920px,键盘弹起的时候可见区域高度是1118px,键盘关闭的时候可见区域的高度恢复到1920px。

监听软键盘的退出。

假设场景:我们屏幕中有一个EditText,用来输入价格,我们要根据输入的价格进行计算。实现方式可以这样。

 editPrice.addTextChangedListener(new TextWatcher() {            @Override            public void beforeTextChanged(CharSequence s, int start, int count, int after) {            }            @Override            public void onTextChanged(CharSequence s, int start, int before, int count) {            }            @Override            public void afterTextChanged(Editable s) {                //在这里进行计算            }        });

但是这种方式有一个缺点,就是每当输入的价格变化的时候就会进行一次价格计算。但是如果能够在软键盘关闭以后再进行价格计算会更好。这样就只会进行一次计算。实现如下。

首先自定义MyEditText

public class MyEditText extends EditText {    private OnFinishComposingListener finishComposingListener;    public void setFinishComposingListener(OnFinishComposingListener finishComposingListener) {        this.finishComposingListener = finishComposingListener;    }    public MyEditText(Context context) {        super(context);    }    public MyEditText(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {        return new MyInputConnection(super.onCreateInputConnection(outAttrs),false);    }    /**        自定义一个输入法连接器    */    class MyInputConnection extends InputConnectionWrapper {        public MyInputConnection(InputConnection target, boolean mutable) {            super(target, mutable);        }        @Override        public boolean finishComposingText() {        //在这个方法里可以监听输入完成动作。            if (finishComposingListener != null) {                finishComposingListener.finishComposing();            }            return super.finishComposingText();        }    }    //定义一个接口,用来回调进行输入完成时的操作,比如计算价格。     interface OnFinishComposingListener {        void finishComposing();    }}

使用,和普通的EditText一样在xml布局文件中使用就可以了。

public class MainActivity extends AppCompatActivity {    private MyEditText editPrice;    private static final String TAG = "MainActivity";    private TextView textResult;    private boolean touchEditPrice;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        editPrice = (MyEditText) findViewById(R.id.eidt_price);        textResult = (TextView) findViewById(R.id.text_result);        editPrice.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                touchEditPrice = true;                return false;            }        });        editPrice.setFinishComposingListener(new MyEditText.OnFinishComposingListener() {            @Override            public void finishComposing() {                if (touchEditPrice) {                    Log.e(TAG, "editPrice finishComposing: ");                    textResult.setText(editPrice.getText().toString());                    touchEditPrice = false;                }            }        });    }}

需要注意:因为在某些情况下,比如EditText失去焦点,Activity结束等finishComposingText()方法也会调用。所以我们加了一个boolean值touchEditPrice ,我们给editPrice设置touch监听事件,当editPrice被touch的时候touchEditPrice 设为true。然后在输入动作完成的时候如果touchEditPrice为true,我们就进行相应的操作,然后把touchEditPrice设为false。这样就能保证finishComposingText()方法中我们的操作只执行一次。

手动显示软键盘,隐藏软件盘

这里写图片描述

1 手动显示软键盘

InputMethodManager imm = (InputMethodManager) TestActivity.this.getSystemService(INPUT_METHOD_SERVICE);} imm.showSoftInput(editText, 0);

首先获取 InputMethodManager ,然后调用InputMethodManager 的showSoftInput方法。

showSoftInput(View view, int flags)

方法第一个参数view必须是一个EditText或者EditText的子类。view 必须可见,可以获得焦点并且当前焦点在view上。第二个参数flag随便不用纠结,直接传0就行。(如果想深入了解,可以参看文章结尾的链接3)。

2 手动隐藏软键盘。

InputMethodManager imm = (InputMethodManager) TestActivity.this.getSystemService(INPUT_METHOD_SERVICE);} imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);

首先获取 InputMethodManager,然后调用InputMethodManager的hideSoftInputFromWindow方法。

hideSoftInputFromWindow(IBinder windowToken, int flags)

方法的第一个参数是一个view的windowToken,这个可以通过view的getWindowToken()方法获得。这个view可以使当前布局中任意一个控件,即使不可见都行。第二个参数不纠结,直接传0。

参考链接:
【1】http://toughcoder.net/blog/2015/10/09/android-trick-detect-soft-keyboard-show-slash-hide/
【2】http://blog.csdn.net/hmyang314/article/details/43019101
【3】http://blog.csdn.net/ccpat/article/details/46717573

0 0
原创粉丝点击