我正在尝试使用 AbsoluteLayout 并设置了一个非常基本的页面,其中包含一个 2 行的网格。
第一行包含另一个网格,其中包含一个按钮,第二行包含一个 AbsoluteLayout,在可用高度(页面的高度减去第一行的高度)上布局 2 个 BoxView。
每个框共享页面的不同比例。单击按钮会更改归因于每个 BoxView 的页面比例。
这是代码:
<Grid x:Name="mainGrid" RowDefinitions="auto, *">
<Grid x:Name="topBar" HeightRequest="200" BackgroundColor="Green" >
<Button VerticalOptions="Center" HorizontalOptions="Center"
Text="Change layout" Clicked="Button_Clicked"/>
</Grid>
<AbsoluteLayout Grid.Row="1" x:Name="absoluteLayout">
<BoxView BackgroundColor="Blue" x:Name="blueBox"/>
<BoxView BackgroundColor="Red" x:Name="redBox"/>
</AbsoluteLayout>
</Grid>
Rect _blueRect;
Rect _redRect;
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
double availableHeight = height - topBar.Height;
_blueRect = new Rect(0, 0, width, availableHeight * 0.7);
_redRect = new Rect(0, _blueRect.Height, width, availableHeight * 0.3);
absoluteLayout.SetLayoutBounds(blueBox, _blueRect);
absoluteLayout.SetLayoutBounds(redBox, _redRect);
}
private void Button_Clicked(object sender, EventArgs e)
{
double availableHeight = Height - topBar.Height;
_blueRect = new Rect(0, 0, Width, availableHeight * 0.4);
_redRect = new Rect(0, _blueRect.Height, Width, availableHeight * 0.6);
absoluteLayout.SetLayoutBounds(blueBox, _blueRect);
absoluteLayout.SetLayoutBounds(redBox, _redRect);
}
现在这段代码在 Windows 上可以完美运行,但在 Android 上则不行。 OnSizeAllocation 中请求的布局更改从未被考虑在内,我尝试了一些基本的操作,例如调用 InvalidateMeasure 或 ForceLayout,但没有成功。
我怀疑这可能是一个错误,也许我缺少一个简单的解决方法,或者可以采取稍微不同的方法来实现此处描述的场景?非常感谢您对此的任何意见。
我已经测试了您的代码并重现了该问题。但问题不在于 AbsoluteLayout 位置,而是BoxView。
您可以在Button_Clicked的开头添加下面两行代码。
var blueLayoutBounds = absoluteLayout.GetLayoutBounds(blueBox);
var redLayoutBounds = absoluteLayout.GetLayoutBounds(redBox);
然后你会看到该值是正确的。 OnSizeAllocation 中请求的布局更改成功。
但是如果你使用
var blueHeight = blueBox.Height
,你会发现该值为0。所以看起来布局更改没有通知 BoxView 调整大小。您可以在 repo 上转发此内容。
作为解决方法,您可以手动设置 BoxView 的 HeightRequest:
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
double availableHeight = height - topBar.Height;
_blueRect = new Rect(0, 0, width, availableHeight * 0.7);
_redRect = new Rect(0, _blueRect.Height, width, availableHeight * 0.3);
absoluteLayout.SetLayoutBounds(blueBox, _blueRect);
absoluteLayout.SetLayoutBounds(redBox, _redRect);
blueBox.HeightRequest = availableHeight * 0.7;
redBox.HeightRequest = availableHeight * 0.3;
}
private void Button_Clicked(object sender, EventArgs e)
{
double availableHeight = Height - topBar.Height;
_blueRect = new Rect(0, 0, Width, availableHeight * 0.4);
_redRect = new Rect(0, _blueRect.Height, Width, availableHeight * 0.6);
absoluteLayout.SetLayoutBounds(blueBox, _blueRect);
absoluteLayout.SetLayoutBounds(redBox, _redRect);
blueBox.HeightRequest = availableHeight * 0.4;
redBox.HeightRequest = availableHeight * 0.6;
}