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?
EDIT: 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();
}
}
EditorText
). – Damian