用键盘打开的Xamarin按钮命令

3

我正在为iOS平台开发一个Xamarin.Forms项目。我有一个Editor控件和一个Button控件并排放置。当我聚焦在编辑器上,输入一些文本,然后单击按钮时,似乎命令没有被触发,而是键盘只是关闭了。然后我必须再次点击添加按钮才能触发命令。

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

我尝试创建一个自定义渲染器,可以在初始时阻止键盘关闭,并在延迟后关闭它。这允许命令被触发,但是我卡在了键盘一直打开的问题上。

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

我的理想解决方案是您能够输入文本,点击添加按钮,键盘同时关闭并执行命令。有任何想法如何实现这一点吗?
编辑:事实证明,问题出在我用于页面的自定义渲染器上。自定义渲染器会在键盘出现时调整页面大小,以便不覆盖我的编辑器字段。
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();
    }
}

当我在iOS上的测试项目中尝试Xaml时,没有使用自定义渲染器,我的命令被触发了。这是在真实设备上的情况。我点击编辑器,输入一些文本,然后点击按钮。键盘消失,命令被触发(我记录了绑定的EditorText中的文本)。Mike - Damian
1
你说得对。实际上,我的内容页面也使用了自定义渲染器,这解决了我的问题。当键盘显示时,自定义渲染器用于调整页面大小,否则编辑器会被键盘遮挡,因为它位于底部。我将把这个自定义渲染器添加到我的问题中。 - Mike Richards
1个回答

0

你的方法存在两个问题

  • Task.Delay(10)之后,你已经不在UI线程上了,这意味着你必须使用Device.BeginInvokeOnMainThread才能访问UI元素。
  • 在调用EndEditing之前,必须先清除Control.ShouldEndEditing

一个可行的解决方案如下:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接