我试图在相对布局中覆盖多个透明背景图像。所以我有1个背景图像和2个重叠的前景图像,如下所示。当我在XAML中将其定义为静态时,下面的代码工作得很好,但现在我的要求是动态添加前景图像。
因此下面的背景图像是静态的,但前景1,前景2,前景3 ......所以图像的计数将在运行时确定。这可以在xaml.cs类中通过向RelativeLayout添加子项来完成,但我使用MVVM方法并且很难将两者混合使用。如何使用MVVM动态创建多个图像以覆盖在背景图像上?
基本上我如何创建ListView中的图像列表,而不是垂直对齐,它们应该相互叠加?
<RelativeLayout x:Name="rlMain" Style="{StaticResource rlStyle}" HorizontalOptions="Start" VerticalOptions="FillAndExpand" >
<Image x:Name="backgroundImage" Source="background.png" Style="{StaticResource ImageStyle}"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=Constant,
Constant=0}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=Constant,
Constant=0}"
RelativeLayout.WidthConstraint =
"{ConstraintExpression Type=RelativeToParent,
Property=Width}"
RelativeLayout.HeightConstraint =
"{ConstraintExpression Type=RelativeToParent,
Property=Height}"/>
<Image x:Name="foreground1" Style="{StaticResource ImageStyle}" Source="{Binding MainFrontPath, Mode=TwoWay}"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=Constant,
Constant=0}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=Constant,
Constant=0}"
RelativeLayout.WidthConstraint =
"{ConstraintExpression Type=RelativeToParent,
Property=Width}"
RelativeLayout.HeightConstraint =
"{ConstraintExpression Type=RelativeToParent,
Property=Height}"/>
<Image x:Name="foreground2" Style="{StaticResource ImageStyle}" Source="{Binding SecFrontPath, Mode=TwoWay}"
RelativeLayout.XConstraint=
"{ConstraintExpression Type=Constant,
Constant=0}"
RelativeLayout.YConstraint=
"{ConstraintExpression Type=Constant,
Constant=0}"
RelativeLayout.WidthConstraint =
"{ConstraintExpression Type=RelativeToParent,
Property=Width}"
RelativeLayout.HeightConstraint =
"{ConstraintExpression Type=RelativeToParent,
Property=Height}"/>
</RelativeLayout>
答案 0 :(得分:1)
我可能不明白你的意图所以请原谅我,如果我没有。
如果您愿意在将每个新元素添加到布局时构建代码来管理布局约束的应用,则可以使用RelativeLayout
执行所需操作。走下这条路,我不推荐它,因为试图让RelativeLayout
的布局代码很快变得复杂,(更重要的是)RelativeLayout
很慢。我之所以这么说,是因为我已经尝试过了,一旦我做到了。经历了这些过程,我意识到构建自定义布局会更快,更易于维护。
所以,如果有人对自定义布局感兴趣,这里有一些基础知识:
您可以将自定义布局作为继承自Xamarin.Forms.Layout<View>
的类启动。正如您从Xamarin Forms文档中看到的那样Layout<View>
及其父级,Layout
是非常简单的类。
布局周期分为两部分:测量和放置。
您可以覆盖自定义布局的OnMeasure
方法(或GetMeasure
,如果您想要更新)来管理“测量”部分。在这里,您要告诉Xamarin Forms布局引擎两件事:
关于OnMeasure
的有趣之处在于您可能会发现内置行为足够好。我建议首先关注Placement部分,看看祖先OnMeasure
代码分配的空间是否符合您的需求。
自定义布局的LayoutChildren
方法是您进行计算并应用自定义布局(布局周期的放置部分)的方法。实际上,它可能是您需要覆盖的唯一方法。它在布局周期中由Xamarin Forms调用,并提供由其父布局提供的位置和大小。
现在可以使用位置和大小,您可以开始计算自定义布局的子视图/布局在您分配的大小内的位置和大小。由于您手动执行此操作,因此您必须考虑自定义布局的填充和每个子视图/布局的保证金。一旦您拥有与此自定义布局相关的子项位置和大小(边界),您将使用LayoutChildInBoundingRegion(VisualElement child, Rectangle bounds)
让Xamarin Forms的布局引擎执行其布局。
看看你的设计目标,我不知道的一件事是什么将控制图像相互重叠的顺序。这将是他们在自定义布局的Children
数组中的顺序,您调用LayoutChild
的顺序,或两者(取决于在不同设备上管理布局周期的方式) 。由于这种不确定性,我会假设它是两者并且以与LayoutChildren
列表相同的顺序在每个孩子上调用Children
。
以下是一个示例自定义布局,其中只包含基本要素:
using System;
using Xamarin.Forms;
namespace Forms9Patch
{
public class ManualLayout : Xamarin.Forms.Layout<View>
{
protected override void LayoutChildren(double x, double y, double width, double height)
{
// layout calculations go here. Don't forget to account for
// this layout's Padding and each child view's/layout's Margin.
// for the sake of this example, let's say I've stored these
// calculation results in:
Dictionary<View, Rectangle> bounds = new Dictionary<View, Rectangle>();
// And with those calculation results, I can apply the layouts.
foreach (var child in Children)
LayoutChild(child, bounds[child]);
}
}
}
通过完全控制您的自定义布局,您会惊讶于您可以构建哪种自定义布局。现在我已经有了一些经验,坦率地说,我非常喜欢它,并且由于它的速度,已经开始依赖它了。
再次,抱歉,如果这个建议被误导了。