Странное поведение модальной страницы при вводе текста и отключении клавиатуры вручную (.NET MAUI Android)

Я создаю приложение для мониторинга растительности, которое впервые разрабатываю в MAUI. В формах Xamarin я не столкнулся с этой проблемой. У меня есть форма ввода данных, как показано ниже:

Форма ввода данных

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

Однако, когда у меня есть запись ниже, где отображается клавиатура, и модальная страница перемещается вверх, чтобы показать запись, я получаю странную прыгающую анимацию страницы каждый раз, когда я набираю букву, и когда я вручную закрываю клавиатуру, она представление не обновляется, но представление остается там, куда оно было перемещено, как показано на рисунках ниже:

Запись внизу страницы

Клавиатура перемещает модальную страницу вверх

Модальная страница не перемещается вниз после закрытия клавиатуры.

Я попытался добавить обходной пакет NuGet под названием PureWeen.Maui.FixesAndWorkarounds. Это не сработало. Я попробовал расширения клавиатуры Maui Community Toolkit, но они не сработали. Я попытался добавить следующие строки в начало xaml этой страницы, но это не сработало:

      xmlns:android="clr-namespace:Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;assembly=Microsoft.Maui.Controls"
             android:Application.WindowSoftInputModeAdjust="Resize"

Мой xaml выглядит так:

      <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ElephantMonitoring.DistanceSampling.Views.DSRecordingAddEditView"
             xmlns:helpers ="clr-namespace:ElephantMonitoring.HelperClasses"
             xmlns:valueConverters = "clr-namespace:ElephantMonitoring.Value_Converters"
             Disappearing="ContentPage_Disappearing"
             xmlns:android="clr-namespace:Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;assembly=Microsoft.Maui.Controls"
             android:Application.WindowSoftInputModeAdjust="Resize">

    <!--VALUE CONVERTER: ERROR MESSAGE TO BOOL-->
    <ContentPage.Resources>
        <valueConverters:ErrorTextToBoolConverter x:Key="errorToBool"/>
        <valueConverters:GPSAccuracyIndicatorValueConverter x:Key="gpsAccuracy"/>
    </ContentPage.Resources>
    
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="60"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="10"/>
        </Grid.RowDefinitions>

        <!--HEADER-->
        <Frame Style="{StaticResource HeaderCard}" Grid.Row="0">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="60"/>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="60"/>
                </Grid.ColumnDefinitions>

                <Button Grid.Column="0" HeightRequest="50" WidthRequest="50" BackgroundColor="DarkGreen" Command="{Binding BackCommand}"
                        HorizontalOptions="Start">
                    <Button.ImageSource>
                        <FontImageSource Glyph="{x:Static helpers:FASolid.ArrowLeft}" FontFamily="FASolid" Size="30"/>
                    </Button.ImageSource>
                </Button>

                <Label Grid.Column="1" Text="{Binding Title, FallbackValue=PAGE_TITLE}" Style="{StaticResource HeaderLabel}"
                           HorizontalOptions="Center"/>

                <Button Grid.Column="2" HeightRequest="50" WidthRequest="50" BackgroundColor="DarkGreen" Command="{Binding AcceptCommand}"
                        HorizontalOptions="End">
                    <Button.ImageSource>
                        <FontImageSource Glyph="{x:Static helpers:FASolid.FloppyDisk}" FontFamily="FASolid" Size="30"/>
                    </Button.ImageSource>
                </Button>
            </Grid>
        </Frame>

        <!--DATA FIELDS-->
        <ScrollView Grid.Row="1" Margin="0,20,0,0">
            <VerticalStackLayout>
                <!--Perpendicuar distance - ENTRY-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Perpendicular distance from transect (*)" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.PerpendicularDistanceError, FallbackValue=False, Converter={StaticResource errorToBool}}"
                           Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.PerpendicularDistanceError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Entry Style="{StaticResource EntryBase}" Text="{Binding RecordingModel.PerpendicularDistance}"
                               Keyboard="Numeric"/>
                    </VerticalStackLayout>
                </Frame>

                <!--Plant Location - GPS LOCATION GROUP-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Loading indicator that will be shown when the GPS is trying to get a location-->
                        <HorizontalStackLayout HorizontalOptions="Center" IsVisible="{Binding ShowGPSLoading}">
                            <ActivityIndicator Color="DarkGreen" IsRunning="True" IsVisible="True" HeightRequest="40"/>
                            <Label Text="Getting device location..." Style="{StaticResource InformationLabelHeader}"
                                   VerticalTextAlignment="Center"/>
                        </HorizontalStackLayout>
                        
                        <!--The fields-->
                        <Grid Margin="0,10,0,0">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*"/>
                                <ColumnDefinition Width="60"/>
                            </Grid.ColumnDefinitions>

                            <VerticalStackLayout Grid.Column="0">
                                <!--Start Location S - ENTRY-->
                                <VerticalStackLayout>
                                    <!--Caption-->
                                    <Label Text="Plant Location South (decimal degrees) (*)" Style="{StaticResource EntryCaptionLabel}"/>
                                    <!--Error Box-->
                                    <Frame IsVisible="{Binding RecordingModel.PlantLocationSError, FallbackValue=False, Converter={StaticResource errorToBool}}"
                           Style="{StaticResource ErrorCard}">
                                        <Label Text="{Binding RecordingModel.PlantLocationSError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                                    </Frame>

                                    <Entry Style="{StaticResource EntryBase}" Text="{Binding RecordingModel.PlantLocationS}"
                                           Keyboard="Numeric"/>
                                </VerticalStackLayout>

                                <!--End Location E - ENTRY-->
                                <VerticalStackLayout>
                                    <!--Caption-->
                                    <Label Text="Plant Location East (decimal degrees) (*)" Style="{StaticResource EntryCaptionLabel}"/>
                                    <!--Error Box-->
                                    <Frame IsVisible="{Binding RecordingModel.PlantLocationEError, FallbackValue=False, Converter={StaticResource errorToBool}}"
                           Style="{StaticResource ErrorCard}">
                                        <Label Text="{Binding RecordingModel.PlantLocationEError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                                    </Frame>

                                    <Entry Style="{StaticResource EntryBase}" Text="{Binding RecordingModel.PlantLocationE}" Keyboard="Numeric"/>
                                </VerticalStackLayout>

                                <!--Accuracy Indicator - LABEL-->
                                <HorizontalStackLayout>
                                    <!--Caption-->
                                    <Label Text="Accuracy: " Style="{StaticResource EntryCaptionLabel}"/>
                                    <Label Text="{Binding RecordingModel.LocationAccuracy, FallbackValue=NA}" Style="{StaticResource InformationLabelHeader}"/>
                                    <Label Text="m" Style="{StaticResource InformationLabelHeader}"/>
                                    <Label Text="{Binding RecordingModel.LocationAccuracy, FallbackValue=NONE, Converter={StaticResource gpsAccuracy}}" 
                                           Style="{StaticResource InformationLabelHeader}"/>
                                </HorizontalStackLayout>
                            </VerticalStackLayout>

                            <Button HeightRequest="50" WidthRequest="50" BackgroundColor="DarkGreen" Grid.Column="1" 
                        Command="{Binding GetGPSLocationCommand}"
                    Margin="0,0,5,0">
                                <Button.ImageSource>
                                    <FontImageSource Glyph="{x:Static helpers:FASolid.LocationDot}" FontFamily="FASolid" Size="30"/>
                                </Button.ImageSource>
                            </Button>

                        </Grid>
                    </VerticalStackLayout>
                </Frame>

                <!--Trunk Circumference - ENTRY-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Trunk circumference (m) (*)" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.TrunkCircumferenceError, FallbackValue=False, Converter={StaticResource errorToBool}}"
                           Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.TrunkCircumferenceError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Entry Style="{StaticResource EntryBase}" Text="{Binding RecordingModel.TrunkCircumference}"
                               Keyboard="Numeric"/>
                    </VerticalStackLayout>
                </Frame>

                <!--Damaged trunk circumference - ENTRY-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Damaged trunk circumference (m) (*)" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.DamagedTrunkCircError, FallbackValue=False, Converter={StaticResource errorToBool}}"
                           Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.DamagedTrunkCircError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Entry Style="{StaticResource EntryBase}" Text="{Binding RecordingModel.DamagedTrunkCirc}"
                               IsReadOnly="True">
                            <Entry.GestureRecognizers>
                                <TapGestureRecognizer Command="{Binding AddDamagedTrunkCommand}"/>
                            </Entry.GestureRecognizers>
                        </Entry>
                    </VerticalStackLayout>
                </Frame>

                <!--Plant height - ENTRY-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Plant Height (m) (*)" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.PlantHeightError, FallbackValue=False, Converter={StaticResource errorToBool}}"
                           Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.PlantHeightError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Entry Style="{StaticResource EntryBase}" Text="{Binding RecordingModel.PlantHeight}"
                               Keyboard="Numeric"/>
                    </VerticalStackLayout>
                </Frame>

                <!--Crown Diameter - ENTRY-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Crown Diameter (m) (*)" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.CrownDiameterError, FallbackValue=False, Converter={StaticResource errorToBool}}"
                           Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.CrownDiameterError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Entry Style="{StaticResource EntryBase}" Text="{Binding RecordingModel.CrownDiameter}"
                               IsReadOnly="True">
                            <Entry.GestureRecognizers>
                                <TapGestureRecognizer Command="{Binding AddCrownDiameterCommand}"/>
                            </Entry.GestureRecognizers>
                        </Entry>
                    </VerticalStackLayout>
                </Frame>

                <!--First Leaves height - ENTRY-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="First Leaves Height (m) (*)" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.FirstLeavesHeightError, FallbackValue=False, Converter={StaticResource errorToBool}}"
                           Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.FirstLeavesHeightError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Entry Style="{StaticResource EntryBase}" Text="{Binding RecordingModel.FirstLeavesHeight}"
                               Keyboard="Numeric"/>
                    </VerticalStackLayout>
                </Frame>

                <!--Toppled - PICKER-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Is the tree Toppled?" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.ToppledError, FallbackValue=False, Converter={StaticResource errorToBool}}" 
                               Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.ToppledError}" 
                                Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Picker 
                        SelectedItem="{Binding RecordingModel.Toppled}"
                        TitleColor="{StaticResource PrimaryMid}"
                        Style="{StaticResource PickerBase}"
                        BackgroundColor="White">
                            <Picker.Items>
                                <x:String>YES</x:String>
                                <x:String>NO</x:String>
                            </Picker.Items>
                        </Picker>
                    </VerticalStackLayout>
                </Frame>

                <!--Top Kill - PICKER-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Is Top Kill evident?" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.TopKillError, FallbackValue=False, Converter={StaticResource errorToBool}}" 
                               Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.TopKillError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Picker 
                        SelectedItem="{Binding RecordingModel.TopKill}"
                        TitleColor="{StaticResource PrimaryMid}"
                        Style="{StaticResource PickerBase}"
                        BackgroundColor="White">
                            <Picker.Items>
                                <x:String>YES</x:String>
                                <x:String>NO</x:String>
                            </Picker.Items>
                        </Picker>
                    </VerticalStackLayout>
                </Frame>
                
                <!--Coppiced - PICKER-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Is the tree Coppicing?" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.CoppicedError, FallbackValue=False, Converter={StaticResource errorToBool}}" 
                               Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.CoppicedError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Picker 
                        SelectedItem="{Binding RecordingModel.Coppiced}"
                        TitleColor="{StaticResource PrimaryMid}"
                        Style="{StaticResource PickerBase}"
                        BackgroundColor="White">
                            <Picker.Items>
                                <x:String>YES</x:String>
                                <x:String>NO</x:String>
                            </Picker.Items>
                        </Picker>
                    </VerticalStackLayout>
                </Frame>

                <!--Utilization Scale - PICKER-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Utilization on scale" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.UtilizationScaleError, FallbackValue=False, Converter={StaticResource errorToBool}}" 
                               Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.UtilizationScaleError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Picker 
                        SelectedItem="{Binding RecordingModel.UtilizationScale}"
                        TitleColor="{StaticResource PrimaryMid}"
                        Style="{StaticResource PickerBase}"
                        BackgroundColor="White">
                            <Picker.Items>
                                <x:String>1</x:String>
                                <x:String>2</x:String>
                                <x:String>3</x:String>
                                <x:String>4</x:String>
                            </Picker.Items>
                        </Picker>
                    </VerticalStackLayout>
                </Frame>

                <!--Fire Damaged - PICKER-->
                <Frame Padding="2" Margin="2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Fire damage evident?" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="{Binding RecordingModel.FireDamageError, FallbackValue=False, Converter={StaticResource errorToBool}}" 
                               Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding RecordingModel.FireDamageError}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Picker 
                        SelectedItem="{Binding RecordingModel.FireDamage}"
                        TitleColor="{StaticResource PrimaryMid}"
                        Style="{StaticResource PickerBase}"
                        BackgroundColor="White">
                            <Picker.Items>
                                <x:String>YES</x:String>
                                <x:String>NO</x:String>
                            </Picker.Items>
                        </Picker>
                    </VerticalStackLayout>
                </Frame>

                <!--Notes - ENTRY-->
                <Frame Padding="2" Margin="2, 2, 2, 2" BorderColor="Black">
                    <VerticalStackLayout>
                        <!--Caption-->
                        <Label Text="Notes" Style="{StaticResource EntryCaptionLabel}"/>
                        <!--Error Box-->
                        <Frame IsVisible="False"
                           Style="{StaticResource ErrorCard}">
                            <Label Text="{Binding SomeBinding}" 
                       Style="{StaticResource ErrorCardLabel}"/>
                        </Frame>

                        <Editor Style="{StaticResource EditorBase}" Text="{Binding PlantSpeciesItem.ScientificName}"
                                Placeholder="Enter notes here" x:Name="notesEditor" Focused="notesEditor_Focused"/>
                    </VerticalStackLayout>
                </Frame>

            </VerticalStackLayout>
        </ScrollView>

    </Grid>
</ContentPage>

Если кто-то нашел решение этой проблемы, пожалуйста, дайте мне знать.

0 ответов

Другие вопросы по тегам