Xamarin键盘打开时的按钮命令 [英] Xamarin Button Command with Keyboard Open

查看:123
本文介绍了Xamarin键盘打开时的按钮命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在专为iOS平台开发Xamarin.Forms项目.我彼此之间有一个Editor控件和一个Button控件.当我将焦点放在编辑器上时,输入一些文本,然后单击按钮,该命令似乎没有被触发,而只是在关闭键盘.然后,我不得不再次点击添加按钮以触发该命令.

I am working on an Xamarin.Forms project specifically for the iOS platform. I have an Editor control and a Button control next to each other. When I focus the editor, enter some text, and click the button it appears the command is not being fired but rather the keyboard is simply closing. I then have to tap the add button again for the command to be fired.

<StackLayout Orientation="Horizontal">
    <Editor HorizontalOptions="FillAndExpand"
            Text="{Binding EditorText}"/>
    <Button Text="Add" 
            Command="{Binding AddCommand}"/>
</StackLayout>

我尝试创建一个自定义渲染器,以防止键盘最初关闭,然后在延迟后将其关闭.这样可以触发该命令,但是键盘一直处于打开状态.

I have tried creating a custom renderer that prevents the keyboard from closing initially and then close it after a delay. That allows the command to be fired, but I am stuck with the keyboard being open.

public class KeyboardEditorRenderer : EditorRenderer
{
    protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == VisualElement.IsFocusedProperty.PropertyName)
        {
            if (Control != null)
            {
                Control.ShouldEndEditing = (UITextView textField) =>
                {
                    Task.Delay(10).ContinueWith(_ =>
                    {
                        // THIS DOES NOT WORK
                        textField.EndEditing(true);
                    });

                    return false;
                };
            }
        }

        base.OnElementPropertyChanged(sender, e);
    }
}

我的理想解决方案是您能够输入文本,点击添加按钮,然后关闭键盘并同时执行命令.关于如何实现这一目标的任何想法?

My ideal solution is that you are able to enter text, tap the add button, and the keyboard closes and the command executes simultaneously. Any ideas on how to achieve this?

事实证明问题出在我用于页面的自定义渲染器上.当键盘出现时,自定义渲染器将调整页面大小,以使其不覆盖我的编辑器字段.

It turns out the problem is with the custom renderer I use for the page. The custom renderer resizes the page when the keyboard appears so that it does not cover my editor field.

public class KeyboardPageRenderer : PageRenderer
{
    private bool keyboardShowing;
    private NSObject keyboardWillShow;
    private NSObject keyboardWillHide;
    private double duration;
    private UIViewAnimationCurve curve;

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        this.keyboardWillShow = UIKeyboard.Notifications.ObserveWillShow(this.KeyboardWillShow);
        this.keyboardWillHide = UIKeyboard.Notifications.ObserveWillHide(this.KeyboardWillHide);
    }

    public override void ViewDidDisappear(bool animated)
    {
        base.ViewDidDisappear(animated);

        this.keyboardWillShow.Dispose();
        this.keyboardWillHide.Dispose();
    }

    private void KeyboardWillShow(object sender, UIKeyboardEventArgs args)
    {
        if (!this.keyboardShowing)
        {
            this.keyboardShowing = true;

            var keyboardFrame = UIKeyboard.FrameBeginFromNotification(args.Notification);

            this.duration = args.AnimationDuration;
            this.curve = args.AnimationCurve;

            this.ScrollTheView(true, keyboardFrame.Height);
        }
    }

    private void KeyboardWillHide(object sender, UIKeyboardEventArgs args)
    {
        if (this.keyboardShowing)
        {
            this.keyboardShowing = false;

            var keyboardFrame = UIKeyboard.FrameBeginFromNotification(args.Notification);

            this.duration = args.AnimationDuration;
            this.curve = args.AnimationCurve;

            this.ScrollTheView(false, keyboardFrame.Height);
        }
    }

    private void ScrollTheView(bool scale, nfloat scrollAmount)
    {
        UIView.BeginAnimations(string.Empty, IntPtr.Zero);
        UIView.SetAnimationDuration(this.duration);
        UIView.SetAnimationCurve(this.curve);

        var frame = View.Frame;

        // Assumes the page belongs to a tabbed view. 
        // This does not scale to pages that do not have one.
        UITabBarController tabBarController = new UITabBarController();
        nfloat tabHeight = tabBarController.TabBar.Frame.Size.Height;

        scrollAmount -= tabHeight;

        if (scale)
        {
            frame.Y -= scrollAmount;
        }
        else
        {
            frame.Y += scrollAmount;
        }

        View.Frame = frame;
        UIView.CommitAnimations();
    }
}

推荐答案

您的方法有两个问题

  • Task.Delay(10)之后,您不再处于UI线程上,这意味着您必须使用Device.BeginInvokeOnMainThread才能访问UI元素.
  • 呼叫EndEditing 之前,必须先清除
  • Control.ShouldEndEditing
  • After Task.Delay(10), you are not on the UI thread anymore, which means you have to use Device.BeginInvokeOnMainThread in order to access UI elements.
  • Control.ShouldEndEditing must be cleared before you call EndEditing

有效的解决方案如下:

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    base.OnElementPropertyChanged(sender, e);

    if (Element == null || Control == null)
        return;

    VisualElement element = Element as VisualElement;
    if (element == null)
        return;

    if (e.PropertyName == VisualElement.IsFocusedProperty.PropertyName && element.IsFocused == false)
    {
        Control.ShouldEndEditing = (UITextView control) =>
        {
            Device.BeginInvokeOnMainThread(() =>
            {
                control.ShouldEndEditing = null;
                control.EndEditing(true);
            });

            // prevent the keyboard from closing
            return false;
        };
    }
}

这篇关于Xamarin键盘打开时的按钮命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆