Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Forms:随后更改RelativeLayout约束_C#_Xamarin_Layout_Xamarin.forms - Fatal编程技术网

C# Forms:随后更改RelativeLayout约束

C# Forms:随后更改RelativeLayout约束,c#,xamarin,layout,xamarin.forms,C#,Xamarin,Layout,Xamarin.forms,是否可以在设置一次约束后更改约束 在文档中我看到了像GetBoundsConstraint(BindableObject)这样的方法,但我认为只有在拥有XAML文件的情况下才能使用它们。目前,我正试图在代码中实现这一点。如果我尝试,我会得到null RelativeLayout.GetBoundsConstraint(this.label); 我发现的唯一方法是从布局中删除子项,然后再次添加新约束 示例: public class TestPage : ContentPage { pr

是否可以在设置一次约束后更改约束

在文档中我看到了像
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;
    }
}
public类测试页:ContentPage
{
私人亲戚;
私有BoxView视图;
private bool moreWidth=false;
公共测试页()
{
this.view=new-BoxView
{
背景颜色=颜色。黄色,
};
按钮=新按钮
{
Text=“更改”,
TextColor=Color.Black,
};
按钮。点击+=按钮\点击;
this.relativeLayout=新的relativeLayout();
this.relativeLayout.Children.Add(this.view,
约束常数(0),
约束常数(0),
约束常数(80),
约束。RelativeToParent((父项)=>
{
返回父项高度;
}));
此.relativeLayout.Children.Add(按钮,
约束。RelativeToParent((父项)=>
{
返回父项宽度/2;
}),
约束。RelativeToParent((父项)=>
{
返回父项高度/2;
}));
this.Content=this.relativeLayout;
}
已单击私有无效按钮(对象发送者,事件参数e)
{
双倍宽度=0;
如果(此.moreWidth)
{
宽度=120;
}
其他的
{
宽度=80;
}
var c=BoundsConstraint.FromExpression((表达式)(()=>新矩形(0,0,width,this.Content.Height)),新视图[0]);
RelativeLayout.SetBoundsConstraint(this.view,c);
此.relativeLayout.ForceLayout();
this.moreWidth=!this.moreWidth;
}
}
对于当前版本的Xamarin表单,官方不允许这样做。
RelativeLayout
容器仅在从其子集合中添加/删除项时重新计算约束(它缓存已解决的约束-可能是为了性能)。即使各种约束被实现为可绑定属性,它们在更改时仍然不会重新计算

我假设其目的是为了有一天尊重约束更新,例如,这对动画很有用,但目前看来它似乎不是这样工作的

然而,我查看了RelativeLayout的反编译源代码,可以找到一种解决方法-但它可能不适合您的需要,这取决于您需要多少功能以及约束定义有多复杂

请参阅此示例代码(关键部分是使用SetBoundsConstraint设置约束,该约束覆盖添加视图的内部计算边界,然后调用
ForceLayout()
):

公共部分类应用程序:应用程序
{
公共应用程序()
{
变量标签=新标签{
Text=“测试”,
HorizontalTextAlignment=TextAlignment.Center,
VerticalTextAlignment=TextAlignment.Center,
背景颜色=颜色。银色
};
var布局=新的RelativeLayout();
layout.Children.Add(标签,
约束常数(50),
约束常数(100),
约束常数(260),
常数(30);
主页=新内容页{
内容=布局
};
var fwd=真;
布局。动画(“反弹”,
(增量)=>{
var d=fwd?增量:1.0-增量;
变量y=100.0+(50.0*d);
var c=BoundsConstraint.FromExpression((表达式)(()=>新矩形(50,y,260,30)),新视图[0]);
相对立根约束(标签c);
layout.ForceLayout();
},16800,Easing.SinInOut,(f,b)=>{
//重置方向
fwd=!fwd;
}, () => {
//继续跳
返回true;
});
}
}

如果我理解正确,我会尝试以下方法

为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 .
}
对。这是可能的。 布局代码:

<StackLayout RelativeLayout.XConstraint="{Binding XConstaint}" ...>

谢谢你的回答!是否可以将
BoundsConstraint.FromExpression
Constraint.RelativeToParent
一起使用?或者只能为
矩形设置值?我想做的是改变占据屏幕一半的元素的宽度。因此,您必须知道父级高度。目前我正在使用
this.Content.Height
,这似乎很有效。尽管我必须进一步测试它。只要您要修改的项上的所有约束都是常量或相对父项(BoundsConstraint是所有四个x/y/宽度/高度约束的组合,因此所有这些约束都必须满足此标准),它就应该可以工作。如果其中任何一个使用RelativeToView,则需要将这些视图作为第二个参数在数组中传递给
FromExpression()
。不过,除非您尝试一下,否则很难确定这种破解方法是否适用于常数以外的任何东西。当然,这取决于内部结构,所以在下一个XF版本中可能会出现中断。我尝试使用
RelativeToParent
,但难以使用正确的表示法。我尝试使用
Constraint.RelativeToParent((parent)=>{return parent.Height;})代替常量
<StackLayout RelativeLayout.XConstraint="{Binding XConstaint}" ...>
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; });
}