【问题标题】:Xamarin Button Command with Keyboard Open键盘打开的 Xamarin 按钮命令
【发布时间】:2017-12-01 04:05:14
【问题描述】:

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

【问题讨论】:

  • Mike 当我在 iOS 上的测试项目中尝试 Xaml 时,没有自定义渲染器,我的命令被触发。这是在真实设备上。我点击编辑器,输入一些文本,然后点击按钮。键盘消失,命令触发(我从绑定的EditorText 记录文本)。
  • 你是对的。它解决了我的问题,即我的内容页面实际上也使用了自定义渲染器。自定义渲染器用于在键盘显示或键盘与编辑器重叠时调整页面大小,因为它位于底部。我会将该自定义渲染器添加到我的问题中。

标签: xamarin.ios keyboard xamarin.forms


【解决方案1】:

你的方法有两个问题

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 2015-09-13
    • 2020-06-19
    • 2016-12-13
    • 2019-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多