.NET MAUI Android端ScrollView软键盘遮挡问题求助
.NET MAUI软键盘遮挡页面问题解决
问题描述
我开发了一个.NET MAUI页面,供用户输入速度与百分比,已设置输入框仅弹出数字软键盘,其余功能均正常,但ScrollView存在适配问题:当软键盘弹出时会遮挡页面,需手动关闭才能查看底部的Send按钮。请问如何开启软键盘滚动避让功能?若无法实现,是否有办法检测软键盘并调整页面尺寸?
XAML代码
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="DoradSmartphone.Views.AvatarPage" xmlns:model="clr-namespace:DoradSmartphone.Models" xmlns:viewmodel="clr-namespace:DoradSmartphone.ViewModels" xmlns:helpers="clr-namespace:DoradSmartphone.Helpers" x:DataType="viewmodel:AvatarViewModel" Title="{Binding Title}"> <ContentPage.Resources> <ResourceDictionary> <Style x:Key="EntryContainerStyle" TargetType="Entry"> <Setter Property="FontSize" Value="20" /> <Setter Property="HeightRequest" Value="48" /> </Style> </ResourceDictionary> </ContentPage.Resources> <ContentPage.Content> <ScrollView VerticalOptions="FillAndExpand"> <StackLayout x:Name="MainLayout" VerticalOptions="FillAndExpand"> <Grid VerticalOptions="Center" HorizontalOptions="Center" RowSpacing="15"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Image Source="{x:Static helpers:Icons.AvatarXg}" HeightRequest="300" WidthRequest="300" HorizontalOptions="Center" Grid.Row="0" /> <Label Text="The Route Speed was 17km/h" FontSize="20" TextColor="RoyalBlue" HorizontalTextAlignment="Center" Grid.Row="1" Margin="20"/> <Entry x:Name="Speed" Placeholder="Type the speed" Text="{Binding Speed}" Grid.Row="2" Style="{StaticResource EntryContainerStyle}" Keyboard="Numeric"> <Entry.Behaviors> <helpers:NumericValidationBehavior MaximumValue="30" /> </Entry.Behaviors> </Entry> <Entry x:Name="Percentage" Placeholder="Type the percentage of speed" Text="{Binding Percentage}" Grid.Row="3" Style="{StaticResource EntryContainerStyle}" Keyboard="Numeric"> <Entry.Behaviors> <helpers:NumericValidationBehavior MaximumValue="100" /> </Entry.Behaviors> </Entry> <Label Text="{Binding NewSpeed, StringFormat='The new speed is {0} km/h'}" FontSize="20" TextColor="RoyalBlue" HorizontalTextAlignment="Center" Grid.Row="4" Margin="20"/> <Button Text="Send" WidthRequest="100" CornerRadius="20" HorizontalOptions="Center" Command="{Binding SetAvatarCommand}" Grid.Row="5" Margin="10" FontSize="15"/> </Grid> </StackLayout> </ScrollView> </ContentPage.Content> </ContentPage>
ViewModel代码
public partial class AvatarViewModel : BaseViewModel, INotifyPropertyChanged { private double speed; private double routeSpeed; private double newSpeed; private double percentage; public event PropertyChangedEventHandler PropertyChanged; public double Speed { get { return speed; } set { if (speed != value) { speed = value; OnPropertyChanged(nameof(Speed)); UpdateNewSpeed(); } } } public double RouteSpeed { get { return routeSpeed; } set { if (routeSpeed != value) { routeSpeed = value; OnPropertyChanged(nameof(RouteSpeed)); UpdateNewSpeed(); } } } public double NewSpeed { get { return newSpeed; } set { if (newSpeed != value) { newSpeed = value; OnPropertyChanged(nameof(NewSpeed)); } } } public double Percentage { get { return percentage; } set { if (percentage != value) { percentage = value; OnPropertyChanged(nameof(Percentage)); UpdateNewSpeed(); } } } public AvatarViewModel() { Title = "AvatarPage"; RouteSpeed = 17; } private void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void UpdateNewSpeed() { if (percentage != 0 || percentage >= 0) { var calc = RouteSpeed + (RouteSpeed * (Percentage / 100)); NewSpeed = double.Round(calc, 2, MidpointRounding.AwayFromZero); } } public ICommand SetAvatarCommand => new Command(SetAvatar); private void SetAvatar() { // Perform any necessary actions when the button is clicked } }
解决方案
方式一:启用软键盘自动避让(推荐)
针对不同平台配置系统级软键盘避让:
Android平台
在Platforms/Android/MainActivity.cs中设置软键盘模式:protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); // AdjustResize:调整布局大小腾出键盘空间;AdjustPan:平移页面确保焦点控件可见 Window.SetSoftInputMode(Android.Views.SoftInput.AdjustResize); }iOS平台
iOS默认支持自动避让,若无效可检查:- 确认
ScrollView的VerticalOptions为FillAndExpand(你的代码已满足) - 在
Platforms/iOS/Info.plist中添加配置:<key>UIViewControllerBasedStatusBarAppearance</key> <true/>
- 确认
方式二:手动检测软键盘并调整布局
若自动避让失效,可通过监听软键盘事件手动调整:
在页面后台代码添加监听逻辑:
private IKeyboardService _keyboardService; public AvatarPage(IKeyboardService keyboardService) { InitializeComponent(); _keyboardService = keyboardService; } protected override void OnAppearing() { base.OnAppearing(); _keyboardService.KeyboardShown += OnKeyboardShown; _keyboardService.KeyboardHidden += OnKeyboardHidden; } protected override void OnDisappearing() { base.OnDisappearing(); _keyboardService.KeyboardShown -= OnKeyboardShown; _keyboardService.KeyboardHidden -= OnKeyboardHidden; } private void OnKeyboardShown(object sender, KeyboardEventArgs e) { // 给主布局添加底部边距,避开软键盘 MainLayout.Margin = new Thickness(0, 0, 0, e.KeyboardHeight); } private void OnKeyboardHidden(object sender, EventArgs e) { // 恢复原边距 MainLayout.Margin = Thickness.Zero; }实现跨平台键盘服务(以Android为例):
创建Platforms/Android/KeyboardService.cs:public class KeyboardService : IKeyboardService { public event EventHandler<KeyboardEventArgs> KeyboardShown; public event EventHandler KeyboardHidden; public void Initialize() { var activity = Platform.CurrentActivity; var decorView = activity.Window.DecorView; decorView.ViewTreeObserver.GlobalLayout += (s, args) => { Rect r = new Rect(); decorView.GetWindowVisibleDisplayFrame(r); var screenHeight = decorView.RootView.Height; var keypadHeight = screenHeight - r.Bottom; // 判定软键盘是否显示(高度超过屏幕15%) if (keypadHeight > screenHeight * 0.15) { KeyboardShown?.Invoke(this, new KeyboardEventArgs { KeyboardHeight = keypadHeight }); } else { KeyboardHidden?.Invoke(this, EventArgs.Empty); } }; } } public interface IKeyboardService { event EventHandler<KeyboardEventArgs> KeyboardShown; event EventHandler KeyboardHidden; void Initialize(); } public class KeyboardEventArgs : EventArgs { public int KeyboardHeight { get; set; } }在
MauiProgram.cs注册服务:builder.Services.AddSingleton<IKeyboardService, KeyboardService>();在App启动时初始化服务:
public App(IKeyboardService keyboardService) { InitializeComponent(); keyboardService.Initialize(); MainPage = new AppShell(); }
额外优化建议
- 避免给布局设置固定
HeightRequest,优先使用Auto或FillAndExpand实现自适应 - 确保
ScrollView直接作为ContentPage.Content的子元素(你的代码已满足)
内容的提问来源于stack exchange,提问作者Luiz Carlos
相关产品推荐
相关产品推荐

