按下后退时 EditText 不会触发更改
Posted
技术标签:
【中文标题】按下后退时 EditText 不会触发更改【英文标题】:EditText does not trigger changes when back is pressed 【发布时间】:2011-08-02 20:43:07 【问题描述】:在带有购物车的应用程序中,我提供了通过 EditText 更改商品数量的选项,该选项只允许输入数字。 一切正常,除非用户更改字段然后按后退键隐藏软键盘。在这种情况下,该字段显示更改的值,但我不知道如何检测到此更改并对其做出反应。等待切换到另一个活动不是一种选择。 当用户使用“完成”按钮确认时,我可以使用“OnEditorActionListener”来处理它。但是后退键呢?
更新: 事实证明,使用返回键关闭软键盘时,编辑字段上的 onKeyDown / onBackPressed 和 OnKeyListener 都不会触发。
【问题讨论】:
【参考方案1】:我在前段时间编写的应用程序中遇到了同样的问题。它现在已停产,但这不是你的问题 xD。
事实上,没有选项可以跟踪这样的操作,但我找到了一个很好的(或多或少)解决方案来添加这样的功能。这在理论上很简单,但我认为它也是一个“黑客”。
因此,您需要一个包含您的应用程序或特殊区域的自定义线性布局。之后,您必须为其添加一个侦听器。这仅适用于纵向模式。
所以这里是代码:(对不起,我不记得出处了)
自定义布局:
LinearLayoutThatDetactsSoftwarekeyboard.java(这是布局 xD 的原始名称)
package com.tundem.people.Layout;
import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.LinearLayout;
/*
* LinearLayoutThatDetectsSoftKeyboard - a variant of LinearLayout that can detect when
* the soft keyboard is shown and hidden (something Android can't tell you, weirdly).
*/
public class LinearLayoutThatDetectSoftkeyboard extends LinearLayout
public LinearLayoutThatDetectSoftkeyboard(Context context, AttributeSet attrs)
super(context, attrs);
public interface Listener
public void onSoftKeyboardShown(boolean isShowing);
private Listener listener;
public void setListener(Listener listener)
this.listener = listener;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
int height = MeasureSpec.getSize(heightMeasureSpec);
Activity activity = (Activity) getContext();
Rect rect = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
int diff = (screenHeight - statusBarHeight) - height;
if (listener != null)
listener.onSoftKeyboardShown(diff > 128); // assume all soft
// keyboards are at
// least 128 pixels high
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
以及如何添加监听器:
final LinearLayoutThatDetectSoftkeyboard lltodetectsoftkeyboard = (LinearLayoutThatDetectSoftkeyboard) findViewById(R.id.LinearLayout_SoftKeyboard);
lltodetectsoftkeyboard.setListener(new Listener()
public void onSoftKeyboardShown(boolean isShowing)
if (actMode == MODE_SMS && isShowing)
findViewById(R.id.LinearLayout_bottomnavigationbar).setVisibility(View.GONE);
else
findViewById(R.id.LinearLayout_bottomnavigationbar).setVisibility(View.VISIBLE);
);
LinearLayout 添加了一个监听器,每当 layoutheight 改变至少 128 像素时都会调用该监听器。这是一个技巧,它不适用于小于 128 像素的键盘(但我认为每个键盘都有这样的高度) 如果 LayoutHeight 已更改,您将收到通知是否现在显示。
希望我的回答有用。也许您再次在 *** 上找到了真正的来源。所以我不会偷别人的天才。学分归未知人所有;)
【讨论】:
我还没有尝试过这个解决方案,但是看看代码我很确定它可以工作。我从没想过这个看似微不足道的问题需要这样的黑客攻击。感谢您的代码(即使不是自己编写的)!【参考方案2】:这是 @mikepenz 答案的修改版本,因为它不适用于具有 windowSoftInputMode="adjustPan" 模式的 Android 8。
语言是 kotlin。 将此视图用作根视图并设置keyboardListener:
class KeyboardAwareConstraintLayout(context: Context?, attrs: AttributeSet?) : ConstraintLayout(context, attrs)
var keyboardListener: KeyboardListener? = null
constructor(context: Context?) : this(context, null)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int)
val rect = Rect()
getWindowVisibleDisplayFrame(rect)
val statusBarHeight = rect.top
val keyboardHeight = rootView.height - (rect.bottom - rect.top) - statusBarHeight
// R.dimen.keyboard_min_height has set to 120dp,
// as a reasonable minimum height of a soft keyboard
val minKeyboardHeight = resources.getDimensionPixelSize(R.dimen.keyboard_min_height)
keyboardListener?.onKeyboardShown(keyboardHeight > minKeyboardHeight)
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
interface KeyboardListener
fun onKeyboardShown (shown: Boolean)
【讨论】:
【参考方案3】:您可以在活动中覆盖 onBackPressed(伪代码 - 被警告):
@Override
public void onBackPressed()
if(userHasChangedAnything)
revertChanges();
else
super.onBackPressed();
【讨论】:
我也想过这一点,但是(假设它有效)这将是一个很大的 hack,因为 EditText 位于 Fragment 中,而不是 Activity 中,因此处理此问题的代码将分散在各处。没有更好的解决方案? 这也不起作用(就像 onKeyDown 一样)。关闭键盘时,它不会触发。【参考方案4】:由于代码的新信息位于片段中,我建议在文本框中添加一个关键侦听器。此代码未经测试,但应该可以工作。
((EditText) findViewById(R.id.button)).setOnKeyListener(new OnKeyListener()
@Override
public boolean onKey(View v, int keyCode, KeyEvent event)
if ((keyCode == KeyEvent.KEYCODE_BACK))
Log.d(this.getClass().getName(), "back button pressed");
return true;
return false;
)
【讨论】:
【参考方案5】:如果这不相关,请原谅,但我曾经遇到过这个问题,忘记了我添加了一个 OnKeyListener 来捕获我的 dialogFragment 的背面按下。 我重写了监听器如下。添加了 Top 条件来解决问题。
getDialog().setOnKeyListener(new DialogInterface.OnKeyListener()
@Override
public boolean onKey(DialogInterface dialogInterface, int i, KeyEvent keyEvent)
if(keyEvent.getKeyCode() == KeyEvent.KEYCODE_DEL)
return false;
if(keyEvent.getAction() == KeyEvent.ACTION_DOWN && keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK)
if(iYoutubePickerDialog != null)
iYoutubePickerDialog.closeYoutubeDialog(getDialog());
return true;
);
【讨论】:
以上是关于按下后退时 EditText 不会触发更改的主要内容,如果未能解决你的问题,请参考以下文章
Android:为EditText打开键盘时处理后退按钮单击