Hi Team,
In iOS platform, we have noticed a weird behavior while scrolling the list items when keyboard layout on the View. We have tried to load a ScrollView with several child elements including ListView. We have Entry element inside the ItemTemplate of ListView. While focusing the Entry element, the On screen keyboard comes into the View and pushes the content upwards. This creates a blank space between keyboard and ListView. Sometimes it doesn't actually push the View above the keyboard. At that time while we scroll the list upwards with keyboard enabled, we have noticed the space again. We have attached the issue replicating sample along with the Video cast to showcase this issue.
ScrollView height should be calculated properly when keyboard layout in the View.
When keyboard layout in the View, there is a blank space between ListView and Keyboard when scrolled to the end.
Hi Team,
Can anyone please let me know the progress of this issue fix?
Thanks.
Hi Team,
Any update on this?
Hi, this issue affects layout on our apps on iPhone X, and other shiny-iPhone-with-notch like XR, XS, XS Max. It breaks what design and UX team does.
Hi,
Any update? I have the same issue. I tried it also on the Xamarin.Forms 3.6.0.539721 and 4.2.0.608146-pre1. And I had the same issue.
I found one solution. This is temporary solution, I'm still waiting fixes in the framework :-)
I didn't use ScrollView control, I used just ListView with his own scroll, because two scrolls work incorrect.
I used custom KeyboardRender from here with some fixes. You should add this class in the IOS project:
[assembly: ExportRenderer(typeof(Page), typeof(KeyboardRender))]
namespace MyApp.iOS.Renderers
{
[Preserve(AllMembers = true)]
public class KeyboardRender : PageRenderer
{
NSObject _keyboardShowObserver;
NSObject _keyboardHideObserver;
private bool _pageWasShiftedUp;
private double _activeViewBottom;
private bool _isKeyboardShown;
private double _viewHeight;
public KeyboardRender() { }
public new static void Init()
{
var now = DateTime.Now;
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var page = Element as ContentPage;
if (page != null)
{
var contentScrollView = page.Content as ScrollView;
if (contentScrollView != null)
return;
RegisterForKeyboardNotifications();
}
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
UnregisterForKeyboardNotifications();
}
void RegisterForKeyboardNotifications()
{
if (_keyboardShowObserver == null)
_keyboardShowObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, OnKeyboardShow);
if (_keyboardHideObserver == null)
_keyboardHideObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillHideNotification, OnKeyboardHide);
}
void UnregisterForKeyboardNotifications()
{
_isKeyboardShown = false;
if (_keyboardShowObserver != null)
{
NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardShowObserver);
_keyboardShowObserver.Dispose();
_keyboardShowObserver = null;
}
if (_keyboardHideObserver != null)
{
NSNotificationCenter.DefaultCenter.RemoveObserver(_keyboardHideObserver);
_keyboardHideObserver.Dispose();
_keyboardHideObserver = null;
}
}
protected virtual void OnKeyboardShow(NSNotification notification)
{
if (!IsViewLoaded || _isKeyboardShown)
return;
_isKeyboardShown = true;
var activeView = View.FindFirstResponder();
if (activeView == null)
return;
var keyboardFrame = UIKeyboard.FrameEndFromNotification(notification);
var isOverlapping = activeView.IsKeyboardOverlapping(View, keyboardFrame);
if (!isOverlapping)
return;
if (isOverlapping)
{
_activeViewBottom = activeView.GetViewRelativeBottom(View);
ShiftPageUp(keyboardFrame.Height, _activeViewBottom);
}
}
private void OnKeyboardHide(NSNotification notification)
{
if (!IsViewLoaded)
return;
_isKeyboardShown = false;
var keyboardFrame = UIKeyboard.FrameEndFromNotification(notification);
if (_pageWasShiftedUp)
{
ShiftPageDown(keyboardFrame.Height, _activeViewBottom);
}
}
private void ShiftPageUp(nfloat keyboardHeight, double activeViewBottom)
{
var pageFrame = Element.Bounds;
_viewHeight = pageFrame.Height;
var newHeight = pageFrame.Height + CalculateShiftByAmount(pageFrame.Height, keyboardHeight, activeViewBottom);
Element.LayoutTo(new Rectangle(pageFrame.X, pageFrame.Y,
pageFrame.Width, newHeight));
_pageWasShiftedUp = true;
}
private void ShiftPageDown(nfloat keyboardHeight, double activeViewBottom)
{
var pageFrame = Element.Bounds;
var newHeight = activeViewBottom;
Element.LayoutTo(new Rectangle(pageFrame.X, pageFrame.Y,
pageFrame.Width, _viewHeight));
_pageWasShiftedUp = false;
}
private double CalculateShiftByAmount(double pageHeight, nfloat keyboardHeight, double activeViewBottom)
{
return (pageHeight - activeViewBottom) - keyboardHeight;
}
}
public static class ViewExtensions
{
public static UIView FindFirstResponder(this UIView view)
{
if (view.IsFirstResponder)
{
return view;
}
foreach (UIView subView in view.Subviews)
{
var firstResponder = subView.FindFirstResponder();
if (firstResponder != null)
return firstResponder;
}
return null;
}
public static double GetViewRelativeBottom(this UIView view, UIView rootView)
{
var viewRelativeCoordinates = rootView.ConvertPointFromView(view.Frame.Location, view);
var activeViewRoundedY = Math.Round(viewRelativeCoordinates.Y, 2);
return activeViewRoundedY + view.Frame.Height;
}
public static bool IsKeyboardOverlapping(this UIView activeView, UIView rootView, CGRect keyboardFrame)
{
var activeViewBottom = activeView.GetViewRelativeBottom(rootView);
var pageHeight = rootView.Frame.Height;
var keyboardHeight = keyboardFrame.Height;
var isOverlapping = activeViewBottom >= (pageHeight - keyboardHeight);
return isOverlapping;
}
}
}
This issue doesn't seem to have had any activity in a long time. We're working on prioritizing issues and resolving them as quickly as we can. To help us get through the list, we would appreciate an update from you to let us know if this is still affecting you on the latest version of Xamarin.Forms, since it's possible that we may have resolved this as part of another related or duplicate issue. If we don't see any new activity on this issue in the next 30 days, we'll evaluate whether this issue should be closed. Thank you!
Since we haven't heard from you in more than 30 days, we hope this issue is no longer affecting you. If it is, please reopen this issue and provide the requested information so that we can look into it further. Thank you!
Most helpful comment
Hi, this issue affects layout on our apps on iPhone X, and other shiny-iPhone-with-notch like XR, XS, XS Max. It breaks what design and UX team does.