Xamarin Forms布局不适用于较小的屏幕

时间:2020-08-17 18:51:38

标签: android visual-studio xamarin xamarin.forms

我已经得到了一个现有的Xamarin Forms项目,该项目可以在一台设备上按预期工作,并且我试图在屏幕较小的另一台设备上运行该项目时,纠正一些屏幕布局问题。在较小的设备上,无法访问屏幕顶部和底部的某些项目(SKU / PO号,“保存并继续”按钮以及“计数”)。我的目标是使布局比例与屏幕尺寸一致,以便它在两种设备上均可使用。如果可能的话,我想避免使用滚动视图。我是Xamarin Forms的新手,但是我有使用Xamarin Android的经验。这是在两个设备Correct display on existing device. Incorrect display on new device.

上显示时的部分布局屏幕截图

这是布局。

<ContentPage.Resources>
    <ResourceDictionary Source="../Styles/ReceivingBaseViewStyle.xaml"/>
    <ResourceDictionary Source="../Styles/BaseLotViewStyle.xaml" />
</ContentPage.Resources>

<ContentPage.Content>
    <!--<ScrollView>-->
        <Grid Style="{StaticResource ScannerGridStyle}"
                RowSpacing="0"
                ColumnSpacing="0"
              >
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="10" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>

            <StackLayout Grid.Row="0" 
                            Style="{StaticResource BasePageIdRowStyle}">
                <Grid ColumnSpacing="0" RowSpacing="0" VerticalOptions="EndAndExpand">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="9" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>

                    <Label Grid.Column="0"
                            Text="{Binding Model.AdvanceShipNoticeIdentifier, StringFormat={x:Static resources:Labels.Global_AsnNumber_Template}}" 
                            Style="{StaticResource AsnIdRowLabelStyle}"
                            AutomationId="AsnNumber" />
                    <Image Grid.Column="1" 
                            Style="{StaticResource SeparatorDarkStyle}" />
                    <Label Grid.Column="2"
                            Text="{Binding Model.PurchaseOrderNumber, StringFormat={x:Static resources:Labels.Global_PoNumber_Template}}" 
                            Style="{StaticResource PoIdRowLabelStyle}"
                            AutomationId="PoNumber" />
                </Grid>
            </StackLayout>

            <StackLayout Grid.Row="1" 
                            Style="{StaticResource BasePageTitleWithIdRowStyle}">
                <Label Text="{x:Static resources:Labels.Receiving_SelectLot}" 
                        Style="{StaticResource BasePageTitleLabelStyle}" />
            </StackLayout>

            <StackLayout Grid.Row="2"
                            Style="{StaticResource SingleRowHighlightedStyle}">
                <controls:HintLabel Text="{Binding Model.ItemSku, StringFormat={x:Static resources:Labels.Global_SkuNumber_Template}}"
                        Style="{StaticResource HighlightedRowValueStyle}" />
            </StackLayout>

            <StackLayout Grid.Row="3"
                            Spacing="0"
                            Style="{StaticResource DescriptionRowStyle}">
                <StackLayout>
                    <Label x:Name="DescriptionTitle"
                            Text="{x:Static resources:Labels.Global_Description_Title}"
                            Style="{StaticResource DefaultLabelStyle}" />
                </StackLayout>
                <StackLayout>
                    <controls:HintLabel x:Name="DescriptionText"
                            Text="{Binding Model.ItemDescription}"
                            Style="{StaticResource DefaultTextStyle}" />
                </StackLayout>
            </StackLayout>

            <StackLayout Grid.Row="4"
                            Style="{StaticResource SeparatorRowStyle}">
                <StackLayout Style="{StaticResource SeparatorContentStyle}" />
            </StackLayout>

            <StackLayout Grid.Row="5"
                            Style="{StaticResource LotInputRowStyle}">

                <templates:CustomToggle LeftState="{Binding ItemLotModel.IsNewLotCreating, Converter={StaticResource InverseBoolConverter}}"
                                        ToggleName="{x:Static resources:Labels.Receiving_LotType}"
                                        LeftStateText="{x:Static resources:Labels.Receiving_UseExisting}"
                                        RightStateText="{x:Static resources:Labels.Receiving_CreateNew}"
                                        LeftCommand="{Binding ItemLotModel.ToggleExistingCommand}"
                                        RightCommand="{Binding ItemLotModel.ToggleNewCommand}" />

                <!-- Select Lot + New lot fields in the validation container -->
                <StackLayout>

                    <!-- Select Lot picker -->
                    <Grid RowSpacing="0"
                            ColumnSpacing="5"
                            Padding="0"
                            Style="{StaticResource ScannerGridStyle}">

                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*">
                            </ColumnDefinition>
                            <ColumnDefinition Width="140">
                            </ColumnDefinition>
                        </Grid.ColumnDefinitions>

                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto">
                            </RowDefinition>
                        </Grid.RowDefinitions>

                        <StackLayout Grid.Column="0"
                                        Grid.Row="0">
                            <Label Style="{StaticResource LotLabelStyle}"
                                    Text="{x:Static resources:Labels.Receiving_LotNumber}">
                            </Label>
                            <StackLayout IsVisible="{Binding ItemLotModel.IsNewLotCreating, Converter={StaticResource InverseBoolConverter}}">
                                <StackLayout.Triggers>
                                    <MultiTrigger TargetType="StackLayout">
                                        <MultiTrigger.Conditions>
                                            <BindingCondition Binding="{Binding ItemLotModel.SelectedLot.Errors, Converter={StaticResource ErrorsListToBoolConverter}}"
                                                                Value="True" />
                                        </MultiTrigger.Conditions>
                                        <Setter Property="Style"
                                                Value="{StaticResource ValidatableTextInputContainerActive}" />
                                    </MultiTrigger>
                                    <MultiTrigger TargetType="StackLayout">
                                        <MultiTrigger.Conditions>
                                            <BindingCondition Binding="{Binding ItemLotModel.SelectedLot.Errors, Converter={StaticResource ErrorsListToBoolConverter}}"
                                                                Value="False" />
                                        </MultiTrigger.Conditions>
                                        <Setter Property="Style"
                                                Value="{StaticResource LotInputContainerStyle}" />
                                    </MultiTrigger>
                                </StackLayout.Triggers>

                                <StackLayout Style="{StaticResource LotPickerStackLayoutStyle}"
                                                AutomationId="ExistingLotInput">
                                    <Label Text="{Binding ItemLotModel.SelectedLot.Value.Identifier}"
                                            Style="{StaticResource LotPickerLabelStyle}">

                                        <Label.GestureRecognizers>
                                            <TapGestureRecognizer 
                                            Command="{Binding ShowLotSelectionCommand}"
                                            NumberOfTapsRequired="1" />
                                        </Label.GestureRecognizers>

                                    </Label>
                                </StackLayout>

                            </StackLayout>

                            <StackLayout IsVisible="{Binding ItemLotModel.IsNewLotCreating}">
                                <StackLayout.Triggers>
                                    <MultiTrigger TargetType="StackLayout">
                                        <MultiTrigger.Conditions>
                                            <BindingCondition Binding="{Binding ItemLotModel.NewLot.Errors, Converter={StaticResource ErrorsListToBoolConverter}}"
                                                                Value="True" />
                                        </MultiTrigger.Conditions>
                                        <Setter Property="Style"
                                                Value="{StaticResource ValidatableTextInputContainerActive}" />
                                    </MultiTrigger>
                                    <MultiTrigger TargetType="StackLayout">
                                        <MultiTrigger.Conditions>
                                            <BindingCondition Binding="{Binding ItemLotModel.NewLot.Errors, Converter={StaticResource ErrorsListToBoolConverter}}"
                                                                Value="False" />
                                        </MultiTrigger.Conditions>
                                        <Setter Property="Style"
                                                Value="{StaticResource LotInputContainerStyle}" />
                                    </MultiTrigger>
                                </StackLayout.Triggers>

                                <!-- New Lot input box -->
                                <Grid RowSpacing="0"
                                        ColumnSpacing="0"
                                        Padding="0"
                                        Style="{StaticResource ScannerGridStyle}">

                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="*">
                                        </ColumnDefinition>
                                        <ColumnDefinition Width="Auto">
                                        </ColumnDefinition>
                                        <ColumnDefinition Width="Auto">
                                        </ColumnDefinition>
                                    </Grid.ColumnDefinitions>

                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto">
                                        </RowDefinition>
                                    </Grid.RowDefinitions>

                                    <controls:TextInput Grid.Column="0"
                                                        Grid.Row="0"
                                                        Style="{StaticResource LotInputStyle}"
                                                        AutomationId="NewLotInput"
                                                        Text="{Binding ItemLotModel.NewLot.Value, Mode=TwoWay}">
                                        <Entry.Behaviors>
                                            <behaviors:EventToCommandBehavior EventName="Completed"
                                                                                Command="{Binding ItemLotModel.NewLotEnteredCommand}" />
                                            <behaviors:EventToCommandBehavior EventName="TextChanged"
                                                                                Command="{Binding ItemLotModel.ValidateNewLotCommand}" />
                                        </Entry.Behaviors>
                                    </controls:TextInput>

                                </Grid>
                            </StackLayout>
                        </StackLayout>

                        <!-- Expiration box -->
                        <StackLayout Grid.Column="1"
                                        Grid.Row="0">
                            <Label Style="{StaticResource LotLabelStyle}"
                                    Text="{x:Static resources:Labels.Receiving_Expiration}">
                            </Label>
                            <StackLayout Style="{StaticResource LotInputContainerStyle}">
                                <StackLayout.Triggers>
                                    <MultiTrigger TargetType="StackLayout">
                                        <MultiTrigger.Conditions>
                                            <BindingCondition Binding="{Binding ItemLotModel.ExpirationDate.Errors, Converter={StaticResource ErrorsListToBoolConverter}}"
                                                                Value="True" />
                                        </MultiTrigger.Conditions>
                                        <Setter Property="Style"
                                                Value="{StaticResource ValidatableTextInputContainerActive}" />
                                    </MultiTrigger>
                                    <MultiTrigger TargetType="StackLayout">
                                        <MultiTrigger.Conditions>
                                            <BindingCondition Binding="{Binding ItemLotModel.ExpirationDate.Errors, Converter={StaticResource ErrorsListToBoolConverter}}"
                                                                Value="False" />
                                        </MultiTrigger.Conditions>
                                        <Setter Property="Style"
                                                Value="{StaticResource LotInputContainerStyle}" />
                                    </MultiTrigger>
                                </StackLayout.Triggers>

                                <StackLayout IsVisible="{Binding ItemLotModel.IsNewLotCreating}">
                                    <controls:NullableDatePicker Style="{StaticResource LotInputStyle}"
                                                                    NullableDate="{Binding ItemLotModel.ExpirationDate.Value}"
                                                                    AutomationId="NewLotExpirationDateInput"
                                                                    ValueUpdatedCommand="{Binding ItemLotModel.DateSelectedCommand}" >
                                    </controls:NullableDatePicker>
                                </StackLayout>

                                <StackLayout IsVisible="{Binding ItemLotModel.IsNewLotCreating, Converter={StaticResource InverseBoolConverter}}">
                                    <controls:NullableDatePicker Style="{StaticResource LotInputStyle}"
                                                                    NullableDate="{Binding ItemLotModel.SelectedLot.Value.ExpirationDate}"
                                                                    AutomationId="ExistingLotExpirationDateInput"
                                                                    IsEnabled="False">
                                    </controls:NullableDatePicker>
                                </StackLayout>

                            </StackLayout>
                        </StackLayout>
                    </Grid>
                </StackLayout>

                <!-- Error message box -->
                <StackLayout Style="{StaticResource ErrorMessageContainer}"
                                IsVisible="{Binding ItemLotModel.Errors, Converter={StaticResource ErrorsListToBoolConverter}}"
                                Margin="5">
                    <Label Text="{Binding ItemLotModel.Errors, Converter={StaticResource FirstValidationErrorConverter}}"
                            Style="{StaticResource ErrorMessageLabel}"
                            AutomationId="LoginErrorMessageLabel">
                    </Label>
                </StackLayout>

            </StackLayout>

            <StackLayout Grid.Row="6">
                <Image Style="{StaticResource ScannerRoundedCornerStyle}" />
            </StackLayout>

            <StackLayout Grid.Row="7" 
                            Style="{StaticResource BasePageActionButtonRowStyle}" Margin="0,18,0,0"
                            AutomationId="SkipItemButton">
                <Frame Style="{StaticResource BasePageActionButtonFrameStyle}">
                    <StackLayout Style="{StaticResource BasePageActionButtonContainerStyle}">
                        <Label Text="{x:Static resources:Labels.Receiving_SaveAndContinue}"
                                Style="{StaticResource BasePageActionButtonLabelStyle}"
                                IsEnabled="{Binding ItemLotModel.IsUpdating, Converter={StaticResource InverseBoolConverter}}" />
                        <Image Style="{StaticResource BasePageContinueButtonImageStyle}" />
                    </StackLayout>
                </Frame>
                <StackLayout.GestureRecognizers>
                    <TapGestureRecognizer NumberOfTapsRequired="1"
                        Command="{Binding SubmitItemLotCommand}" />
                </StackLayout.GestureRecognizers>
            </StackLayout>

            <StackLayout Grid.Row="8" Style="{StaticResource BasePageRemainingItemsRowStyle}">
                <Label Text="{Binding Model.CountNumber, StringFormat={x:Static resources:Labels.Receiving_CountName_Template}}"
                        Style="{StaticResource BasePageRemainingItemRowLabelStyle}"
                        AutomationId="CountNumber" />
            </StackLayout>

            <Label Grid.Row="8" x:Name="KeepVisibleLabel" />

        </Grid>
    <!--</ScrollView>-->
</ContentPage.Content>

任何帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:0)

如果使用 Grid 作为根布局,我们可以定义RowDefinitions以按比例显示。

例如:

<Grid.RowDefinitions>
    <RowDefinition Height="0.8*" />
    <RowDefinition Height="2*" />
    <RowDefinition Height="0.8*" />
    <RowDefinition Height="1.2*" />
    <RowDefinition Height="10" />
    <RowDefinition Height="0.8*" />
    <RowDefinition Height="1.2*" />
    <RowDefinition Height="1.2*" />
    <RowDefinition Height="1*" />
</Grid.RowDefinitions>

现在上面的代码即使在较小的设备屏幕上也可以显示全部内容。

0.8*表示屏幕高度的8%,而1.2*表示屏幕高度的12%。如果未超过屏幕高度,则使它们的总和小于10*

此外,无论设备的屏幕是大还是小,我们也可以使用Xamarin.Forms RelativeLayout按比例显示。