hta*_*oya 340 android android-softkeyboard
好的,大家都知道要隐藏你需要实现的键盘:
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
Run Code Online (Sandbox Code Playgroud)
但这里最重要的是当用户触摸或选择任何其他不是EditText
软键盘或软键盘的地方时如何隐藏键盘?
我试图onTouchEvent()
在我的父母Activity
身上使用,但这只有在用户触摸任何其他视图以外且没有滚动视图时才有效.
我尝试实现触摸,单击,集中监听器而没有任何成功.
我甚至尝试实现自己的scrollview来拦截触摸事件,但我只能获取事件的坐标而不是点击的视图.
有没有一种标准的方法来做到这一点?在iPhone中它真的很容易.
Nav*_*h G 556
以下代码段只是隐藏了键盘:
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager =
(InputMethodManager) activity.getSystemService(
Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(
activity.getCurrentFocus().getWindowToken(), 0);
}
Run Code Online (Sandbox Code Playgroud)
您可以将其放在实用程序类中,或者如果要在活动中定义它,请避免使用activity参数或调用hideSoftKeyboard(this)
.
最棘手的部分是何时调用它.您可以编写一个循环遍历View
活动中每个活动的方法,并检查它是否是一个,instanceof EditText
如果它没有注册setOnTouchListener
到该组件,一切都将落实到位.如果你想知道如何做到这一点,事实上它很简单.这是你做的,你写一个像下面这样的递归方法,实际上你可以用它来做任何事情,比如设置自定义字体等......这是方法
public void setupUI(View view) {
// Set up touch listener for non-text box views to hide keyboard.
if (!(view instanceof EditText)) {
view.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
hideSoftKeyboard(MyActivity.this);
return false;
}
});
}
//If a layout container, iterate over children and seed recursion.
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View innerView = ((ViewGroup) view).getChildAt(i);
setupUI(innerView);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这就是全部,只需setContentView
在您的活动中调用此方法即可.如果您想知道要传递什么参数,它是id
父容器的参数.将id
容器分配给您的父容器
<RelativeLayoutPanel android:id="@+id/parent"> ... </RelativeLayout>
并打电话setupUI(findViewById(R.id.parent))
,就是这样.
如果要有效地使用它,可以创建扩展Activity
并将此方法放入其中,并使应用程序中的所有其他活动扩展此活动并setupUI()
在onCreate()
方法中调用它.
希望能帮助到你.
如果您使用多个活动,则将父公布定义为公共ID
<RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>
然后从中扩展一个类Activity
并setupUI(findViewById(R.id.main_parent))
在其中定义OnResume()
并扩展此类而不是``Activityin your program
vid*_*ida 268
您可以通过执行以下步骤来实现此目的:
通过添加以下属性,使父视图(活动的内容视图)可单击并可聚焦
android:clickable="true"
android:focusableInTouchMode="true"
Run Code Online (Sandbox Code Playgroud)实现hideKeyboard()方法
public void hideKeyboard(View view) {
InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
Run Code Online (Sandbox Code Playgroud)最后,设置edittext的onFocusChangeListener.
edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
hideKeyboard(v);
}
}
});
Run Code Online (Sandbox Code Playgroud)正如下面的一条评论中所指出的,如果父视图是ScrollView,这可能不起作用.对于这种情况,可以在ScrollView正下方的视图上添加clickable和focusableInTouchMode.
roe*_*pit 56
我发现接受的答案有点复杂.
这是我的解决方案.添加OnTouchListener
到您的主要布局,即:
findViewById(R.id.mainLayout).setOnTouchListener(this)
Run Code Online (Sandbox Code Playgroud)
并将以下代码放在onTouch方法中.
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
Run Code Online (Sandbox Code Playgroud)
这样您就不必遍历所有视图.
Sau*_*eek 39
我还有一个解决方案来隐藏键盘:
InputMethodManager imm = (InputMethodManager) getSystemService(
Activity.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
Run Code Online (Sandbox Code Playgroud)
在这里通过HIDE_IMPLICIT_ONLY
位置showFlag
和0
位置hiddenFlag
.它将强制关闭软键盘.
小智 37
只需覆盖Activity中的以下代码
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (getCurrentFocus() != null) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
return super.dispatchTouchEvent(ev);
}
Run Code Online (Sandbox Code Playgroud)
hta*_*oya 16
好吧我设法解决了这个问题,我在我的活动上覆盖了dispatchTouchEvent,在那里我使用以下来隐藏键盘.
/**
* Called to process touch screen events.
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
touchDownTime = SystemClock.elapsedRealtime();
break;
case MotionEvent.ACTION_UP:
//to avoid drag events
if (SystemClock.elapsedRealtime() - touchDownTime <= 150){
EditText[] textFields = this.getFields();
if(textFields != null && textFields.length > 0){
boolean clickIsOutsideEditTexts = true;
for(EditText field : textFields){
if(isPointInsideView(ev.getRawX(), ev.getRawY(), field)){
clickIsOutsideEditTexts = false;
break;
}
}
if(clickIsOutsideEditTexts){
this.hideSoftKeyboard();
}
} else {
this.hideSoftKeyboard();
}
}
break;
}
return super.dispatchTouchEvent(ev);
}
Run Code Online (Sandbox Code Playgroud)
编辑: getFields()方法只是一个返回视图中包含文本字段的数组的方法.为了避免在每次触摸时创建这个数组,我创建了一个名为sFields的静态数组,它在getFields()方法中返回.此数组在onStart()方法上初始化,例如:
sFields = new EditText[] {mUserField, mPasswordField};
它并不完美,拖动事件时间只是基于启发式,所以有时它在执行长文件时不会隐藏,我还完成了创建一个方法来获取每个视图的所有editTexts; 否则键盘会在单击其他EditText时隐藏和显示.
仍然,欢迎更清洁和更短的解决方案
Ser*_*tov 14
例如:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
hideKeyboard();
}
}
});
Run Code Online (Sandbox Code Playgroud)
更新:您还可以覆盖onTouchEvent()
您的活动并检查触摸的坐标.如果坐标在EditText之外,则隐藏键盘.
Jis*_*hen 13
我在Activity中实现了dispatchTouchEvent来执行此操作:
private EditText mEditText;
private Rect mRect = new Rect();
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final int action = MotionEventCompat.getActionMasked(ev);
int[] location = new int[2];
mEditText.getLocationOnScreen(location);
mRect.left = location[0];
mRect.top = location[1];
mRect.right = location[0] + mEditText.getWidth();
mRect.bottom = location[1] + mEditText.getHeight();
int x = (int) ev.getX();
int y = (int) ev.getY();
if (action == MotionEvent.ACTION_DOWN && !mRect.contains(x, y)) {
InputMethodManager input = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
input.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
}
return super.dispatchTouchEvent(ev);
}
Run Code Online (Sandbox Code Playgroud)
我测试了它,效果很好!
Hoa*_*inh 11
在任何Activity中覆盖公共布尔dispatchTouchEvent(MotionEvent事件)(或扩展Activity类)
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
View view = getCurrentFocus();
boolean ret = super.dispatchTouchEvent(event);
if (view instanceof EditText) {
View w = getCurrentFocus();
int scrcoords[] = new int[2];
w.getLocationOnScreen(scrcoords);
float x = event.getRawX() + w.getLeft() - scrcoords[0];
float y = event.getRawY() + w.getTop() - scrcoords[1];
if (event.getAction() == MotionEvent.ACTION_UP
&& (x < w.getLeft() || x >= w.getRight()
|| y < w.getTop() || y > w.getBottom()) ) {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0);
}
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
这就是你需要做的一切
Phi*_*hil 11
使用TextInputEditText的更多Kotlin 和Material Design方法(这种方法也与EditTextView兼容)......
1.通过添加以下属性,使父视图(活动/片段的内容视图)可单击并可聚焦
android:focusable="true"
android:focusableInTouchMode="true"
android:clickable="true"
Run Code Online (Sandbox Code Playgroud)
2.为所有View创建扩展(例如,在ViewExtension.kt文件中):
fun View.hideKeyboard(){
val inputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(this.windowToken, 0)
}
Run Code Online (Sandbox Code Playgroud)
3.创建继承TextInputEditText的BaseTextInputEditText.在视图未聚焦时,实现onFocusChanged方法隐藏键盘:
class BaseTextInputEditText(context: Context?, attrs: AttributeSet?) : TextInputEditText(context, attrs){
override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
super.onFocusChanged(focused, direction, previouslyFocusedRect)
if (!focused) this.hideKeyboard()
}
}
Run Code Online (Sandbox Code Playgroud)
4.只需在XML中调用全新的自定义视图:
<android.support.design.widget.TextInputLayout
android:id="@+id/textInputLayout"
...>
<com.your_package.BaseTextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
... />
</android.support.design.widget.TextInputLayout>
Run Code Online (Sandbox Code Playgroud)
就这样.无需修改控制器(片段或活动)来处理这种重复的情况.
而不是遍历所有视图或覆盖 dispatchTouchEvent。
为什么不只是覆盖 Activity 的 onUserInteraction() 这将确保键盘在用户点击 EditText 之外时关闭。
即使 EditText 在 scrollView 内也能工作。
@Override
public void onUserInteraction() {
if (getCurrentFocus() != null) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
}
Run Code Online (Sandbox Code Playgroud)
我修改了Andre Luis IM的解决方案我实现了这个:
我创建了一个实用工具方法来隐藏软键盘,就像Andre Luiz IM所做的那样:
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
Run Code Online (Sandbox Code Playgroud)
但是,不是为每个视图注册一个OnTouchListener,而是性能很差,我只为root视图注册了OnTouchListener.由于事件一直消耗直到被消耗(EditText是默认使用它的视图之一),如果它到达根视图,那是因为它没有被消耗,所以我关闭了软键盘.
findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Utils.hideSoftKeyboard(activity);
return false;
}
});
Run Code Online (Sandbox Code Playgroud)
我知道这个线程已经很老了,正确的答案似乎是有效的,并且有很多工作解决方案,但我认为下面提出的方法可能会在效率和优雅方面带来额外的好处.
我的所有活动都需要这种行为,所以我创建了一个继承自Activity类的CustomActivity类,并"挂钩"了dispatchTouchEvent函数.主要有两个条件需要照顾:
这是我的结果:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_UP) {
final View view = getCurrentFocus();
if(view != null) {
final boolean consumed = super.dispatchTouchEvent(ev);
final View viewTmp = getCurrentFocus();
final View viewNew = viewTmp != null ? viewTmp : view;
if(viewNew.equals(view)) {
final Rect rect = new Rect();
final int[] coordinates = new int[2];
view.getLocationOnScreen(coordinates);
rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight());
final int x = (int) ev.getX();
final int y = (int) ev.getY();
if(rect.contains(x, y)) {
return consumed;
}
}
else if(viewNew instanceof EditText || viewNew instanceof CustomEditText) {
return consumed;
}
final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0);
viewNew.clearFocus();
return consumed;
}
}
return super.dispatchTouchEvent(ev);
}
Run Code Online (Sandbox Code Playgroud)
旁注:此外,我将这些属性分配给根视图,从而可以清除对每个输入字段的关注,并防止输入字段聚焦于活动启动(使内容视图成为"焦点捕获器"):
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final View view = findViewById(R.id.content);
view.setFocusable(true);
view.setFocusableInTouchMode(true);
}
Run Code Online (Sandbox Code Playgroud)
在 kotlin 中,我们可以执行以下操作。无需迭代所有视图。它也适用于片段。
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
currentFocus?.let {
val imm: InputMethodManager = getSystemService(
Context.INPUT_METHOD_SERVICE
) as (InputMethodManager)
imm.hideSoftInputFromWindow(it.windowToken, 0)
}
return super.dispatchTouchEvent(ev)
}
Run Code Online (Sandbox Code Playgroud)
我喜欢dispatchTouchEvent
htafoya 的调用方法,但是:
所以,我做了一些更简单的解决方案:
@Override
public boolean dispatchTouchEvent(final MotionEvent ev) {
// all touch events close the keyboard before they are processed except EditText instances.
// if focus is an EditText we need to check, if the touchevent was inside the focus editTexts
final View currentFocus = getCurrentFocus();
if (!(currentFocus instanceof EditText) || !isTouchInsideView(ev, currentFocus)) {
((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
return super.dispatchTouchEvent(ev);
}
/**
* determine if the given motionevent is inside the given view.
*
* @param ev
* the given view
* @param currentFocus
* the motion event.
* @return if the given motionevent is inside the given view
*/
private boolean isTouchInsideView(final MotionEvent ev, final View currentFocus) {
final int[] loc = new int[2];
currentFocus.getLocationOnScreen(loc);
return ev.getRawX() > loc[0] && ev.getRawY() > loc[1] && ev.getRawX() < (loc[0] + currentFocus.getWidth())
&& ev.getRawY() < (loc[1] + currentFocus.getHeight());
}
Run Code Online (Sandbox Code Playgroud)
有一个缺点:
从一个切换EditText
到另一个EditText
使键盘隐藏和重新显示 - 在我的情况下,它需要这样,因为它显示您在两个输入组件之间切换.
辩诉:我知道我没有影响力,但请认真对待我的回答.
问题:单击远离键盘或使用最少代码编辑文本时,关闭软键盘.
解决方案:外部库称为Butterknife.
单线解决方案:
@OnClick(R.id.activity_signup_layout) public void closeKeyboard() { ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); }
Run Code Online (Sandbox Code Playgroud)
更易读的解决方案:
@OnClick(R.id.activity_signup_layout)
public void closeKeyboard() {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
Run Code Online (Sandbox Code Playgroud)
说明:将 OnClick侦听器绑定到活动的XML布局父ID,以便对布局(而不是编辑文本或键盘)上的任何单击都将运行将隐藏键盘的代码片段.
示例: 如果您的布局文件是R.layout.my_layout,并且您的布局ID是R.id.my_layout_id,那么您的Butterknife绑定调用应该如下所示:
(@OnClick(R.id.my_layout_id)
public void yourMethod {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
Run Code Online (Sandbox Code Playgroud)
Butterknife文档链接: http ://jakewharton.github.io/butterknife/
插件: Butterknife将彻底改变您的Android开发.考虑一下.
注意:如果不使用外部库Butterknife,可以获得相同的结果.只需将OnClickListener设置为父布局,如上所述.
小智 5
它太简单了,只需通过以下代码使您最近的布局可点击即可:
android:id="@+id/loginParentLayout"
android:clickable="true"
android:focusableInTouchMode="true"
Run Code Online (Sandbox Code Playgroud)
然后为该布局编写一个方法和一个 OnClickListner ,这样当最上面的布局被触摸时,它会调用一个方法,您将在其中编写代码来关闭键盘。以下是两者的代码;// 你必须在 OnCreate() 中写这个
yourLayout.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
hideKeyboard(view);
}
});
Run Code Online (Sandbox Code Playgroud)
从侦听器调用的方法:-
public void hideKeyboard(View view) {
InputMethodManager imm =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
330779 次 |
最近记录: |