【问题标题】:EditText does not trigger changes when back is pressed按下后退时 EditText 不会触发更改
【发布时间】:2011-08-02 20:43:07
【问题描述】:

在带有购物车的应用程序中,我提供了通过 EditText 更改商品数量的选项,该选项只允许输入数字。
一切正常,除非用户更改字段然后按后退键隐藏软键盘。在这种情况下,该字段显示更改的值,但我不知道如何检测到此更改并对其做出反应。等待切换到另一个活动不是一种选择。
当用户使用“完成”按钮确认时,我可以使用“OnEditorActionListener”来处理它。但是后退键呢?

更新:
事实证明,使用返回键关闭软键盘时,编辑字段上的 onKeyDown / onBackPressed 和 OnKeyListener 都不会触发。

【问题讨论】:

    标签: android android-edittext back


    【解决方案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 已更改,您将收到通知是否现在显示。

    希望我的回答有用。也许您再次在 StackOverFlow 上找到了真正的来源。所以我不会偷别人的天才。学分归未知人所有;)

    【讨论】:

    • 我还没有尝试过这个解决方案,但是看看代码我很确定它可以工作。我从没想过这个看似微不足道的问题需要这样的黑客攻击。感谢您的代码(即使不是自己编写的)!
    【解决方案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;
            }
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-06-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多