我的布局中有一个EditText和一个Button。
在编辑字段中写入并单击按钮后,我想在触摸键盘外部时隐藏虚拟键盘。我假设这是一段简单的代码,但我在哪里可以找到它的示例?
我的布局中有一个EditText和一个Button。
在编辑字段中写入并单击按钮后,我想在触摸键盘外部时隐藏虚拟键盘。我假设这是一段简单的代码,但我在哪里可以找到它的示例?
当前回答
以上答案适用于不同的场景,但如果您想将键盘隐藏在视图中,并努力获得正确的上下文,请尝试以下操作:
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
hideSoftKeyBoardOnTabClicked(v);
}
}
private void hideSoftKeyBoardOnTabClicked(View v) {
if (v != null && context != null) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getApplicationWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
并从构造函数获取上下文:)
public View/RelativeLayout/so and so (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
init();
}
其他回答
我创建了一个布局,部分来自xml,部分来自自定义布局引擎,所有这些都在代码中处理。对我来说,唯一有效的方法是跟踪键盘是否打开,并使用如下键盘切换方法:
public class MyActivity extends Activity
{
/** This maintains true if the keyboard is open. Otherwise, it is false. */
private boolean isKeyboardOpen = false;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
LayoutInflater inflater;
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(context.getResources().getIdentifier("main", "layout", getPackageName()), null);
setContentView(contentView);
contentView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
public void onGlobalLayout()
{
Rect r = new Rect();
contentView.getWindowVisibleDisplayFrame(r);
int heightDiff = contentView.getRootView().getHeight() - (r.bottom - r.top);
if (heightDiff > 100)
isKeyboardVisible = true;
else
isKeyboardVisible = false;
});
}
}
public void closeKeyboardIfOpen()
{
InputMethodManager imm;
imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (isKeyboardVisible)
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}
}
有时你只需要按回车键来折叠键盘在“编辑文本”框中指定属性
android:imeOptions="actionDone"
这将将Enter按钮更改为Done按钮,该按钮将关闭键盘。
如果有人感兴趣的话,我已经为Kotlin写了一个小扩展,但没有太多测试:
fun Fragment.hideKeyboard(context: Context = App.instance) {
val windowToken = view?.rootView?.windowToken
windowToken?.let {
val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(windowToken, 0)
}
}
App.instance是存储在Application中的静态“this”Application对象
更新:在某些情况下,windowToken为空。我增加了使用反射来检测键盘是否关闭的额外关闭方式
/**
* If no window token is found, keyboard is checked using reflection to know if keyboard visibility toggle is needed
*
* @param useReflection - whether to use reflection in case of no window token or not
*/
fun Fragment.hideKeyboard(context: Context = MainApp.instance, useReflection: Boolean = true) {
val windowToken = view?.rootView?.windowToken
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
windowToken?.let {
imm.hideSoftInputFromWindow(windowToken, 0)
} ?: run {
if (useReflection) {
try {
if (getKeyboardHeight(imm) > 0) {
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS)
}
} catch (exception: Exception) {
Timber.e(exception)
}
}
}
}
fun getKeyboardHeight(imm: InputMethodManager): Int = InputMethodManager::class.java.getMethod("getInputMethodWindowVisibleHeight").invoke(imm) as Int
试试这个
简单,您可以在活动中调用
public static void hideKeyboardwithoutPopulate(Activity activity) {
InputMethodManager inputMethodManager =
(InputMethodManager) activity.getSystemService(
Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(
activity.getCurrentFocus().getWindowToken(), 0);
}
在您的主活动中调用
hideKeyboardwithoutPopulate(MainActivity.this);
为了帮助澄清这种疯狂,我想首先代表所有Android用户为谷歌对软键盘的荒谬处理道歉。对于同一个简单的问题,有这么多答案,每个答案都不同,原因是这个API和Android中的许多其他API一样,设计得很糟糕。我想不出有礼貌的方式来表达。
我想隐藏键盘。我希望为Android提供以下语句:Keyboard.hide().结束。非常感谢你。但Android有一个问题。必须使用InputMethodManager隐藏键盘。好吧,这是Android的键盘API。但是!您需要有上下文才能访问IMM。现在我们有一个问题。我可能想将键盘隐藏在一个静态类或实用程序类中,该类不使用或不需要任何上下文。或者更糟糕的是,IMM要求您指定要隐藏键盘的视图(甚至更糟糕的,窗口)。
这就是隐藏键盘如此具有挑战性的原因。亲爱的谷歌:当我在查找蛋糕的食谱时,世界上没有食谱提供商会拒绝向我提供食谱,除非我首先回答世界卫生组织会吃蛋糕以及在哪里吃蛋糕!!
这个悲伤的故事以丑陋的事实结尾:要隐藏Android键盘,你需要提供两种形式的标识:上下文和视图或窗口。
我已经创建了一个静态实用程序方法,只要您从“活动”调用它,它就可以非常可靠地完成任务。
public static void hideKeyboard(Activity activity) {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
//Find the currently focused view, so we can grab the correct window token from it.
View view = activity.getCurrentFocus();
//If no view currently has focus, create a new one, just so we can grab a window token from it
if (view == null) {
view = new View(activity);
}
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
请注意,此实用程序方法仅在从“活动”调用时有效!上述方法调用目标Activity的getCurrentFocus以获取适当的窗口标记。
但是,假设您想对DialogFragment中托管的EditText隐藏键盘?您不能使用上述方法:
hideKeyboard(getActivity()); //won't work
这不会起作用,因为您将传递一个对Fragment的主机Activity的引用,在显示Fragment时,该主机Activity将没有焦点控制!哇!因此,为了隐藏键盘的碎片,我选择了更低级、更常见、更丑陋的方法:
public static void hideKeyboardFrom(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
以下是从浪费更多时间追求此解决方案中收集到的一些附加信息:
关于windowSoftInputMode
还有一个争论点需要注意。默认情况下,Android会自动将初始焦点分配给“活动”中的第一个EditText或可聚焦控件。很自然,InputMethod(通常是软键盘)将通过显示自己来响应焦点事件。AndroidManifest.xml中的windowSoftInputMode属性设置为stateAlwaysHidden时,指示键盘忽略自动分配的初始焦点。
<activity
android:name=".MyActivity"
android:windowSoftInputMode="stateAlwaysHidden"/>
几乎令人难以置信的是,当您触摸控件时,它似乎没有阻止键盘打开(除非将focusable=“false”和/或focusableInTouchMode=“false”分配给控件)。显然,windowSoftInputMode设置仅适用于自动聚焦事件,而不适用于由触摸事件触发的聚焦事件。
因此,stateAlwaysHidden的名称确实非常糟糕。它可能应该被称为ignoreInitialFocus。
更新:获取窗口令牌的更多方法
如果没有聚焦视图(例如,如果您只是更改了片段,可能会发生这种情况),则会有其他视图提供有用的窗口标记。
如果(view==null)view=new view(activity),则这些是上述代码的替代方案;这些并没有明确提到你的活动。
在片段类中:
view = getView().getRootView().getWindowToken();
给定片段片段作为参数:
view = fragment.getView().getRootView().getWindowToken();
从内容主体开始:
view = findViewById(android.R.id.content).getRootView().getWindowToken();
更新2:如果从后台打开应用程序,请清除焦点以避免再次显示键盘
将此行添加到方法的末尾:
view.clearFocus();