Xamarin.Forms动态布局取决于屏幕方向或大小

时间:2017-10-04 12:12:22

标签: c# xaml xamarin xamarin.forms

Xamarin.Forms是否已经包含一个控件/布局,根据屏幕方向或大小来命令它的内容?

我想要的: 如果屏幕有足够的空间,则两个stacklayouts水平排序。 当屏幕改变时,屏幕没有足够的水平空间,两个堆叠布局应垂直排序。

I dont want to do it in code behind.

I search for an solution which only uses the xaml.

提前致谢

2 个答案:

答案 0 :(得分:2)

(我很抱歉我的英语不好)

我猜你无法使用ONLY XAML实现这一点。当然你需要一些c#代码。 Xamarin.Forms上的XAML设计为响应式,您经常以相对模式(绝对值)定义视图属性。

您可以查看所需行为的示例at this topic,我们可以在其中看到根据设备方向更改StackLayout方向的屏幕(您可以将其用作编写自己的布局组件的指南)< / p>

纵向模式下的屏幕: The screen on portrait mode

横向模式下的屏幕: The screen on landscape mode

  

使用以下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;
        }
    }
}

我希望它可以帮到你。

答案 1 :(得分: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;

也许你不得不使用内部StackLayout s的水平选项 - 或其他布局参数,但基本上应该这样做。