xamarin学习笔记B06(ios的Autolayout布局)

(每次学习一点xamarin就做个学习笔记和视频来加深记忆巩固知识)

如有不正确的地方,请帮我指正。

 

Autolayout简介

Autolayout是一种自动布局技术,很方便进行屏幕适配。在这之前有Autoresizing技术,但只能设置控件自己和父控件之间的位置关系,有点类似于Winform中的Anchor。而Autolayout可以设置任意控件之间的位置关系。

 

Autolayout原理

原理就是通过公式 View1.Property = (View2.Property * multiplier) + constant 最终得到Frame值(X,Y,Width,Height)。

视图1的属性值 = (视图2的属性值乘以乘数)加上一个常量值。

举几个例子:

例A:UIImageView的宽为150,高为150,距离UIView的左边和上边都是10。那么:

imageView.Width=(0 * 1.0)+150

imageView.Height=(0 * 1.0)+150

imageView.X=(UIView.Left*1.0)+10

imageView.Y=(UIView.Top*1.0)+10

 

例B:UILabel的上边距离图片是7,下边距离UIView是8,左边距离UIView是10,右边距离UIView的右边是16。那么:

label.Y=(imageView.Bottom*1.0)+7

label.Height=((UIView.Bottom*1.0-8) – label.Y

label.X=(UIView.Left*1.0)+10

label.Width=(UIView.Right*1.0-16) – label.X

 

例C:UILabel的宽永远等于UIView的宽的一半。那么:

label.Width=(UIView.Width*0.5)+0

Autolayout基本使用

例如要实现下图这样的布局:

xamarin学习笔记B06(ios的Autolayout布局)_第1张图片

条件如下:

1. 有三个控件,图片控件UIImageView,文本控件UILabel,和它俩的父控件灰色的UIView。

2. UIImageView的宽为150,高为150,距离UIView的左边和上边都是10。

3. UILabel的上边距离图片是7,下边距离UIView是8,左边距离UIView是10,右边距离UIView的右边是16,宽度则是跟随UIView的宽度自动变化,高度则跟随文本内容自动变化。

4. UIView距离屏幕的左和右都是20,宽度跟随屏幕宽度自动变化,高度则跟随它里面的子控件的高度自动变化,即刚好包住它们。距离屏幕上边暂时随变吧。

1. 通过界面设计工具来布局

首先查看storyboard的属性,默认是勾选了“UseAutoLayout”的。

xamarin学习笔记B06(ios的Autolayout布局)_第2张图片


还得注意要加如下代码
//因为默认会有Autoresizing设置,所以要禁止IOS把默认的Autoresizing转成约束
            grayView.TranslatesAutoresizingMaskIntoConstraints = false;
            imageView.TranslatesAutoresizingMaskIntoConstraints = false;
            label.TranslatesAutoresizingMaskIntoConstraints = false;

分别拖三个控件并调好大概的位置。第一步是切换到约束编辑模式,下图少了一个“模”字。第二步则进行相关拖线来设置约束。第三步在Layout栏可看到结果,可以点击设置图标来进行修改或删除约束。

xamarin学习笔记B06(ios的Autolayout布局)_第3张图片


在使用下面三个方式之前先做好准备工作,通过代码先添加好三个控件

//1.添加灰色View
            UIView grayView2 = new UIView();
            grayView2.BackgroundColor = UIColor.Gray;
            grayView2.Frame = new CGRect(0, 400, 300, 300);
            this.View.AddSubview(grayView2);

            //2.添加图片View
            UIImage image = UIImage.FromBundle("a1");
            UIImageView imageView2 = new UIImageView(image);
            imageView2.BackgroundColor = UIColor.Cyan;
            imageView2.Frame = new CGRect(0, 0, 150, 150);
            grayView2.AddSubview(imageView2);

            //3.添加文本View
            UILabel label2 = new UILabel();
            label2.BackgroundColor = UIColor.White;
            label2.Frame = new CGRect(5, imageView2.Frame.Size.Height + 7, 200, 20);
            label2.Text = "BookName";
            label2.Font = UIFont.SystemFontOfSize(UIFont.LabelFontSize, UIFontWeight.Bold);
            label2.Lines = 0;//设置允许自动换行
            grayView2.AddSubview(label2);
            _label2 = label2; 

//默认会有Autoresizing设置,禁止IOS把默认的Autoresizing转成约束
            grayView2.TranslatesAutoresizingMaskIntoConstraints = false;
            imageView2.TranslatesAutoresizingMaskIntoConstraints = false;
            label2.TranslatesAutoresizingMaskIntoConstraints = false;

2. 通过NSLayoutConstraint类来布局

直接上代码

//4添加grayView2的约束
            //4.1添加X值约束
            NSLayoutConstraint grayView2CT_X = NSLayoutConstraint.Create(grayView2, NSLayoutAttribute.Left, NSLayoutRelation.Equal
                                                                         , this.View, NSLayoutAttribute.Left, 1.0F, 20);
            this.View.AddConstraint(grayView2CT_X);
            //4.2添加Y值约束
            NSLayoutConstraint grayView2CT_Y = NSLayoutConstraint.Create(grayView2, NSLayoutAttribute.Top, NSLayoutRelation.Equal
                                                                         , this.View, NSLayoutAttribute.Top, 1.0F, 300);
            this.View.AddConstraint(grayView2CT_Y);
            //4.3添加Width约束(因为有X值约束了,所以再来个Trailing就行了)
            NSLayoutConstraint grayView2CT_Trailing = NSLayoutConstraint.Create(grayView2, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal
                                                                                , this.View, NSLayoutAttribute.Trailing, 1.0F, -20);
            this.View.AddConstraint(grayView2CT_Trailing);
            //4.4添加Height约束
            //不需添加高约束,因为可以根据里面的imageView和label自动计算出来


            //5.添加imageView2的约束
            //4.1添加X值约束
            NSLayoutConstraint imageView2CT_X = NSLayoutConstraint.Create(imageView2, NSLayoutAttribute.Left, NSLayoutRelation.Equal
                                                                        , imageView2.Superview, NSLayoutAttribute.Left, 1.0F, 10);
            grayView2.AddConstraint(imageView2CT_X);
            //5.2添加Y值约束
            NSLayoutConstraint imageView2CT_Y = NSLayoutConstraint.Create(imageView2, NSLayoutAttribute.Top, NSLayoutRelation.Equal
                                                                          , imageView2.Superview, NSLayoutAttribute.Top, 1.0F, 10);
            grayView2.AddConstraint(imageView2CT_Y);
            //5.3添加Width约束
            NSLayoutConstraint imageView2CT_W = NSLayoutConstraint.Create(imageView2, NSLayoutAttribute.Width, NSLayoutRelation.Equal
                                                                          , null, NSLayoutAttribute.NoAttribute, 1.0F, 150);
            imageView2.AddConstraint(imageView2CT_W);
            //5.4添加Height约束
            NSLayoutConstraint imageView2CT_H = NSLayoutConstraint.Create(imageView2, NSLayoutAttribute.Height, NSLayoutRelation.Equal
                                                                          , null, NSLayoutAttribute.NoAttribute, 1.0F, 150);
            imageView2.AddConstraint(imageView2CT_H);


            //6.添加label2的约束
            //6.1添加X值约束
            NSLayoutConstraint label2CT_X = NSLayoutConstraint.Create(label2, NSLayoutAttribute.Left, NSLayoutRelation.Equal
                                                                      , label2.Superview, NSLayoutAttribute.Left, 1.0F, 10);
            grayView2.AddConstraint(label2CT_X);
            //6.2添加Y值约束
            NSLayoutConstraint label2CT_Y = NSLayoutConstraint.Create(label2, NSLayoutAttribute.Top, NSLayoutRelation.Equal
                                                                      , imageView2, NSLayoutAttribute.Bottom, 1.0F, 7);
            grayView2.AddConstraint(label2CT_Y);
            //6.3添加Width约束(因为有X值约束了,所以再来个Trailing就行了)
            NSLayoutConstraint label2CT_Trailing = NSLayoutConstraint.Create(label2, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal
                                                                             , label2.Superview, NSLayoutAttribute.Trailing, 1.0F, -16);
            grayView2.AddConstraint(label2CT_Trailing);
            //6.4添加Height约束所以再来个Bottom就行了(因为有Y值约束了,所以再来个Bottom就行了)
            NSLayoutConstraint label2CT_Bottom = NSLayoutConstraint.Create(label2, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal
                                                                           , label2.Superview, NSLayoutAttribute.Bottom, 1.0F, -8);
            grayView2.AddConstraint(label2CT_Bottom);


3. 通过VFL(VisualFormatLanguage可视化格式语言)来布局

直接上代码。

NSDictionary viewDict = NSDictionary.FromObjectsAndKeys(new UIView[] { grayView2, imageView2, label2 },
                                                                   new string[] { "grayView", "imageView", "label" }); 
            string grayView2VFL_H = "H:|-20-[grayView]-20-|";//距父控件左边和右边都是20(X值和With值也就确定了)
            string grayView2VFL_V = "V:|-350-[grayView]";  //距父控件上边是350,下边自动计算(Y值和Height值也就确定了)
            NSLayoutConstraint[] grayView2VFLArray_H=NSLayoutConstraint.FromVisualFormat(grayView2VFL_H, 0
                                                                                         , null, viewDict);
            NSLayoutConstraint[] grayView2VFLArray_V =NSLayoutConstraint.FromVisualFormat(grayView2VFL_V,0
                                                                                          ,null, viewDict);
            this.View.AddConstraints(grayView2VFLArray_H);
            this.View.AddConstraints(grayView2VFLArray_V);


            string imageView2VFL_H = "H:|-10-[imageView(150)]";//距父控件左边为10,自已宽为150(X值和With值也就确定了)
            string imageView2VFL_V = "V:|-10-[imageView(150)]";//距父控件上边是10,自已高为150(Y值和Height值也就确定了)
            NSLayoutConstraint[] imageView2VFLArray_H =NSLayoutConstraint.FromVisualFormat(imageView2VFL_H, 0
                                                                                         , null, viewDict);
            NSLayoutConstraint[] imageView2VFLArray_V =NSLayoutConstraint.FromVisualFormat(imageView2VFL_V, 0
                                                                                         , null, viewDict);
            imageView2.Superview.AddConstraints(imageView2VFLArray_H);
            imageView2.Superview.AddConstraints(imageView2VFLArray_V);


            string label2VFL_H = "H:|-10-[label]-16-|";//距父控件左边为10,右边为16(X值和With值也就确定了)
            string label2VFL_V = "V:[imageView]-7-[label]-8-|";//距上边(imageView)是7,下边(grayView)是8(Y值和Height值也就确定了)
            NSLayoutConstraint[] label2VFLArray_H =NSLayoutConstraint.FromVisualFormat(label2VFL_H, 0
                                                                                         , null, viewDict);
            NSLayoutConstraint[] label2VFLArray_V =NSLayoutConstraint.FromVisualFormat(label2VFL_V, 0
                                                                                         , null, viewDict);
            label2.Superview.AddConstraints(label2VFLArray_H);
            label2.Superview.AddConstraints(label2VFLArray_V);



4. 通过第三方开源框架Masonry来布局

从Nuget中下载安装Masonry这个包。

grayView2.MakeConstraints((ConstraintMaker obj) => {
                obj.Left.EqualTo(this.View.Left()).Offset(20);
                obj.Right.EqualTo(this.View.Right()).Offset(-20);
                obj.Top.EqualTo(this.View.Top()).Offset(350);
            });

            imageView2.MakeConstraints((ConstraintMaker obj) => {
                obj.Left.EqualTo(imageView2.Superview.Left()).Offset(10);
                obj.Width.EqualTo(new NSNumber(150));
                obj.Top.EqualTo(imageView2.Superview.Top()).Offset(10);
                obj.Height.EqualTo(new NSNumber(150));
            });

            label2.MakeConstraints((ConstraintMaker obj) =>{
                obj.Left.EqualTo(label2.Superview.Left()).Offset(10);
                obj.Right.EqualTo(label2.Superview.Right()).Offset(-16);
                obj.Top.EqualTo(imageView2.Bottom()).Offset(7);
                obj.Bottom.EqualTo(label2.Superview.Bottom()).Offset(-8);
            }); 


注意,最后记得注掉这三个控件的Frame代码。


Autolayout的约束的优先级

约束可以设置优先级,优先级高的生效。

例如有三个UIView,它们之间的水平间距都是10,当删掉中间青色的视图后,红色要自动贴到橙色的右边来且间距还是10。

xamarin学习笔记B06(ios的Autolayout布局)_第4张图片

上代码

//约束优先级
            UIView orangeView = new UIView();
            orangeView.BackgroundColor = UIColor.Orange;

            UIView cyanView = new UIView();
            cyanView.BackgroundColor = UIColor.Cyan;

            UIView redView = new UIView();
            redView.BackgroundColor = UIColor.Red;

            this.View.AddSubview(orangeView);
            this.View.AddSubview(cyanView);
            this.View.AddSubview(redView);
            _cyanView1 = cyanView;

            orangeView.MakeConstraints((ConstraintMaker obj) => {
                obj.Left.EqualTo(this.View.Left()).Offset(10);
                obj.Bottom.EqualTo(this.View.Bottom()).Offset(-5);
                obj.Width.EqualTo(new NSNumber(100));
                obj.Height.EqualTo(new NSNumber(100));
            });
            cyanView.MakeConstraints((ConstraintMaker obj) => {
                obj.Left.EqualTo(orangeView.Right()).Offset(10).Priority(260);
                obj.Bottom.EqualTo(this.View.Bottom()).Offset(-5);
                obj.Width.EqualTo(new NSNumber(100));
                obj.Height.EqualTo(new NSNumber(100));
            });
            redView.MakeConstraints((ConstraintMaker obj) => {
                obj.Left.EqualTo(cyanView.Right()).Offset(10);
                obj.Bottom.EqualTo(this.View.Bottom()).Offset(-5);
                obj.Width.EqualTo(new NSNumber(100));
                obj.Height.EqualTo(new NSNumber(100));
                obj.Left.EqualTo(orangeView.Right()).Offset(10).Priority(250);
            }); 
public override void TouchesBegan(Foundation.NSSet touches, UIEvent evt)
        {
            base.TouchesBegan(touches, evt);
            //label.Text = "BookNameBookNameBookNameBookNameBookNameBookNameBookNameBookName";
            //_label2.Text = "BookNameBookNameBookNameBookNameBookNameBookNameBookNameBookName";
            _cyanView1.RemoveFromSuperview();
        } 

注意cyanView的Left约束的优先级

 obj.Left.EqualTo(orangeView.Right()).Offset(10).Priority(260);

和redView的Left约束的优先级

obj.Left.EqualTo(orangeView.Right()).Offset(10).Priority(250);

由于redView的优先级250低于cyanView的优先级260,所以开始显示出来不会生效,当删掉cyanView后,cyanView的约束也没了,所以redView约束中的第一句就失效了并且最后一句的就生效了。

结果如下图

xamarin学习笔记B06(ios的Autolayout布局)_第5张图片


代码和视频在我上传的CSDN资源中 http://download.csdn.net/download/junshangshui/10151330

你可能感兴趣的:(xamarin)