【问题标题】:How do I make Xamarin.Forms.iOS View scroll to the Entry that is in focus?如何使 Xamarin.Forms.iOS 视图滚动到焦点所在的条目?
【发布时间】:2020-02-06 16:22:43
【问题描述】:

我有一个登录页面,在一个大图像徽标下有 3 个 Entry 控件,页面底部有一个 Button 控件,当我单击顶部的 Entry 控件以使 Entry 成为焦点以开始输入时,键盘出现并掩盖了下面的 Entry 控件和 Login 按钮,这不是最好的用户体验。

用户只能在 Xamarin.Forms.iOS 上手动向上滚动,但在 Android 上使用相同的代码 ScrollToAsync 我已经能够通过抓取父 ScrollView 并执行“使焦点上的条目滚动到页面顶部” ScrollView.ScrollToAsync(EntryControl, ScrollToPosition.Start, true);"

在 Android 上,页面底部的按钮也会通过在中间空白区域的 Grid Row 定义中使用 * 来向上移动。

在呈现时,Xamarin.Forms.iOS 的行为似乎与 Xamarin.Forms.Android 完全不同。我已经看到 ScrollToAsync 在页面加载时在 iOS 上存在一些问题,因为 ScrollView 在页面完全加载之前不存在。但是这个动作是在已经完全呈现的页面上进行的。我做错了什么?

我已经尝试过这个 SO 中提到的延迟,但它没有帮助。 ScrollToAsync is not working in 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);
    }

【问题讨论】:

    标签: c# xamarin.forms xamarin.forms.entry xamarin-forms-4


    【解决方案1】:

    解决方案部分来自上面的@numan98 答案,这让我重新审视了微软文档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;
        );
    }
    

    我希望这对某人有所帮助。接下来的事情是让 CTA 按钮移动并始终显示在视图中。

    【讨论】:

      【解决方案2】:

      将此添加到您的 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));
          }
      

      【讨论】:

      【解决方案3】:

      我觉得你应该试试这个……

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

      【讨论】:

      猜你喜欢
      • 2017-05-12
      • 2012-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-10
      • 1970-01-01
      • 2019-11-07
      • 2017-12-29
      相关资源
      最近更新 更多