paulpatarinski / Xamarin.Forms.Plugins

Xamarin Forms Plugins
http://paulpatarinski.github.io/Xamarin.Forms.Plugins
MIT License
276 stars 141 forks source link

Screen scrolls down below position after selecting item in Picker. #162

Open noelfernandes opened 6 years ago

noelfernandes commented 6 years ago

Hi I'm using the KeyOverlap plugin in my XF .NET Standard project. As mentioned in the documentation, I have deployed the plugin only in the iOS project.

I have a login page consisting of input fields, namely: 'Username', 'Password', a Picker for 'Location' and a Login button. Everything works well when I tap on the Entry's. The screen scrolls up and then back to position when I tap anywhere outside of the Entrys. However, when I tap the Picker, select an item and then tap 'Done', the screen scrolls below position i.e. the login button gets hidden. The screenshots below should give you an idea.

keyoverlap

Any ideas on how to resolve this?

zanesc commented 5 years ago

You can fix this by modifying ShiftPageDown in the KeyboardOverlapRenderer like this:

void ShiftPageDown(nfloat keyboardHeight, double activeViewBottom)
{
    var pageFrame = Element.Bounds;
    Element.LayoutTo(new Rectangle(pageFrame.X, 0, pageFrame.Width, pageFrame.Height));
    _pageWasShiftedUp = false;
}

The calculated newY coordinate seems to be what caused this.

zanesc commented 5 years ago

Just found a better alternative. The newY issue seems to be as a result of a bug with the _isKeyboardShown bool property. If you remove this bool you can leave the newY coordinate as it should be. This also fixes the issue where the keyboard may hide the entry on the first attempt.

Here is a commit that details the steps: https://github.com/paulpatarinski/Xamarin.Forms.Plugins/pull/148/commits/d586d01562b23bee34a568cc81aa5f9b3a3f9f45

To note: There still seems to be shifting issues with custom keyboards, stock keyboard works fine.

shalomthegreat commented 5 years ago

Hey guys. I had no idea how to implement Zanesc's solution, so I was thinking about just disabling the whole plugin when I noticed there was one page in my app that didn't have the problem. All I had to do was narrow down why one page worked, and the other didn't.

So a few hours of beating my head against the wall and I found the offending bit. It makes NO SENSE to me, so I created an account to post the solution here for you, maybe someone else can explain.

The offending code:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:locale="clr-namespace:DuplimarkApp.Locales"
             xmlns:iOSSpecific="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
             x:Class="DuplimarkApp.Views.Contacts.NewContact" 
             xmlns:views="clr-namespace:DuplimarkApp.Views" 
             BackgroundColor="#E9EAEE">
    <ContentPage.Content>
        <StackLayout HorizontalOptions="FillAndExpand">
            <ContentView>
                <views:TopNav x:Name="NavBar">
                </views:TopNav>
            </ContentView>
            <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand">
                <Label x:Name="lblTitle" Text="{locale:Translate Text=PointClass5}" Margin="10,10,10,5" />
                <StackLayout Orientation="Horizontal" HorizontalOptions="EndAndExpand">
                    <Button x:Name="btnCancel" Text="{locale:Translate Text=Cancel}" TextColor="#4A90E2" HeightRequest="20" BackgroundColor="Transparent" Clicked="btnCancel_Clicked" Margin="0,0,15,0" />
                </StackLayout>
            </StackLayout>
            <Frame CornerRadius="5" HasShadow="False" VerticalOptions="Start" Margin="10,0" Padding="20">                    
                <StackLayout BackgroundColor="White" VerticalOptions="Center">
                    <Image x:Name="imgContact" Margin="0,0,0,10">
                        <Image.Source>
                            <OnPlatform x:TypeArguments="ImageSource" iOS="Contacts/Info/Photo.png" Android="contacts_info_photo.png" />
                        </Image.Source>
                    </Image>
                    <Entry x:Name="entFirstname" Placeholder="{locale:Translate Text=FirstName}" ReturnType="Next" />
                    <Entry x:Name="entLastname" Placeholder="{locale:Translate Text=LastName}" ReturnType="Next" />
                    <Entry x:Name="entPhone" Placeholder="{locale:Translate Text=MobileNumber}" ReturnType="Next" />
                    <Entry x:Name="entEmail" Placeholder="{locale:Translate Text=EmailAddress}" ReturnType="Next" />
                    <!--<Button HorizontalOptions="FillAndExpand" BackgroundColor="Transparent" TextColor="#4A90E2" Text="More" IsEnabled="False" />-->
                    <Label Text="{locale:Translate Text=Notes}" FontSize="Small" Margin="0,10,0,0" />
                    <Frame CornerRadius="5" HasShadow="False" BorderColor="Silver" Padding="0" VerticalOptions="FillAndExpand" HeightRequest="80">
                        <Editor x:Name="entNotes" VerticalOptions="FillAndExpand" />
                    </Frame>
                    <StackLayout x:Name="pnlOptions" IsVisible="false">
                    <Frame CornerRadius="0" HasShadow="False" BorderColor="Silver" Padding="0" Margin="0,20,0,0">
                        <Picker x:Name="pkStatus" Title="{locale:Translate Text=SelectStatus}" ItemDisplayBinding="{Binding Title}" ItemsSource="{Binding ContactStatuses}" iOSSpecific:Picker.UpdateMode="WhenFinished">
                            <Picker.HeightRequest><OnPlatform iOS="30" Android="40" /></Picker.HeightRequest>
                        </Picker>
                    </Frame>
                    <Frame CornerRadius="0" HasShadow="False" BorderColor="Silver" Padding="0">
                        <Picker x:Name="pkGroup" Title="{locale:Translate Text=SelectGroup}" ItemDisplayBinding="{Binding Title}" ItemsSource="{Binding UserGroups}"  iOSSpecific:Picker.UpdateMode="WhenFinished">
                            <Picker.HeightRequest><OnPlatform iOS="30" Android="40" /></Picker.HeightRequest>
                        </Picker>
                    </Frame>
                    </StackLayout>
                    <Button x:Name="btnDone"
                            HorizontalOptions="FillAndExpand"
                            Margin="0,20,0,0"
                            BackgroundColor="#4A90E2"
                            BorderRadius="5"
                            TextColor="White"
                            Text="{locale:Translate Text=Save}"
                            Clicked="btnDone_Clicked" />
                </StackLayout>                    
            </Frame>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

The solution: Change the VerticalOptions on the frame at line 21 from VerticalOptions="Start" to VerticalOptions="FillAndExpand"... O-O I guess it just comes to down to: check your XAML. I had another page where putting everything in a scrollview was a problem as well, even with the 'fix'.

GOSTWorker commented 4 years ago

I guess it is because after selecting a new value, the UI is completely reloaded. If ShiftPageDown is then executed, the page moves down. I solved the problem for me in the following way:

    private void OnKeyboardHide(NSNotification notification)
    {
        if (!IsViewLoaded)
            return;

        _isKeyboardShown = false;
        var keyboardFrame = UIKeyboard.FrameEndFromNotification(notification);

        if (_pageWasShiftedUp && Element.Y != 0)
        {
            ShiftPageDown(keyboardFrame.Height, _activeViewBottom);
        }

        _activeViewBottom = 0; //me
    }

if Element.Y = 0 then the page has already been reloaded and the shift does not need to be executed again.