我有EditText
名为myTextview
。我希望当我点击EditText
时显示软键盘,但如果我点击EditText
之外,我就会关闭。所以我使用下面的方法。但是当我在视图外单击时,键盘不会被忽略(我单击TextView
)。我该如何修复此代码?
myTextview.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
} else {
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myTextview.getWindowToken(), 0);
}
}
});
答案 0 :(得分:47)
我找到了更好的解决方案:
覆盖您的活动中的dispatchTouchEvent
方法。
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
View v = getCurrentFocus();
if (v != null &&
(ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) &&
v instanceof EditText &&
!v.getClass().getName().startsWith("android.webkit.")) {
int scrcoords[] = new int[2];
v.getLocationOnScreen(scrcoords);
float x = ev.getRawX() + v.getLeft() - scrcoords[0];
float y = ev.getRawY() + v.getTop() - scrcoords[1];
if (x < v.getLeft() || x > v.getRight() || y < v.getTop() || y > v.getBottom())
hideKeyboard(this);
}
return super.dispatchTouchEvent(ev);
}
public static void hideKeyboard(Activity activity) {
if (activity != null && activity.getWindow() != null && activity.getWindow().getDecorView() != null) {
InputMethodManager imm = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(activity.getWindow().getDecorView().getWindowToken(), 0);
}
}
即使您正在使用webview,这也适用。
答案 1 :(得分:15)
也许有点容易:
在编辑文本上设置focusChangedListener,然后在没有焦点的情况下隐藏键盘。
yourEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus){
hideKeyboard();
}
}
});
private void hideKeyboard() {
InputMethodManager imm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(yourEditText.getWindowToken(), 0);
}
答案 2 :(得分:3)
这样,只有触摸可以获得焦点的视图时,键盘才会消失。我建议你做以下事情:
像这样创建一个自定义ViewGroup:
public class TouchLayout extends LinearLayout {
private OnInterceptTouchEventListener mListener;
public TouchLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if(mListener != null) {
return mListener.onInterceptTouchEvent(event);
}
return super.onInterceptTouchEvent(event);
}
public void setOnInterceptTouchEventListener(OnInterceptTouchEventListener listener) {
mListener = listener;
}
public interface OnInterceptTouchEventListener {
public boolean onInterceptTouchEvent(MotionEvent event);
}
}
然后将自定义视图添加为xml布局的根目录:
<com.example.TouchLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
在您的活动中,您应该执行以下操作:
final TouchLayout root = (TouchLayout) findViewById(R.id.root);
final EditText text = (EditText) findViewById(R.id.text);
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
root.setOnInterceptTouchEventListener(new OnInterceptTouchEventListener() {
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
final View v = getCurrentFocus();
if(v != null && v.equals(text)) {
final int screenCords[] = new int[2];
text.getLocationOnScreen(screenCords);
final Rect textRect = new Rect(screenCords[0], screenCords[1], screenCords[0] + text.getWidth(), screenCords[1] + text.getHeight());
if(!textRect.contains(event.getRawX(), event.getRawY() {
imm.hideSoftInputFromWindow(myTextview.getWindowToken(), 0);
// Optionally you can also do the following:
text.setCursorVisible(false);
text.clearFocus();
}
}
return false;
}
};
答案 3 :(得分:3)
使用以下代码。
public static void hideSoftKeyboard(Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
它对我有用。
答案 4 :(得分:2)
辩诉:我知道我没有影响力,但请认真对待我的回答。
问题:点击键盘或使用最少代码编辑文字时关闭软键盘。
解决方案:外部库称为 Butterknife。
单行解决方案:
@OnClick(R.id.activity_signup_layout) public void closeKeyboard() { ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); }
更易读的解决方案:
@OnClick(R.id.activity_signup_layout)
public void closeKeyboard() {
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
说明:将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);
}
Butterknife文档链接: http://jakewharton.github.io/butterknife/
插件: Butterknife将彻底改变您的Android开发。考虑一下。
答案 5 :(得分:0)
视图上的触摸事件将从ACTION_DOWN
开始,从顶部传递到视图层次结构中的此视图。覆盖dispatchTouchEvent
以执行其他操作。这是一个从kotlin中的FrameLayout
扩展的例子:
class TLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet?=null):
FrameLayout(context, attrs){
var preDispatchTouchEvent: ((ev: MotionEvent?)->Boolean)? = null
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
if (preDispatchTouchEvent==null || !preDispatchTouchEvent!!.invoke(ev)) {
super.dispatchTouchEvent(ev)
}
return true
}
}
在此布局下包裹您的EditText
和其他亲戚View
,并设置preDispatchTouchEvent
以在事件不高于此时解除EditText
。
检查this OS question和official doc,以便更深入地了解触摸事件传递。
答案 6 :(得分:0)
Xamarin Android代码:
public override bool DispatchTouchEvent(MotionEvent ev)
{
try
{
View view = CurrentFocus;
if (view != null && (ev.Action == MotionEventActions.Up || ev.Action == MotionEventActions.Move) && view is EditText && !view.Class.Name.StartsWith("android.webkit."))
{
int[] Touch = new int[2];
view.GetLocationOnScreen(Touch);
float x = ev.RawX + view.Left - Touch[0];
float y = ev.RawY + view.Top - Touch[1];
if (x < view.Left || x > view.Right || y < view.Top || y > view.Bottom)
((InputMethodManager)GetSystemService(InputMethodService)).HideSoftInputFromWindow((Window.DecorView.ApplicationWindowToken), 0);
}
}
catch (System.Exception ex)
{
}
return base.DispatchTouchEvent(ev);
}
答案 7 :(得分:0)
我在下面的过程中使用。完美地为我工作。在活动类中添加以下函数。
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_DOWN) {
val v = currentFocus
if (v is EditText) {
val outRect = Rect()
v.getGlobalVisibleRect(outRect)
if (!outRect.contains(event.rawX.toInt(), event.rawY.toInt())) {
Log.d("focus", "touchevent")
v.clearFocus()
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(v.windowToken, 0)
}
}
}
return super.dispatchTouchEvent(event)
}
然后,我将检查片段中的焦点状态。
appCompatEditText.onFocusChangeListener = View.OnFocusChangeListener { view, hasFocus ->
if (!hasFocus) {
toast("Focus Off")
}else {
toast("Focus On")
}
}
我被检入片段。我需要任务状态为“焦点”状态。集中精力我需要完成一些任务。
答案 8 :(得分:0)
在科特林,我使用了波纹管代码,效果很好
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
val v = currentFocus
if (v != null && (ev.action == MotionEvent.ACTION_UP || ev.action == MotionEvent.ACTION_MOVE)
&& v is EditText
&& !v.javaClass.name.startsWith("android.webkit.")
) {
val scrcoords = IntArray(2)
v.getLocationOnScreen(scrcoords)
val x = ev.rawX + v.getLeft() - scrcoords[0]
val y = ev.rawY + v.getTop() - scrcoords[1]
if (x < v.getLeft() || x > v.getRight() || y < v.getTop() || y > v.getBottom()
) hideKeyboard(this)
}
return super.dispatchTouchEvent(ev)
}
fun hideKeyboard(activity: Activity?) {
if (activity != null && activity.window != null && activity.window.decorView != null
) {
val imm = activity
.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(
activity.window.decorView
.windowToken, 0
)
}
}
在Java中,我使用了波纹管代码,效果很好
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
View v = getCurrentFocus();
if (v != null
&& (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE)
&& v instanceof EditText
&& !v.getClass().getName().startsWith("android.webkit.")) {
int scrcoords[] = new int[2];
v.getLocationOnScreen(scrcoords);
float x = ev.getRawX() + v.getLeft() - scrcoords[0];
float y = ev.getRawY() + v.getTop() - scrcoords[1];
if (x < v.getLeft() || x > v.getRight() || y < v.getTop()
|| y > v.getBottom())
hideKeyboard(this);
}
return super.dispatchTouchEvent(ev);
}
public static void hideKeyboard(Activity activity) {
if (activity != null && activity.getWindow() != null
&& activity.getWindow().getDecorView() != null) {
InputMethodManager imm = (InputMethodManager) activity
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(activity.getWindow().getDecorView()
.getWindowToken(), 0);
}
}