android:windowSoftInputMode属性
1,stateVisible:软键盘通常是可见的,想让打开activity时开启软键盘
2,stateHidden:用户选择activity时,软键盘总是被隐藏
3,adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间 (ScrollView)
4,adjustPan:当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分
设置android:windowSoftInputMode="adjustResize|stateVisible" 打开activity键盘弹出,并且要是和输入框在同一RelativeLayout下的view会被顶起会让屏幕整体上移
键盘弹出监听
package com.xcm91.xiaocaimi.util;
import android.app.Activity;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import com.xcm91.xiaocaimi.others.utils.LogManager;
/**
* Created by lhy on 2018/11/8.
*/
public class SoftKeyBoardListener {
private View rootView;//activity的根视图
private int rootViewVisibleHeight;//纪录根视图的显示高度
private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener;
public SoftKeyBoardListener(Activity activity) {
//获取activity的根视图
rootView = activity.getWindow().getDecorView();
//监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//获取当前根视图在屏幕上显示的大小
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
int visibleHeight = r.height();
LogManager.i(""+visibleHeight);
if (rootViewVisibleHeight == 0) {
rootViewVisibleHeight = visibleHeight;
return;
}
//根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
if (rootViewVisibleHeight == visibleHeight) {
return;
}
//根视图显示高度变小超过200,可以看作软键盘显示了
if (rootViewVisibleHeight - visibleHeight > 200) {
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight);
}
rootViewVisibleHeight = visibleHeight;
return;
}
//根视图显示高度变大超过200,可以看作软键盘隐藏了
if (visibleHeight - rootViewVisibleHeight > 200) {
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight);
}
rootViewVisibleHeight = visibleHeight;
return;
}
}
});
}
private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener;
}
public interface OnSoftKeyBoardChangeListener {
void keyBoardShow(int height);
void keyBoardHide(int height);
}
public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity);
softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener);
}
}
ScrollView滑动到底部
SoftKeyBoardListener.setListener(this, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() {
@Override
public void keyBoardShow(int height) {
if (sv_main != null) {
sv_main.postDelayed(new Runnable() {
@Override
public void run() {
sv_main.smoothScrollTo(0, sv_main.getChildAt(0).getHeight());
}
}, 300);
}
}
@Override
public void keyBoardHide(int height) {
}
});
在开始进入页面时不弹出键盘
方法一:在包含EditText外层布局上添加
android:focusable="true"
android:focusableInTouchMode="true"
抢在EditText获取焦点,即可
原理 view touch source:
[java] view plain copy
- public boolean onTouchEvent(MotionEvent event) {
- ...
- if (((viewFlags & CLICKABLE) == CLICKABLE ||
- (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
- ...
- if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
- focusTaken = requestFocus();
- }
- ...
- }
- ...
- }
即一个子view想要获取焦点必须满足clickable, focusable, focusableInTouchMode 属性为true,缺一不可.
方法二:在onResume中加入这行代码
[java] view plain copy
- getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE |
- WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
软键盘出现把原来的布局底部拦布局给顶上去的方法解决办法:
Android:windowSoftInputMode="adjustPan|stateHidden"
1,绑定软键盘到EditText:
[java] view plain copy
- edit.setFocusable(true);
- edit.setFocusableInTouchMode(true);
- edit.requestFocus();
- InputMethodManager inputManager = (InputMethodManager)edit.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- inputManager.showSoftInput(edit, 0);
2,点击空白区域去除EditText软键盘显示:
重写Activity dispatchTouch
[java] view plain copy
- @Override
- public boolean dispatchTouchEvent(MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- View v = getCurrentFocus();
- if ( v instanceof EditText) {
- Rect outRect = new Rect();
- v.getGlobalVisibleRect(outRect);
- if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
- v.clearFocus();
- InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
- }
- }
- }
- return super.dispatchTouchEvent( event );
- }
EditText始终不弹出软件键盘
EditText edit=(EditText)findViewById(R.id.edit); edit.setInputType(InputType.TYPE_NULL);
还可以
[java] view plain copy
- InputMethodManager imm = (InputMethodManager)v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- if(imm.isActive()){ //这里可以判断也可以不判断
- imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0 );
- }
1,在设置软键盘弹出属性界面加载后,软键盘不能弹出,不能弹出软键盘的主要原因是Android程序未将屏幕绘制完成,所以延迟一定时间,弹出软键盘。
方法一:
[java] view plain copy
- private Handler hander=new Handler(){
- public void handleMessage(android.os.Message msg) {
- edit.setFocusable(true);
- edit.setFocusableInTouchMode(true);
- edit.requestFocus();
- InputMethodManager inputManager = (InputMethodManager)edit.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- inputManager.showSoftInput(edit, 0);
- };
- };
[java] view plain copy
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- if(visible){
- hander.sendEmptyMessageDelayed(0, 1000);
- }
- }
方法二:
[java] view plain copy
- Timer timer = new Timer();
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- InputMethodManager m = (InputMethodManager) editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
- }
- }, 300);
<activity android:windowSoftInputMode="stateVisible|adjustResize" . . . >
该Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间
软键盘打开,关闭监控:
[java] view plain copy
- import android.app.Activity;
- import android.os.Build;
- import android.view.View;
- import android.view.ViewTreeObserver;
- import android.view.Window;
- import android.view.WindowManager;
- import java.lang.ref.WeakReference;
- /**
- * Created by froger_mcs on 21/03/16.
- */
- public class KeyboardWatcher {
- private WeakReference<Activity> activityRef;
- private WeakReference<View> rootViewRef;
- private WeakReference<OnKeyboardToggleListener> onKeyboardToggleListenerRef;
- private ViewTreeObserver.OnGlobalLayoutListener viewTreeObserverListener;
- public KeyboardWatcher(Activity activity) {
- activityRef = new WeakReference<>(activity);
- initialize();
- }
- public void setListener(OnKeyboardToggleListener onKeyboardToggleListener) {
- onKeyboardToggleListenerRef = new WeakReference<>(onKeyboardToggleListener);
- }
- public void destroy() {
- if (rootViewRef.get() != null)
- if (Build.VERSION.SDK_INT >= 16) {
- rootViewRef.get().getViewTreeObserver().removeOnGlobalLayoutListener(viewTreeObserverListener);
- } else {
- rootViewRef.get().getViewTreeObserver().removeGlobalOnLayoutListener(viewTreeObserverListener);
- }
- }
- private void initialize() {
- if (hasAdjustResizeInputMode()) {
- viewTreeObserverListener = new GlobalLayoutListener();
- rootViewRef = new WeakReference<>(activityRef.get().findViewById(Window.ID_ANDROID_CONTENT));
- rootViewRef.get().getViewTreeObserver().addOnGlobalLayoutListener(viewTreeObserverListener);
- } else {
- throw new IllegalArgumentException(String.format("Activity %s should have windowSoftInputMode=\"adjustResize\"" +
- "to make KeyboardWatcher working. You can set it in AndroidManifest.xml", activityRef.get().getClass().getSimpleName()));
- }
- }
- private boolean hasAdjustResizeInputMode() {
- return (activityRef.get().getWindow().getAttributes().softInputMode & WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) != 0;
- }
- private class GlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
- int initialValue;
- boolean hasSentInitialAction;
- boolean isKeyboardShown;
- @Override
- public void onGlobalLayout() {
- if (initialValue == 0) {
- initialValue = rootViewRef.get().getHeight();
- } else {
- if (initialValue > rootViewRef.get().getHeight()) {
- if (onKeyboardToggleListenerRef.get() != null) {
- if (!hasSentInitialAction || !isKeyboardShown) {
- isKeyboardShown = true;
- onKeyboardToggleListenerRef.get().onKeyboardShown(initialValue - rootViewRef.get().getHeight());
- }
- }
- } else {
- if (!hasSentInitialAction || isKeyboardShown) {
- isKeyboardShown = false;
- rootViewRef.get().post(new Runnable() {
- @Override
- public void run() {
- if (onKeyboardToggleListenerRef.get() != null) {
- onKeyboardToggleListenerRef.get().onKeyboardClosed();
- }
- }
- });
- }
- }
- hasSentInitialAction = true;
- }
- }
- }
- public interface OnKeyboardToggleListener {
- void onKeyboardShown(int keyboardSize);
- void onKeyboardClosed();
- }
- }
使用监控:
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize" />
keyboardWatcher = new KeyboardWatcher(this);
keyboardWatcher.setListener(this);
1,绑定软键盘到EditText:
[java] view plain copy
- edit.setFocusable(true);
- edit.setFocusableInTouchMode(true);
- edit.requestFocus();
- InputMethodManager inputManager = (InputMethodManager)edit.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- inputManager.showSoftInput(edit, 0);
2,点击空白区域去除EditText软键盘显示:
重写Activity dispatchTouch
[java] view plain copy
- @Override
- public boolean dispatchTouchEvent(MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- View v = getCurrentFocus();
- if ( v instanceof EditText) {
- Rect outRect = new Rect();
- v.getGlobalVisibleRect(outRect);
- if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
- v.clearFocus();
- InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
- }
- }
- }
- return super.dispatchTouchEvent( event );
- }
EditText始终不弹出软件键盘
EditText edit=(EditText)findViewById(R.id.edit); edit.setInputType(InputType.TYPE_NULL);
还可以
[java] view plain copy
- InputMethodManager imm = (InputMethodManager)v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- if(imm.isActive()){ //这里可以判断也可以不判断
- imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), 0 );
- }
1,在设置软键盘弹出属性界面加载后,软键盘不能弹出,不能弹出软键盘的主要原因是Android程序未将屏幕绘制完成,所以延迟一定时间,弹出软键盘。
方法一:
[java] view plain copy
- private Handler hander=new Handler(){
- public void handleMessage(android.os.Message msg) {
- edit.setFocusable(true);
- edit.setFocusableInTouchMode(true);
- edit.requestFocus();
- InputMethodManager inputManager = (InputMethodManager)edit.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- inputManager.showSoftInput(edit, 0);
- };
- };
[java] view plain copy
- @Override
- public void onWindowFocusChanged(boolean hasWindowFocus) {
- if(visible){
- hander.sendEmptyMessageDelayed(0, 1000);
- }
- }
方法二:
[java] view plain copy
- Timer timer = new Timer();
- timer.schedule(new TimerTask() {
- @Override
- public void run() {
- InputMethodManager m = (InputMethodManager) editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- m.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
- }
- }, 300);
<activity android:windowSoftInputMode="stateVisible|adjustResize" . . . >
该Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间
软键盘打开,关闭监控:来源girhub:
[java] view plain copy
- import android.app.Activity;
- import android.os.Build;
- import android.view.View;
- import android.view.ViewTreeObserver;
- import android.view.Window;
- import android.view.WindowManager;
- import java.lang.ref.WeakReference;
- /**
- * Created by froger_mcs on 21/03/16.
- */
- public class KeyboardWatcher {
- private WeakReference<Activity> activityRef;
- private WeakReference<View> rootViewRef;
- private WeakReference<OnKeyboardToggleListener> onKeyboardToggleListenerRef;
- private ViewTreeObserver.OnGlobalLayoutListener viewTreeObserverListener;
- public KeyboardWatcher(Activity activity) {
- activityRef = new WeakReference<>(activity);
- initialize();
- }
- public void setListener(OnKeyboardToggleListener onKeyboardToggleListener) {
- onKeyboardToggleListenerRef = new WeakReference<>(onKeyboardToggleListener);
- }
- public void destroy() {
- if (rootViewRef.get() != null)
- if (Build.VERSION.SDK_INT >= 16) {
- rootViewRef.get().getViewTreeObserver().removeOnGlobalLayoutListener(viewTreeObserverListener);
- } else {
- rootViewRef.get().getViewTreeObserver().removeGlobalOnLayoutListener(viewTreeObserverListener);
- }
- }
- private void initialize() {
- if (hasAdjustResizeInputMode()) {
- viewTreeObserverListener = new GlobalLayoutListener();
- rootViewRef = new WeakReference<>(activityRef.get().findViewById(Window.ID_ANDROID_CONTENT));
- rootViewRef.get().getViewTreeObserver().addOnGlobalLayoutListener(viewTreeObserverListener);
- } else {
- throw new IllegalArgumentException(String.format("Activity %s should have windowSoftInputMode=\"adjustResize\"" +
- "to make KeyboardWatcher working. You can set it in AndroidManifest.xml", activityRef.get().getClass().getSimpleName()));
- }
- }
- private boolean hasAdjustResizeInputMode() {
- return (activityRef.get().getWindow().getAttributes().softInputMode & WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) != 0;
- }
- private class GlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
- int initialValue;
- boolean hasSentInitialAction;
- boolean isKeyboardShown;
- @Override
- public void onGlobalLayout() {
- if (initialValue == 0) {
- initialValue = rootViewRef.get().getHeight();
- } else {
- if (initialValue > rootViewRef.get().getHeight()) {
- if (onKeyboardToggleListenerRef.get() != null) {
- if (!hasSentInitialAction || !isKeyboardShown) {
- isKeyboardShown = true;
- onKeyboardToggleListenerRef.get().onKeyboardShown(initialValue - rootViewRef.get().getHeight());
- }
- }
- } else {
- if (!hasSentInitialAction || isKeyboardShown) {
- isKeyboardShown = false;
- rootViewRef.get().post(new Runnable() {
- @Override
- public void run() {
- if (onKeyboardToggleListenerRef.get() != null) {
- onKeyboardToggleListenerRef.get().onKeyboardClosed();
- }
- }
- });
- }
- }
- hasSentInitialAction = true;
- }
- }
- }
- public interface OnKeyboardToggleListener {
- void onKeyboardShown(int keyboardSize);
- void onKeyboardClosed();
- }
- }
使用监控:
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustResize" />
keyboardWatcher = new KeyboardWatcher(this);
keyboardWatcher.setListener(this);
动态关闭软键盘
有时希望根据条件动态关闭软键盘,我们可以使用InputMethodManager类,按照下面的方法来实现:
方法一:
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); //得到InputMethodManager的实例
if (imm.isActive()) {//如果开启
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT,InputMethodManager.HIDE_NOT_ALWAYS);//关闭软键盘,开启方法相同,这个方法是切换开启与关闭状态的
}
方法二:
强制隐藏软键盘
public void KeyBoardCancle() {
View view = getWindow().peekDecorView();
if (view != null) {
InputMethodManager inputmanger = (InputMethodManager) getSystemService(ActivityBase.INPUT_METHOD_SERVICE);
inputmanger.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
方法三:
int flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
getWindow().addFlags(flags);
方法四:
在onclick事件下.以下方法可行.(如果是EditText失去焦点/得到焦点,没有效果)
InputMethodManager im = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(getCurrentFocus().getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
软键盘界面按钮功能设置方法
使用android:imeOptinos可对Android自带的软键盘进行一些界面上的设置:
<EditText
android:id="@+id/text1"
android:layout_width="150dip"
android:layout_height="wrap_content"
android:imeOptions="flagNoExtractUi"/>
android:imeOptions="flagNoExtractUi" //使软键盘不全屏显示,只占用一部分屏幕
同时,这个属性还能控件软键盘右下角按键的显示内容,默认情况下为回车键
android:imeOptions="actionNone" //输入框右侧不带任何提示
android:imeOptions="actionGo" //右下角按键内容为'开始'
android:imeOptions="actionSearch" //右下角按键为放大镜图片,搜索
android:imeOptions="actionSend" //右下角按键内容为'发送'
android:imeOptions="actionNext" //右下角按键内容为'下一步'
android:imeOptions="actionDone" //右下角按键内容为'完成'
一、软键盘无法顶起页面
开发中有个需求是将页面底部的一个按钮顶起,但是开发时发现Android5.0以后的版本设置了adjustResize属性后无法成功顶起。纠结了好久,最后在stackoverflow找到解决方案,那就是在根布局上加上fitsSystemWindow=”true”即可。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
>
也可以使用AndroidBug5497Workaround解决键盘问题
二、自定义软键盘按钮功能无效
在edittext上加入Android:imeOptions=”actionSearch”这个属性没响应,最后发现在2.3及以上版本不起作用,解决方案:加上
android:singleLine="true"
因为输入法键盘右下角默认的回车键本来就是换行用的,当设置单行后,回车换行就失去作用了,这样就可以设置为搜索、发送、go等等。