【问题标题】:Xamarin.Forms dynamic layout depending on screen orientation or sizeXamarin.Forms 动态布局取决于屏幕方向或大小
【发布时间】:2017-10-04 12:12:22
【问题描述】:

Xamarin.Forms 是否已经包含根据屏幕方向或大小对其内容进行排序的控件/布局?

我想要的: 如果屏幕有足够的空间,则水平排列的两个堆栈布局。 当屏幕发生变化,导致屏幕没有足够的水平空间时,两个堆栈布局应该垂直排列。

我不想在后面的代码中这样做。

我正在寻找只使用 xaml 的解决方案。

【问题讨论】:

  • 我知道 UWP 有这个,但我也很想知道 Xamarin 目前是否支持这个。
  • solution wich only uses the xaml :没有布局可以做到这一点,您当然可以编写一个或在代码隐藏中处理它,但您排除了这一点。
  • @Tony 你能给我一份文档或一些关于 uwp 的参考吗?也许我可以适应它。

标签: c# xaml xamarin xamarin.forms


【解决方案1】:

我猜你不能只使用 XAML 来实现这一点。当然,您将需要一些 c# 代码。 Xamarin.Forms 上的 XAML 设计为响应式,您通常以相对模式(而不是绝对模式)定义视图属性。

您可以看到您想要的行为示例at this topic,我们可以看到屏幕根据设备方向更改 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# 用于根据 设备方向:

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;
        }
    }
}

希望对你有帮助。

【讨论】:

  • 非常感谢!太糟糕了,没有唯一的 xaml 变体。
  • 我同意。但请记住,XAML 是一种标记语言,不幸的是,您不能在上面编写所有内容。我建议您查看this presentation of Charles Pretzold at Xamarin Evolve 2016,这对我有很大帮助!这是一种关于 XAML 的惊人方法。看完之后我成了粉丝。
【解决方案2】:

据我所知,这是不可能的。我基本上做了你想要的“手动”。不过,这并不太难。首先,您必须将堆栈布局包装在另一个 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;

也许您将不得不稍微摆弄内部StackLayouts 的水平选项 - 或其他布局参数,但基本上应该这样做。

【讨论】:

    猜你喜欢
    • 2014-07-30
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多