打开键盘的Xamarin按钮命令

时间:2017-06-27 23:31:50

标签: xamarin.ios keyboard xamarin.forms

我正在开发专门针对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();
    }
}

1 个答案:

答案 0 :(得分:0)

您的方法有两个问题

  • Task.Delay(10)之后,您不再处于UI线程上,这意味着您必须使用Device.BeginInvokeOnMainThread才能访问UI元素。
  • Control.ShouldEndEditing必须先清除,然后再致电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;
        };
    }
}