xamarin / Xamarin.Forms

Xamarin.Forms is no longer supported. Migrate your apps to .NET MAUI.
https://aka.ms/xamarin-upgrade
Other
5.64k stars 1.88k forks source link

[Bug] [iOS] Entry Control Inside ScrollView is Hidden Behind Keyboard while focusing in Xamarin.Forms #15826

Open anandhan-rajagopal opened 8 months ago

anandhan-rajagopal commented 8 months ago

Description

When using Xamarin.Forms on the iOS platform, we have encountered a critical issue where an Entry control, placed inside a ScrollView, is hidden behind the keyboard when focused on text input. This issue makes it challenging for users to interact with the Entry control and enter data, impacting the overall user experience.

Steps to Reproduce

  1. Run the attached issue reproducing sample in Xamarin.Forms iOS platform

  2. Tap to Focus the entry control

Expected Behavior

Entry control should placed above the keyboard

Actual Behavior

Entry control placed behind the keyboard

Basic Information

Build Logs

NA

Screenshots

https://github.com/xamarin/Xamarin.Forms/assets/97146406/fe38ae58-8d2c-4fcf-aa6e-4f42a86844d7

Reproduction Link

https://github.com/anandhan-rajagopal/EntrySample

Workaround

NA

Domik234 commented 8 months ago

Hello, reproduction project contains nested scrollviews.

  1. There is warning @ https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/layouts/scrollview that says not to use nested scrollviews or any scroll-containing view inside of scrollview.
  2. It really matters what you want to achieve here. I believe there may be an layout alternative.
  3. Scrollview can be extended as much as it's needed and inside of root scrollview is StackLayout with VerticalOptions set to "end" (Where is end of scrollview?) that contains one additional scrollview.

If you want to have an entry on the end of page and use it for value entry then this will work:

    <ScrollView>
        <Grid ColumnDefinitions="*" RowDefinitions="*, auto">
            <StackLayout>
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
                <Label Text="Not enough long text to provide that thing you want to achieve!" />
            </StackLayout>
            <Entry Grid.Row="1" Placeholder="Entry" />
            <!-- Some bottom margin?-->
        </Grid>
    </ScrollView>

There is also possibility to add bottom margin to entry using effect for example like this to push entry from bottom to visible part:

public class MoveWithKeyboardiOSEffectPlatform : PlatformEffect
    {
        Thickness OrigMargin;
        protected override void OnAttached()
        {
            if (Element != null)
            {
                OrigMargin = (Element as View).Margin;
            }

            UIKeyboard.Notifications.ObserveWillShow((sender, args) =>
            {
                if (Element != null)
                {
                    (Element as View).Margin = new Thickness(OrigMargin.Left, OrigMargin.Top, OrigMargin.Right, OrigMargin.Bottom + args.FrameEnd.Height); //push the entry up to keyboard height when keyboard is activated
                }
            });

            UIKeyboard.Notifications.ObserveWillHide((sender, args) =>
            {
                if (Element != null)
                {
                    (Element as View).Margin = OrigMargin; //set the margins to zero when keyboard is dismissed
                }
            });
        }

        protected override void OnDetached()
        {
        }
    }