[英]Xamarin.Forms dynamic layout depending on screen orientation or size
Xamarin.Forms 是否已經包含一個控件/布局,它根據屏幕方向或大小對其內容進行排序?
我想要的:如果屏幕有足夠的空間,兩個堆棧布局是水平排列的。 當屏幕發生變化時,屏幕沒有足夠的水平空間,兩個堆棧布局應該垂直排列。
我不想在后面的代碼中這樣做。
我搜索僅使用 xaml 的解決方案。
我猜你不能只使用 XAML 來實現這一點。 當然,您將需要一些 c# 代碼。 Xamarin.Forms 上的 XAML 設計為響應式的,您通常以相對模式(而不是絕對模式)定義視圖屬性。
您可以在本主題中看到您想要的行為示例,我們可以看到屏幕根據設備方向更改 StackLayout 的方向(您可以將其用作編寫自己的布局組件的指南)
這是通過以下 XAML 完成的:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ResponsiveLayout.StackLayoutPageXaml"
Title="Stack Photo Editor - XAML">
<ContentPage.Content>
<StackLayout Spacing="10" Padding="5" Orientation="Vertical"
x:Name="outerStack"> <!-- can change orientation to make responsive -->
<ScrollView>
<StackLayout Spacing="5" HorizontalOptions="FillAndExpand"
WidthRequest="1000">
<StackLayout Orientation="Horizontal">
<Label Text="Name: " WidthRequest="75"
HorizontalOptions="Start" />
<Entry Text="deer.jpg"
HorizontalOptions="FillAndExpand" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Date: " WidthRequest="75"
HorizontalOptions="Start" />
<Entry Text="07/05/2015"
HorizontalOptions="FillAndExpand" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Tags:" WidthRequest="75"
HorizontalOptions="Start" />
<Entry Text="deer, tiger"
HorizontalOptions="FillAndExpand" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Button Text="Save" HorizontalOptions="FillAndExpand" />
</StackLayout>
</StackLayout>
</ScrollView>
<Image Source="deer.jpg" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
一些 C# 用於根據設備的方向更改 outerStack 的方向:
protected override void OnSizeAllocated (double width, double height){
base.OnSizeAllocated (width, height);
if (width != this.width || height != this.height) {
this.width = width;
this.height = height;
if (width > height) {
outerStack.Orientation = StackOrientation.Horizontal;
} else {
outerStack.Orientation = StackOrientation.Vertical;
}
}
}
我希望它對你有幫助。
據我所知,這是不可能的。 我基本上做了你想要的“手動”。 不過,這並不太難。 首先,您必須將堆棧布局包裝在另一個StackLayout
中
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App.Views.TestPage">
<ContentPage.Content>
<StackLayout x:Name="OuterStackLayout">
<StackLayout>
<!-- Inner stack layout 1 -->
</StackLayout>
<StackLayout>
<!-- Inner stack layout 2 -->
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
接下來,您必須覆蓋OnSizeAllocated
並根據您的屏幕方向設置外部OuterStackLayout.Orientation
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
if (SizeHasChanged(width, height)) // elided, just compare width, height with the stored values
{
StoreSize(width, height); // store in private members
if (IsLandscape)
{
this.OuterStackLayout.Orientation = StackOrientation.Horizontal;
}
else
{
this.OuterStackLayout.Orientation = StackOrientation.Vertical;
}
}
}
public bool IsLandscape => _width > _height;
也許您將不得不擺弄內部StackLayout
的水平選項或其他布局參數,但基本上應該這樣做。
選項 #1 '方向狀態' - 縱向和橫向。 在視覺狀態管理器中使用“OrientationStates”,如下所示:
內部 .XAML 文件
<Grid x:Name="myGrid"
Margin="10,30,10,10">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="OrientationStates">
<!-- Row & Column Definitions of Grid - [2 Rows, 1 Col = Portrait] & [1 Row, 2 Cols = Landscape] -->
<VisualState x:Name="Portrait">
<VisualState.Setters>
<Setter Property="Grid.RowDefinitions"
Value="*,*" />
<Setter Property="Grid.ColumnDefinitions"
Value="*" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Landscape">
<VisualState.Setters>
<Setter Property="Grid.RowDefinitions"
Value="*" />
<Setter Property="Grid.ColumnDefinitions"
Value="*,*" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<!-- Change position of stack layouts in grid, to match above stated orientation requirement -->
<StackLayout x:Name="firstStackLayout">
<Entry Placeholder="Enter first words" />
<Button Text="Nothing Happens" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Portrait">
<VisualState.Setters>
<Setter Property="Grid.Row" Value="0" />
<Setter Property="Grid.Column" Value="0" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Landscape">
<VisualState.Setters>
<Setter Property="Grid.Row" Value="0" />
<Setter Property="Grid.Column" Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</StackLayout>
<StackLayout x:Name="secondStackLayout">
<Entry Placeholder="Enter last words" />
<Button Text="Still Nothing Happens" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="Portrait">
<VisualState.Setters>
<Setter Property="Grid.Row" Value="1" />
<Setter Property="Grid.Column" Value="0" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Landscape">
<VisualState.Setters>
<Setter Property="Grid.Row" Value="0" />
<Setter Property="Grid.Column" Value="1" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</StackLayout>
</Grid>
在 CodeBehind 中添加了“OnSizeAllocated()”函數,如下所示:
內部 .XAML.CS 文件
public partial class RegisterPage : ContentPage
{
public RegisterPage()
{
InitializeComponent();
}
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
var state = (width > height) ? "Landscape" : "Portrait";
// Call the 'Portrait' & 'Landscape' States in .XAML File
VisualStateManager.GoToState(myGrid, state);
VisualStateManager.GoToState(firstStackLayout, state);
VisualStateManager.GoToState(secondStackLayout, state);
}
}
[或者]
選項 #2 靈丹妙葯 - 您唯一的 .XAML 文件解決方案。
“方向觸發器” - 縱向和橫向。
在 Visual State 的“狀態觸發器”中使用“OrientationStateTriggers”,如下所示:
內部 .XAML 文件
<Grid Margin="10,30,10,10">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<!-- Row & Column Definitions of Grid - [2 Rows, 1 Col = Portrait] & [1 Row, 2 Cols = Landscape] -->
<VisualState x:Name="gridPortrait">
<VisualState.StateTriggers>
<OrientationStateTrigger Orientation="Portrait" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Property="Grid.RowDefinitions"
Value="*,*" />
<Setter Property="Grid.ColumnDefinitions" Value="*" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="gridLandscape">
<VisualState.StateTriggers>
<OrientationStateTrigger Orientation="Landscape" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Property="Grid.RowDefinitions"
Value="*" />
<Setter Property="Grid.ColumnDefinitions"
Value="*,*" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<!-- Change position of stack layouts in grid, to match above stated orientation requirement -->
<StackLayout>
<Entry Placeholder="Enter first words" />
<Button Text="Nothing Happens" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="myPortraitState">
<VisualState.StateTriggers>
<OrientationStateTrigger Orientation="Portrait" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Property="Grid.Row" Value="0" />
<Setter Property="Grid.Column" Value="0" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="myLandscapeState">
<VisualState.StateTriggers>
<OrientationStateTrigger Orientation="Landscape" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Property="Grid.Row" Value="0" />
<Setter Property="Grid.Column" Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</StackLayout>
<StackLayout>
<Entry Placeholder="Enter last words" />
<Button Text="Still Nothing Happens" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="myPortraitState">
<VisualState.StateTriggers>
<OrientationStateTrigger Orientation="Portrait" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Property="Grid.Row" Value="1" />
<Setter Property="Grid.Column" Value="0" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="myLandscapeState">
<VisualState.StateTriggers>
<OrientationStateTrigger Orientation="Landscape" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Property="Grid.Row" Value="0" />
<Setter Property="Grid.Column" Value="1" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</StackLayout>
</Grid>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.