首页 文章

如何在Xamarin中的ScrollView内的StackLayout中正确使用AbsoluteLayout?

提问于
浏览
3

好的,我放弃了 . 尝试完成这个简单的事情花了3天时间 .

这是我的场景(并非所有在同一个XAML文件中):

<TabbedPage>
  <NavigationPage>
    <ContentPage/>
    <ContentPage/>
    <CarouselPage>
      <CarouselContentPage>

这是 CarouselContentPage

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyApp.Layouts.PointInfoDataTemplate"
             >
  <ContentPage.Content>  
    <ScrollView Orientation="Vertical" BackgroundColor="Navy" VerticalOptions="Fill">
      <StackLayout x:Name="MyStackLayout" HorizontalOptions="StartAndExpand" VerticalOptions="Start" BackgroundColor="Gray">
        <Label x:Name="NameLabel" FontSize="Medium" HorizontalOptions="Center"/>
        <Label x:Name="DescLabel" FontSize="Medium" HorizontalOptions="Center" />
        <AbsoluteLayout x:Name="ImgsContainer" VerticalOptions="Start" BackgroundColor="Green">
          <Image x:Name="BackImg" Aspect="AspectFit" VerticalOptions="Start"/>
          <Image x:Name="MidImg" Aspect="AspectFit" VerticalOptions="Start"/>
          <Image x:Name="FrontImg" Aspect="AspectFit" VerticalOptions="Start"/>
        </AbsoluteLayout>
      </StackLayout>
    </ScrollView>
  </ContentPage.Content>
</ContentPage>

我需要的是简单的,垂直滚动页面垂直堆叠几个标签,之后我需要创建"one image",它由3个图像组成,彼此重叠(如3层重叠) . 为此,我需要 AbsoluteLayout 仅用于图像,对吗?

我已经为这个文件中的所有视图尝试了所有可能的 VerticalOptions 组合,但没有任何效果 .

问题是滚动总是在图像下留下一个大空间 . 并且使用绿色,这意味着 AbsoluteLayout 在图像调整大小后不会缩小其高度 . 图像可以具有可变的大小和形状(尽管每个页面内的3个都具有相同的尺寸)并且它们都比任何智能手机屏幕都大(稍后的缩放功能) . 所以我需要图像使用所有可用的宽度并保持纵横比(我相信 AspectFit ) .

所有图像都是嵌入式资源 . 这是 CarouselContentPage 背后的代码:

public PointInfoDataTemplate(PointModel point)
{
    InitializeComponent();
    NameLabel.Text = point.nome;
    DescLabel.Text = point.apelido;
    BackImg.Source = ImageSource.FromResource(point.backimg);
    MidImg.Source = ImageSource.FromResource(point.midimg);
    FrontImg.Source = ImageSource.FromResource(point.frontimg);
    //BackImg.SizeChanged += delegate {
    //    ImgsContainer.Layout(new Rectangle(imgsContainer.Bounds.X, imgsContainer.Bounds.Y, BackImg.Bounds.Width, BackImg.Bounds.Height));
    //    MyStackLayout.Layout(new Rectangle(imgsContainer.Bounds.X, imgsContainer.Bounds.Y, BackImg.Bounds.Width, BackImg.Bounds.Height));
    //};
}

我甚至在 SizeChanged 事件后尝试调整了Layouts的大小,但它也没有用 .

所以也许我做错了,这是我的所有代码 . 我被困了3天,我不知道还能做什么 .

我尝试使用 RelativeLayout 作为 ScrollView.Content . 经过一整天试图理解它(并且不确定我是否完全做到了),我遇到了更糟糕的问题 . RelativeLayout 将溢出 Scroll 高度并隐藏选项卡(基本应用程序容器)后面的部分图像 .

但我真的想保留 StackLayout->items + AbsoluteLayout 方法 .

我感谢任何帮助 .

3 回答

  • 1

    我发现问题是 AbsoluteLayout 没有处理它的子调整大小事件 . Image元素的问题不是调度正确的事件,或者 AbsoluteLayout 没有很好地处理它们 . 所以我需要的只是创建这个事件处理 . 添加了 Image.SizeChanged 的监听器以设置 AbsoluteLayout 高度 .

    private void BackImg_SizeChanged(object sender, EventArgs e)
            {
                ImgsContainer.HeightRequest = BackImg.Height;
            }
    

    这适用于我的情况,但如果你有一个更复杂的 AbsoluteLayout 的子处置,你将需要这样的东西:

    private void ChildAdded_EventHandler(object sender, EventArgs e) {
        double neededHeight = 0;
        foreach(var child in sender) {
            if(neededHeight < child.Y+child.Height) {
                neededHeight = child.Y+child.Height;
            }
        }
        sender.HeightRequest = neededHeight;
    }
    

    并且您必须将此事件处理程序添加到 AbsoluteLayout.ChildAddedAbsoluteLayout.ChildRemoved ;

  • 1

    如果Grid解决方案有效,那可能会更容易,但是因为你问过AbsoluteLayout ......

    要使AbsoluteLayout正常工作,您不要在子项上使用与其他视图相同的VerticalOptions .

    相反,还有其他方法可以准确指出如何布置与绝对布局相关的孩子 . 使用C#而不是Xaml,你会做类似的事情:

    AbsoluteLayout.SetLayoutFlags(BackImg,
         AbsoluteLayoutFlags.PositionProportional);
    AbsoluteLayout.SetLayoutBounds(BackImg,
         new Rectangle(0, 0, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize));
    

    和MidImg和FrontImg一样 .

    SetLayoutFlags告诉系统子项的大小和/或位置的哪些方面与父项成比例 . 然后SetLayoutBounds提供了如何布局的详细信息 . 在这种情况下,代码说要在左上角布置BackImg .

  • 2

    它在C#中不是XAML,但它应该很容易转换

    Grid imageContainer = new Grid() {    
        HeightRequest = 400,
    
        Children = {
            new Image(), //Image 1
            new Image(), //Image 2 on top of image 1
            new Image(), //Image 3 on top of image 2 and 1
        }
    }
    
    Content = new ScrollView() {    
        Content = new Grid() {
            RowDefinitions = {
                new RowDefinition(){Height = new GridLength(1, GridUnitType.Auto)}, //label1
                new RowDefinition(){Height = new GridLength(1, GridUnitType.Auto)}, //label2
                new RowDefinition(){Height = new GridLength(1, GridUnitType.Auto)}, //image container
            },
    
            Children ={
                {new Label(), 0, 0},   //Label 1
                {new Label(), 0, 1},   //Label 2
                {imageContainer, 0, 2} //image container
            }
        }
    };
    

相关问题