如何使 Xamarin.Forms.iOS 视图滚动到焦点所在的条目?
How do I make Xamarin.Forms.iOS View scroll to the Entry that is in focus?
我有一个登录页面,在大图像徽标下有 3 个 Entry 控件,在页面底部有一个 Button 控件,当我单击顶部的 Entry 控件以使 Entry 成为焦点以开始输入时,键盘出现并遮盖下面的输入控件和登录按钮,这不是最佳用户体验。
用户只能在 Xamarin.Forms.iOS 上手动向上滚动,但在 Android 上使用相同的代码 ScrollToAsync 我已经能够通过抓取使焦点上的条目滚动到页面顶部父 ScrollView 并做 "ScrollView.ScrollToAsync(EntryControl, ScrollToPosition.Start, true);"
在 Android 上,页面底部的按钮也通过在中间空 space 的 Grid Row 定义中使用 * 向上移动。
渲染时 Xamarin.Forms.iOS 的行为似乎与 Xamarin.Forms.Android 完全不同。我已经看到 ScrollToAsync 在页面加载 iOS 上有一些问题,因为 ScrollView 在页面完全加载之前不存在。但是这个动作是在一个已经完全呈现的页面上进行的。我做错了什么?
我已经尝试过此 SO 中提到的延迟,但它没有帮助。
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);
}
将此添加到您的 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));
}
我想你应该试试这个...
private async void BranchName_Focused(object sender, FocusEventArgs e)
{
await ScrollViewContainer.ScrollToAsync(BranchName.Bounds.X, BranchName.Bounds.Y, true);
}
解决方案部分来自@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 按钮移动并始终在视图中。
我有一个登录页面,在大图像徽标下有 3 个 Entry 控件,在页面底部有一个 Button 控件,当我单击顶部的 Entry 控件以使 Entry 成为焦点以开始输入时,键盘出现并遮盖下面的输入控件和登录按钮,这不是最佳用户体验。
用户只能在 Xamarin.Forms.iOS 上手动向上滚动,但在 Android 上使用相同的代码 ScrollToAsync 我已经能够通过抓取使焦点上的条目滚动到页面顶部父 ScrollView 并做 "ScrollView.ScrollToAsync(EntryControl, ScrollToPosition.Start, true);"
在 Android 上,页面底部的按钮也通过在中间空 space 的 Grid Row 定义中使用 * 向上移动。
渲染时 Xamarin.Forms.iOS 的行为似乎与 Xamarin.Forms.Android 完全不同。我已经看到 ScrollToAsync 在页面加载 iOS 上有一些问题,因为 ScrollView 在页面完全加载之前不存在。但是这个动作是在一个已经完全呈现的页面上进行的。我做错了什么?
我已经尝试过此 SO 中提到的延迟,但它没有帮助。
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);
}
将此添加到您的 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));
}
我想你应该试试这个...
private async void BranchName_Focused(object sender, FocusEventArgs e)
{
await ScrollViewContainer.ScrollToAsync(BranchName.Bounds.X, BranchName.Bounds.Y, true);
}
解决方案部分来自@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 按钮移动并始终在视图中。