使用Xamarin的iOS AutoLayout在Visual Studio 2013中仅使用C#代码,没有XCode或Interface Builder

Cur*_*tis 10 xamarin.ios ios autolayout xamarin visual-studio-2013

我开始使用Xamarin是因为我想留在Visual Studio 2013环境中而不必学习新的环境.无论如何,我打算在下面粘贴我的控制器代码,希望有人比我聪明(几乎可以肯定)并且可以让我回到正轨.

我刚刚发现了AutoLayout.在我看来,AutoLayout理解对于加速开发至关重要.但是,在Visual Studio 2013中,我没有找到很多关于在纯C#中使用AutoLayout的信息.也许我只是在寻找合适的地方.

无论如何,让我们用一个简单的控制器开始这个新讨论,该控制器在C#中使用AutoLayout TOTALLY,而根本不使用任何.nib或Interface Builder的东西.而且不使用Xamarin Studio.只需在Visual Studio 2013中完成所有操作.

以下是要求:

  1. 创建一个UIViewController,以便于实现apple的iAD.
  2. 基本上,我们希望在屏幕底部放置一个iAD横幅占据整个宽度.
  3. 我们将视图放在iAD横幅上方,并将其填充到屏幕的其余部分.
  4. 如果没有AD,横幅视图可能会不时消失,因此我们需要处理.
  5. 我们需要处理设备何时旋转以适应新的方向.
  6. 我们需要处理不同的设备.iPod,iPad,iPhone,版本4和5

    这应该是微不足道的,但是我已经在键盘上敲了两天试图让它工作.任何建议,示例或想法都会非常有用.请记住,我们只想在Visual Studio中使用C#而根本不使用Interface Builder.这是我的非工作尝试:

使用下面的代码,我最终在内部视图下方的屏幕上显示AdBanner.此外,内部视图比屏幕长,只有屏幕宽度的一半.这里发生了什么?我是否需要在某处启用AutoLayout功能?我可以在C#代码中执行此操作还是隐藏在项目设置中的某处?

using System;
using MonoTouch.iAd;
using MonoTouch.UIKit;

namespace ADayBDayiOS
{
    public class ADViewController : UIViewController
    {
        private UIView InternalView { get; set; }
        private ADBannerView AdView { get; set; }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            InternalView = new UIView{BackgroundColor=UIColor.Blue}; 

            //This is apple's standard ADBannerView
            AdView = new ADBannerView(ADAdType.Banner) {Hidden = true};
            AdView.FailedToReceiveAd += HandleFailedToReceiveAd;
            AdView.AdLoaded += HandleAdLoaded;

            View.BackgroundColor = UIColor.Clear;

            //I'm pretty sure that we need these three lines
            View.TranslatesAutoresizingMaskIntoConstraints = false;
            InternalView.TranslatesAutoresizingMaskIntoConstraints = false;
            AdView.TranslatesAutoresizingMaskIntoConstraints = false;

            View.AddSubview(InternalView);
            View.AddSubview(AdView);

            Resize();
        }

        public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
        {
            base.DidRotate(fromInterfaceOrientation);
            Resize();
        }

        public override void ViewDidAppear(bool animated)
        {
            base.ViewDidAppear(animated);
            Resize();
        }

        private void Resize()
        {
            //Remove all constraints, and reset them...
            View.RemoveConstraints(View.Constraints);

            if (AdView == null || AdView.Hidden)
            {//Fill up the entire screen with our InternalView
                View.AddConstraint(NSLayoutConstraint.Create(InternalView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 1, 0));
                View.AddConstraint(NSLayoutConstraint.Create(InternalView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, View, NSLayoutAttribute.Bottom, 1, 0));
                View.AddConstraint(NSLayoutConstraint.Create(InternalView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, View, NSLayoutAttribute.Top, 1, 0));
            }
            else
            {//Put banner ad at the bottom of the screen and fill the rest of the screen with our InternalView
                View.AddConstraint(NSLayoutConstraint.Create(AdView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 1, 0));
                View.AddConstraint(NSLayoutConstraint.Create(InternalView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 1, 0));

                View.AddConstraint(NSLayoutConstraint.Create(AdView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, View, NSLayoutAttribute.Bottom, 1, 0));
                View.AddConstraint(NSLayoutConstraint.Create(InternalView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, View, NSLayoutAttribute.Bottom, 1, AdView.Bounds.Height));
                View.AddConstraint(NSLayoutConstraint.Create(InternalView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, View, NSLayoutAttribute.Top, 1, 0));
            }
        }

        /// <summary>
        /// Shows the AdView when a new Ad loads
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void HandleAdLoaded(object sender, EventArgs e)
        {
            if (AdView == null)
                return;
            AdView.Hidden = false;
            Resize();
        }

        /// <summary>
        /// Hides the AdView when no ads are available
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void HandleFailedToReceiveAd(object sender, AdErrorEventArgs e)
        {
            if (AdView == null)
                return;
            AdView.Hidden = true;
            Resize();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Viv*_*Viv 8

使用公开的iOS方法手动为AutoLayout创建约束是一个繁琐的过程.

AutoLayout有很多好处,并使用它来实现方向更改和一般布局之类的东西是有点不用脑子的.为了达到你所需要的VS2013,我建议看看

FluentLayouts

它是由创建MVVMCross的作者制作的,它有相当多的文档可以帮助您入门.

博客文章

Youtube Vid教程

从本质上讲,您可以编写如下约束:

View.AddConstraints(
  button.AtTopOf(View).Plus(vPadding),
  button.AtRightOf(View).Minus(hPadding),
  button.Width().EqualTo(ButtonWidth),

  text.AtLeftOf(View, hPadding),
  text.ToLeftOf(button, hPadding),
  text.WithSameTop(button)
);
Run Code Online (Sandbox Code Playgroud)

所以对于你的情况,

你会非常希望将广告横幅视图固定在超级视图的顶部,并使用超级视图左右两侧的引脚.如果需要,Prolly添加固定高度.固定在超视图的左侧和右侧将适应设备方向的变化并相应地缩放宽度.顶部位置将与顶部销钉和横幅高度的固定高度相匹配.

AutoLayout本身会询问您元​​素的X,Y位置以及元素是否知道所需的大小.某些控件(如按钮)具有隐式大小,因此您无需显式设置此宽度/高度.然而像平原UIView这样的事情却没有.所以你必须用约束来指定它们的大小.

最后,具有类似于FluentLayouts的工具将帮助我们建立约束太多容易得多,但基本面是什么自动版式,以及如何使用它的话题只是一般的知识,你实际上可能会更好来访的苹果文档或一些教程喜欢这些.是的它在XCode中显示它,但它也解释了我们需要理解的主题.该网站还有关于代码约束的文章,这些文章解释了关于常量和乘数的细节,以及具有值得阅读的约束的排序.一旦你理解了概念以及你可以用它做什么,那么选择一个像流畅布局的工具,你的要求应该很好地落实到位.