是否可以在设置一次后更改RelativeLayout
的约束?
在文档中我看到像GetBoundsConstraint(BindableObject)
这样的方法,但我认为只有拥有XAML文件才能使用它们。现在我正在尝试在代码中执行此操作。如果我尝试
null
RelativeLayout.GetBoundsConstraint(this.label);
我发现的唯一方法是从布局中删除子项并再次使用新约束添加它。
示例:
public class TestPage : ContentPage
{
private RelativeLayout relativeLayout;
private BoxView view;
private bool moreWidth = false;
public TestPage()
{
this.view = new BoxView
{
BackgroundColor = Color.Yellow,
};
Button button = new Button
{
Text = "change",
TextColor = Color.Black,
};
button.Clicked += Button_Clicked;
this.relativeLayout = new RelativeLayout();
this.relativeLayout.Children.Add(this.view,
Constraint.Constant(0),
Constraint.Constant(0),
Constraint.Constant(80),
Constraint.RelativeToParent((parent) =>
{
return parent.Height;
}));
this.relativeLayout.Children.Add(button,
Constraint.RelativeToParent((parent) =>
{
return parent.Width / 2;
}),
Constraint.RelativeToParent((parent) =>
{
return parent.Height / 2;
}));
this.Content = this.relativeLayout;
}
private void Button_Clicked(object sender, EventArgs e)
{
double width = 0;
if(this.moreWidth)
{
width = 120;
}
else
{
width = 80;
}
var c= BoundsConstraint.FromExpression((Expression<Func<Rectangle>>)(() => new Rectangle(0, 0, width, this.Content.Height)), new View[0]);
RelativeLayout.SetBoundsConstraint(this.view, c);
this.relativeLayout.ForceLayout();
this.moreWidth = !this.moreWidth;
}
}
答案 0 :(得分:12)
当前版本的Xamarin Forms不能正式。 RelativeLayout
容器仅在从子集合中添加/删除项目时重新计算约束(它缓存已解决的约束 - 可能需要性能)。尽管各种约束都是作为Bindable Properties实现的,但在更改时仍然无法重新计算。
我认为目的是有朝一日尊重约束更新,例如,这对于动画很有用,但是现在它看起来并不像那样。
HOWEVER ,我看了一下RelativeLayout的反编译源代码, 可以通过它来解决它 - 但它可能不适合你的需求,具体取决于您需要多少功能以及约束定义的复杂程度。
请参阅此示例代码(关键部分是使用SetBoundsConstraint设置约束,它会覆盖添加的视图的内部计算边界 - 然后调用ForceLayout()
):
public partial class App : Application
{
public App ()
{
var label = new Label {
Text = "Test",
HorizontalTextAlignment = TextAlignment.Center,
VerticalTextAlignment = TextAlignment.Center,
BackgroundColor = Color.Silver
};
var layout = new RelativeLayout ();
layout.Children.Add (label,
Constraint.Constant (50),
Constraint.Constant (100),
Constraint.Constant (260),
Constraint.Constant (30));
MainPage = new ContentPage {
Content = layout
};
var fwd = true;
layout.Animate ("bounce",
(delta) => {
var d = fwd ? delta : 1.0 - delta;
var y = 100.0 + (50.0 * d);
var c = BoundsConstraint.FromExpression ((Expression<Func<Rectangle>>)(() => new Rectangle (50, y, 260, 30)), new View [0]);
RelativeLayout.SetBoundsConstraint(label, c);
layout.ForceLayout ();
}, 16, 800, Easing.SinInOut, (f, b) => {
// reset direction
fwd = !fwd;
}, () => {
// keep bouncing
return true;
});
}
}
答案 1 :(得分:1)
如果我理解正确,我会尝试以下
为relativeLayout实现SizeChanged事件
喜欢: -
var relativeLayout = new RelativeLayout ();
relativeLayout.SizeChanged += someEventForTesting;
并在您想要调整相对布局或某个特定子项的大小时调用该事件。
public void someEventForTesting(Object sender , EventArgs)
{
var layout = (RelativeLayout)sender ;
//here you have access to layout and every child , you can add them again with new constraint .
}
答案 2 :(得分:0)
是的。这可能。 布局代码:
<StackLayout RelativeLayout.XConstraint="{Binding XConstaint}" ...>
VM代码:
public Constraint XConstaint
{
get => _xConstaint;
set { SetFieldValue(ref _xConstaint, value, nameof(XConstaint)); }
}
public override void OnAppearing()
{
base.OnAppearing();
XConstaint = Constraint.RelativeToParent((parent) => { return parent.Width - 128; });
}