5

I'm trying to force the EditText control to lose focus when the user presses the back button to hide the keyboard. 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. Each item has several TextViews and one EditText. I have an AfterTextChanged() method saving edited values. 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. I would like the EditText to not be focused if there's no keyboard.

The solution that seemed the most reasonable is to override OnBackPressed() in the activity as described here. Unfortunately, it doesn't appear that my method is being called. I.e. 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.

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

P.S. I do not need to know how to hide the keyboard. I need to take an action when the user hides the keyboard with the back button. Thanks :)

4

3 回答 3

7

根据我的经验 onBackPressed() (至少是活动中的默认 @Override 之一)在按下后退按钮关闭键盘时通常不会触发。据我所知,它只会在 Back press 启动当前活动的 finish() 时触发。

下面是一种通过监视视图大小的变化来了解何时显示/隐藏键盘的“hacky”方式。您还必须android:windowSoftInputMode="adjustResize"在 AndroidManifest.xml 中将 Activity 设置为。

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
        }
     }
    });
于 2013-08-12T22:32:19.197 回答
2

衷心感谢@Shadesblade(和 Xamarin 的示例代码),我的 EditTexts 现在没有焦点了!这是 Xamarin 化的解决方案:

在您的活动中,添加此类:

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 ();
    }
}

添加一个类变量来保存视图,以便委托可以访问它:

View _rootview;

在您的 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);

我希望需要使用 heightDiff 级别和/或必须添加一些旋转检查,但此时我还没有做任何旋转支持,所以我可以在稍后再取消它。

再次感谢你!*快乐的舞蹈*

于 2013-08-12T23:22:02.883 回答
0

添加到 Shadesblade 的答案,如果您使用的是滚动视图,他的答案需要更改才能工作,因为并非所有滚动视图都显示在屏幕上。所以而不是做

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

你应该做

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

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;
}
于 2016-07-30T12:21:29.083 回答