简体   繁体   English

强制EditText在后退时失去焦点

[英]Force EditText to lose focus when back pressed

I'm trying to force the EditText control to lose focus when the user presses the back button to hide the keyboard. 当用户按下后退按钮隐藏键盘时,我试图强制EditText控件失去焦点。 There are many questions similar to this already, but after several hours, I haven't been able to make it work. 有很多类似的问题已经存在,但几个小时后,我无法使其发挥作用。

First, just a little bit of context. 首先,只是一点点背景。 I have a ListView with custom items. 我有一个带有自定义项目的ListView。 Each item has several TextViews and one EditText. 每个项目都有几个TextView和一个EditText。 I have an AfterTextChanged() method saving edited values. 我有一个AfterTextChanged()方法保存编辑的值。 I have a style set up to highlight the field if it has focus. 如果有焦点,我会设置一个样式来突出显示该字段。 Unfortunately, it is now much more obvious that the EditText doesn't actually lose focus when you hide the (soft) keyboard, and I think it's confusing. 不幸的是,现在更明显的是,当您隐藏(软)键盘时,EditText实际上不会失去焦点,我认为这令人困惑。 I would like the EditText to not be focused if there's no keyboard. 如果没有键盘,我希望EditText不会聚焦。

The solution that seemed the most reasonable is to override OnBackPressed() in the activity as described here . 似乎最合理的解决方案是为描述重写OnBackPressed()在活动这里 Unfortunately, it doesn't appear that my method is being called. 不幸的是,似乎没有调用我的方法。 Ie the field is still focused, and a breakpoint in the function doesn't fire. 即场仍然是聚焦的,并且函数中的断点不会触发。

Similarly, an OnKeyUp() listener on the activity doesn't fire, and Xamarin doesn't appear to support the OnKeyUp handler for the EditText control. 类似地,活动上的OnKeyUp()侦听器不会触发,并且Xamarin似乎不支持EditText控件的OnKeyUp处理程序。

I'm not trying to suppress the keyboard on creation, or anything, so using any of the invisible control tricks don't help either. 我不打算在创作或任何东西上压制键盘,因此使用任何隐形控制技巧也无济于事。

It's obvious that a lot of people have this problem. 很明显很多人都有这个问题。 I'm sure one of you has solved it! 我相信你们其中一个人已经解决了! Can you please share your solution? 你能分享一下你的解决方案吗?

Thank you so much! 非常感谢! -Karen -Karen

PS I do not need to know how to hide the keyboard. PS我不需要知道如何隐藏键盘。 I need to take an action when the user hides the keyboard with the back button. 当用户使用后退按钮隐藏键盘时,我需要执行操作。 Thanks :) 谢谢 :)

In my experience onBackPressed() (at least the default @Override one in an activity) will not normally fire when pushing the back button to close the keyboard. 根据我的经验,onBackPressed()(至少在活动中默认为@Override)在按下后退按钮关闭键盘时通常不会触发。 As far as I know it will only fire when a Back press would initiate a finish() on the current activity. 据我所知,只有当Back press会在当前活动中启动finish()时才会触发。

Below is a kind of "hacky" way to know when the keyboard is shown/hidden by monitoring the change in the view size. 下面是一种通过监视视图大小的变化来了解何时显示/隐藏键盘的“hacky”方式。 You must also set the Activity to android:windowSoftInputMode="adjustResize" in the AndroidManifest.xml. 您还必须在AndroidManifest.xml中将Activity设置为android:windowSoftInputMode="adjustResize"

final View activityRootView = findViewById("Your main View");
    activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        Rect r = new Rect();
        //r will be populated with the coordinates of your view that area still visible.
        activityRootView.getWindowVisibleDisplayFrame(r);

        int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);
        if (heightDiff > 100) { // if more than 100 pixels, its probably a keyboard...
          //Keyboard is shown


        }
        if(heightDiff <= 100) {
            //Keybaord not shown
        }
     }
    });

With sincere thanks to @Shadesblade (and Xamarin's sample code), my EditTexts now unfocus! 真诚地感谢@Shadesblade(和Xamarin的示例代码),我的EditTexts现在没有重点! Here's the Xamarin-ized solution: 这是Xamarin化的解决方案:

To your activity, add this class: 在您的活动中,添加以下类:

class GlobalLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
{
    Action on_global_layout;
    public GlobalLayoutListener (Action onGlobalLayout)
    {
        on_global_layout = onGlobalLayout;
    }

    public void OnGlobalLayout ()
    {
        on_global_layout ();
    }
}

Add a class variable to hold the View so that the delegate can access it: 添加一个类变量来保存View,以便委托可以访问它:

View _rootview;

In your OnCreate() add: 在你的OnCreate()中添加:

GlobalLayoutListener gll = new GlobalLayoutListener(
    delegate {
        Android.Graphics.Rect r = new Android.Graphics.Rect();
        _rootView.GetWindowVisibleDisplayFrame(r);
        int heightDiff = _rootView.RootView.Height - (r.Bottom - r.Top);
        if (heightDiff < 100)
        {
            if (Window.CurrentFocus != null)
                Window.CurrentFocus.ClearFocus();
        }
    });

_rootView = FindViewById<View>(Resource.Id.relativeLayoutOrder);
_rootView.ViewTreeObserver.AddOnGlobalLayoutListener(gll);

I expect to need to dork around with the heightDiff level and/or have to add some rotation checking, but I haven't done any rotation support at this point, so I can punt that until later. 我希望需要使用heightDiff级别来调整和/或必须添加一些旋转检查,但此时我还没有做任何旋转支持,所以我可以直到稍后才进行调整。

Thank you again! 再次感谢你! * happy dance * * 快乐的舞蹈 *

adding on to Shadesblade's answer, if you are using a scrollview, his answer needs a change to work, because not all of the scrollview is showing on screen. 添加到Shadesblade的答案,如果你使用的是scrollview,他的答案需要改变才能工作,因为并非所有的scrollview都在屏幕上显示。 so instead of doing 所以不要这样做

int heightDiff = activityRootView.getRootView().getHeight() - (r.bottom - r.top);

you should do 你应该做

int heightDiff = Utils.getScreenHeight(SearchActivity.this) - (r.bottom - r.top);

where Utils.getScreenHeight is this: Utils.getScreenHeight是这样的:

public static int getScreenHeight(Context c) {
    if (screenHeight == 0) {
        WindowManager wm = (WindowManager) c.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        screenHeight = size.y;
        screenWidth = size.x;
    }
    return screenHeight;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM