Как заставить представление Xamarin.Forms.iOS прокручиваться до записи, которая находится в фокусе?

У меня есть страница входа с 3 элементами управления вводом под большим логотипом изображения и элементом управления «Кнопка» в нижней части страницы, когда я нажимаю на верхний элемент управления вводом, чтобы сфокусировать ввод, чтобы начать печатать, появляется клавиатура и закрывает Элементы управления входом ниже и кнопка «Войти», которая не является лучшим пользовательским интерфейсом.

Пользователь может прокручивать вверх только вручную на Xamarin.Forms.iOS, но с помощью того же кода, ScrollToAsync, на Android. (EntryControl, ScrollToPosition.Start, правда);"

В Android кнопка в нижней части страницы также перемещается вверх с помощью символа * в определении строки сетки для пустого места посередине.

Похоже, Xamarin.Forms.iOS ведет себя совершенно иначе, чем Xamarin.Forms.Android при рендеринге. Я видел, что у ScrollToAsync есть некоторые проблемы с iOS при загрузке страницы из-за того, что ScrollView не существует до полной загрузки страницы. Но это действие происходит на странице, которая уже полностью отрендерилась. Что я делаю не так?

Я пробовал задержку, как указано в этом SO, но это не помогает. ScrollToAsync не работает в Xamarin.Forms

XAML

<Grid>
    <ScrollView VerticalOptions="FillAndExpand"
                BackgroundColor="White"
                x:Name="ScrollViewContainer"
                >
        <Grid Margin="15, 0, 15, 10">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" /><!--Logo-->
                <RowDefinition Height="Auto" /><!--Entry1-->
                <RowDefinition Height="Auto" /><!--Entry2-->
                <RowDefinition Height="Auto" /><!--Entry3-->                    
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" /><!--Button-->
                <RowDefinition Height="20" /><!--Empty padding-->
            </Grid.RowDefinitions>
            <Image Grid.Row="0"                
                   Aspect="AspectFit"
                   Source="CompanyLogo"
                   HorizontalOptions="Start"
                   HeightRequest="300"
                   VerticalOptions="Start"
                   Margin="10, 20, 20, 0"
                   />
             <Entry Grid.Row="1"
                    x:Name="BranchName"
                    Placeholder="BranchName" 
                    Focused="BranchName_Focused"
                    />   
             <Entry Grid.Row="2"
                    x:Name="Username"
                    Placeholder="e.g. Batman "
                    Focused="Username_Focused"
                    />  
             <Entry Grid.Row="3"
                    x:Name="Password"
                    Placeholder="Enter your password"
                    Focused="Password_Focused"
                    IsPassword="True"
                    />              
             <Button Grid.Row="5"
                     x:Name="LoginButton"
                     Text="Log in"
                     />
        </Grid>
    </ScrollView>
</Grid>

Код позади

    private async void BranchName_Focused(object sender, FocusEventArgs e)
    {
        await ScrollViewContainer.ScrollToAsync(BranchName, ScrollToPosition.Start, true);
    }

person CookieMonster    schedule 09.10.2019    source источник


Ответы (3)


Решение частично было найдено в ответе @numan98 выше, который заставил меня еще раз взглянуть на документы Microsoft, https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.scrollview.scrolltoasync?view=xamarin-forms

В нем указано, что ScrollToAsync(double X, double Y, bool animate) будет конечными значениями двойной позиции, где должны быть X и Y.

Таким образом, X никуда не перемещается, поэтому я считаю, что он должен быть равен 0, а Y я просто дал произвольное число, например 250. Думаю, где-то близко к вершине.

После этого у нас снова возникает эта ошибка iOS, когда вам нужно установить задержку.

Окончательный код выглядит примерно так.

private async void BranchName_Focused(object sender, FocusEventArgs e)
{
    Device.StartTimer(TimeSpan.FromSeconds(0.25), () =>
    {
        scroll.ScrollToAsync(0, 250, true);
        return false;
    );
}

Я надеюсь, что это помогает кому-то. Следующее, что нужно сделать, это заставить кнопку призыва к действию двигаться и всегда быть на виду.

person CookieMonster    schedule 11.10.2019

Добавьте это в свой файл xaml.cs

 protected override void OnAppearing()
    {
        base.OnAppearing();
        userName.Focused += InputFocused;
        password.Focused += InputFocused;
        userName.Unfocused += InputUnfocused;
        password.Unfocused += InputUnfocused;
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        userName.Focused -= InputFocused;
        password.Focused -= InputFocused;
        userName.Unfocused -= InputUnfocused;
        password.Unfocused -= InputUnfocused;
    }
    void InputFocused(object sender, EventArgs args)
    {
        Content.LayoutTo(new Rectangle(0, -270, Content.Bounds.Width, Content.Bounds.Height));
    }

    void InputUnfocused(object sender, EventArgs args)
    {
        Content.LayoutTo(new Rectangle(0, 0, Content.Bounds.Width, Content.Bounds.Height));
    }
person Anand    schedule 09.10.2019
comment
Привет, спасибо за ваш ответ, я только что попробовал это, и это не сработало. Может быть, я что-то упускаю. Из документов Microsoft . microsoft.com/en-us/dotnet/api/ и этот xfcomplete.net/xamarin.forms/2016/01/14/ можете объяснить, как LayoutTo может помочь в решении проблемы? Спасибо - person CookieMonster; 10.10.2019
comment
Привет, вы можете сослаться на эту ссылку «формы xamarin перемещают представление вверх в соответствии с высотой клавиатуры»> stackoverflow.com/questions/39641429/ - person Anand; 10.10.2019
comment
Не помогло, спасибо. На самом деле мне нужен точно такой же эффект, и плагин в вашей ссылке SO тоже не работает для меня. Я нашел другое решение - person CookieMonster; 11.10.2019
comment
@CookieMonster Окей, счастливого программирования, братан. +1 от меня - person Anand; 11.10.2019

Я думаю, вам стоит попробовать это...

private async void BranchName_Focused(object sender, FocusEventArgs e)
{
   await ScrollViewContainer.ScrollToAsync(BranchName.Bounds.X, BranchName.Bounds.Y, true);
}
person numan98    schedule 10.10.2019
comment
Да, читая документы MS, я понимаю, что есть два способа перегрузить этот метод. docs.microsoft.com/ en-us/dotnet/api/ - person CookieMonster; 11.10.2019