not*_*173 88 android focus android-edittext
我的布局包含ListView
,SurfaceView
和EditText
.当我点击EditText
它时,它会获得焦点并弹出屏幕键盘.当我点击EditText
它之外的某个地方时,它仍然有焦点(它不应该).我想我可以OnTouchListener
在布局中设置其他视图并手动清除EditText
焦点.但似乎过于hackish ......
我在其他布局中也有相同的情况 - 列表视图中包含不同类型的项目,其中一些项目EditText
位于内部.他们的行为就像我上面写的那样.
EditText
当用户触摸外面的东西时,任务就是失去焦点.
我在这里看到过类似的问题,但没有找到任何解决方案......
zMa*_*Man 202
以Ken的答案为基础,这是最模块化的复制粘贴解决方案.
不需要XML.
将它放在您的Activity中,它将适用于所有EditTexts,包括该活动中片段内的那些.
@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 );
}
Run Code Online (Sandbox Code Playgroud)
Ken*_*Ken 65
我试过所有这些解决方案.edc598是最接近工作的,但触摸事件没有触发View
布局中包含的其他内容.如果有人需要这种行为,这就是我最终做的事情:
我创建了一个FrameLayout
名为touchInterceptor的(不可见)作为View
布局中的最后一个,以便它覆盖所有内容(编辑:您还必须使用a RelativeLayout
作为父布局并提供touchInterceptor fill_parent
属性).然后我用它来拦截触摸并确定触摸是否在上面EditText
:
FrameLayout touchInterceptor = (FrameLayout)findViewById(R.id.touchInterceptor);
touchInterceptor.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mEditText.isFocused()) {
Rect outRect = new Rect();
mEditText.getGlobalVisibleRect(outRect);
if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
mEditText.clearFocus();
InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
}
return false;
}
});
Run Code Online (Sandbox Code Playgroud)
返回false以使触摸处理失效.
这很hacky,但它是唯一对我有用的东西.
小智 32
对于EditText的父视图,让以下3个属性为" true ":
clickable,focusable,focusableInTouchMode.
如果视图想要获得焦点,则必须满足这3个条件.
见android.view:
public boolean onTouchEvent(MotionEvent event) {
...
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
...
if (isFocusable() && isFocusableInTouchMode()
&& !isFocused()) {
focusTaken = requestFocus();
}
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你.
小智 18
只需将这些属性放在最顶层的父级中.
android:focusableInTouchMode="true"
android:clickable="true"
android:focusable="true"
Run Code Online (Sandbox Code Playgroud)
Mik*_*tiz 15
肯的回答是有效的,但它很糟糕.正如pcans在答案的评论中暗示的那样,可以使用dispatchTouchEvent完成同样的事情.这个解决方案更清晰,因为它避免了使用透明的虚拟FrameLayout破解XML.这是看起来像:
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
EditText mEditText = findViewById(R.id.mEditText);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if (mEditText.isFocused()) {
Rect outRect = new Rect();
mEditText.getGlobalVisibleRect(outRect);
if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) {
mEditText.clearFocus();
//
// Hide keyboard
//
InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
}
return super.dispatchTouchEvent(event);
}
Run Code Online (Sandbox Code Playgroud)
这是我基于 zMan 代码的版本。如果下一个视图也是编辑文本,它不会隐藏键盘。如果用户只是滚动屏幕,它也不会隐藏键盘。
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
downX = (int) event.getRawX();
}
if (event.getAction() == MotionEvent.ACTION_UP) {
View v = getCurrentFocus();
if (v instanceof EditText) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
//Was it a scroll - If skip all
if (Math.abs(downX - x) > 5) {
return super.dispatchTouchEvent(event);
}
final int reducePx = 25;
Rect outRect = new Rect();
v.getGlobalVisibleRect(outRect);
//Bounding box is to big, reduce it just a little bit
outRect.inset(reducePx, reducePx);
if (!outRect.contains(x, y)) {
v.clearFocus();
boolean touchTargetIsEditText = false;
//Check if another editText has been touched
for (View vi : v.getRootView().getTouchables()) {
if (vi instanceof EditText) {
Rect clickedViewRect = new Rect();
vi.getGlobalVisibleRect(clickedViewRect);
//Bounding box is to big, reduce it just a little bit
clickedViewRect.inset(reducePx, reducePx);
if (clickedViewRect.contains(x, y)) {
touchTargetIsEditText = true;
break;
}
}
}
if (!touchTargetIsEditText) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
}
}
return super.dispatchTouchEvent(event);
}
Run Code Online (Sandbox Code Playgroud)
你可能已经找到了这个问题的答案,但我一直在寻找如何解决这个问题,但仍然无法找到我想要的东西,所以我想我会在这里发布.
我所做的是以下(这是非常概括的,目的是让你知道如何继续,复制和粘贴所有代码将无法工作O:D):
首先让EditText和您在程序中想要的任何其他视图由单个视图包装.在我的例子中,我使用LinearLayout来包装所有内容.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainLinearLayout">
<EditText
android:id="@+id/editText"/>
<ImageView
android:id="@+id/imageView"/>
<TextView
android:id="@+id/textView"/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
然后在您的代码中,您必须为主LinearLayout设置Touch Listener.
final EditText searchEditText = (EditText) findViewById(R.id.editText);
mainLinearLayout.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(searchEditText.isFocused()){
if(event.getY() >= 72){
//Will only enter this if the EditText already has focus
//And if a touch event happens outside of the EditText
//Which in my case is at the top of my layout
//and 72 pixels long
searchEditText.clearFocus();
InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
Toast.makeText(getBaseContext(), "Clicked", Toast.LENGTH_SHORT).show();
return false;
}
});
Run Code Online (Sandbox Code Playgroud)
我希望这可以帮助一些人.或者至少帮助他们开始解决问题.
对我而言,事无巨细-
1. 添加android:clickable="true"
和android:focusableInTouchMode="true"
对parentLayout
的EditText
,即android.support.design.widget.TextInputLayout
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusableInTouchMode="true">
<EditText
android:id="@+id/employeeID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number"
android:hint="Employee ID"
tools:layout_editor_absoluteX="-62dp"
tools:layout_editor_absoluteY="16dp"
android:layout_marginTop="42dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="36dp"
android:layout_marginEnd="36dp" />
</android.support.design.widget.TextInputLayout>
Run Code Online (Sandbox Code Playgroud)
2. 覆盖dispatchTouchEvent
Activity类和插入hideKeyboard()
函数
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
View view = getCurrentFocus();
if (view != null && view instanceof EditText) {
Rect r = new Rect();
view.getGlobalVisibleRect(r);
int rawX = (int)ev.getRawX();
int rawY = (int)ev.getRawY();
if (!r.contains(rawX, rawY)) {
view.clearFocus();
}
}
}
return super.dispatchTouchEvent(ev);
}
public void hideKeyboard(View view) {
InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
Run Code Online (Sandbox Code Playgroud)
3. 为EditText 添加setOnFocusChangeListener
EmployeeId.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
hideKeyboard(v);
}
}
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
105784 次 |
最近记录: |