我已经得到了一个现有的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>
任何帮助将不胜感激。谢谢!
答案 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按比例显示。