我开始使用Xamarin是因为我想留在Visual Studio 2013环境中,而不必学习新的环境。无论如何,我将把我的控制器代码粘贴在下面,希望有人比我更聪明(这几乎是肯定的),可以让我回到正轨。
我刚刚发现自动布局。在我看来,理解自动布局对于加快开发至关重要。然而,我没有找到很多关于在Visual Studio 2013中使用纯c#的自动布局的信息。也许我只是没有找对地方。
无论如何,让我们从一个简单的控制器开始这个新的讨论,它完全使用c#中的自动布局,而不使用任何。nib或接口生成器的东西。而且不使用Xamarin Studio。在Visual Studio 2013中完成。要求如下:
制作一个UIViewController,这将有助于实现苹果的iAD。
基本上,我们想在屏幕底部放置一个iAD横幅,占用整个宽度。
我们将把视图放在iAD横幅上方,并让它填充屏幕的其余部分。
如果没有ADs存在,横幅视图可能会不时消失,所以我们需要处理这个问题。
我们需要处理当设备旋转以适应新的方向
我们需要处理不同的设备。iPod, iPad, iPhone,版本4和5
这应该是微不足道的,但我已经在键盘上敲了2天试图让它工作。任何建议、例子或想法都将大有帮助。记住,我们只想在Visual Studio中使用c#,而不是使用Interface Builder。这是我的非工作尝试:
使用下面的代码,我结束了在InternalView下面的屏幕上的AdBanner。此外,内部视图比屏幕长,只有屏幕宽度的一半。这是怎么回事?我需要在某个地方打开自动布局功能吗?我可以做它在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();
}
}
}
在代码中使用暴露的iOS方法手动为autollayout创建约束是一个繁琐的过程。
AutoLayout有很多好处,用它来实现像方向改变和一般布局这样的东西是很容易的。要在VS2013中实现所需的功能,我建议查看
FluentLayouts
它是由创建MVVMCross的作者制作的,它有相当多的文档可以帮助您入门。
博文Youtube Vid Tutorial
基本上你可以用它来写约束:
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)
);
对于你的情况,
你肯定想把广告横幅视图固定在父视图的顶部,父视图的左边和右边也要固定。如果需要,请添加一个固定的高度。固定在父视图的左右会在设备方向改变时适应,并相应地缩放宽度。顶部位置将与顶部别针和固定高度的横幅高度相匹配。
AutoLayout本身会询问元素的X,Y位置,并让元素知道它想要的大小。有些控件(如按钮)具有隐式大小,因此您不需要显式设置此宽度/高度。然而,像普通的UIView
这样的东西就不会。所以你也必须用约束来指定它们的大小。
最后有一个像FluentLayouts这样的工具可以帮助我们更容易地创建约束,但是什么是自动布局的基本原理以及如何使用它只是关于这个主题的一般知识,你可能最好访问苹果文档或一些类似的教程。是的,它显示在XCode中,但它也解释了我们需要理解的主题。该网站还有一些关于代码约束的文章,解释了常量和乘数的细节,并使用约束进行排序,值得一读。一旦你理解了概念和你可以用它做什么,然后选择像流畅布局这样的工具,你的需求就会很好地落实。
Frank Krueger对这个问题有一个优雅的解决方案,您可以在这里阅读:http://praeclarum.org/post/45690317491/easy-layout-a-dsl-for-nslayoutconstraint。代码可在这里获得:https://gist.github.com/praeclarum/5175100
把这个类添加到你的iOS项目中,你可以这样写代码:
void LayoutWithEase ()
{
View.ConstrainLayout (() =>
button.Frame.Width == ButtonWidth &&
button.Frame.Right == View.Frame.Right - HPadding &&
button.Frame.Top == View.Frame.Top + VPadding &&
text.Frame.Left == View.Frame.Left + HPadding &&
text.Frame.Right == button.Frame.Left - HPadding &&
text.Frame.Top == button.Frame.Top
);
}
我发现下面的代码对于一个显示iAd AdBannerView和常规视图的简单控制器来说非常有效。下面的代码还为所有类型为'AdView'的子视图调用'Resize'方法
public override void DidRotate(UIInterfaceOrientation fromInterfaceOrientation)
{
Resize();
base.DidRotate(fromInterfaceOrientation);
}
public override void ViewDidAppear(bool animated)
{
Resize();
base.ViewDidAppear(animated);
}
private void Resize()
{
try
{
if (AdBannerView.Hidden)
{
InternalView.Frame = new RectangleF(0, 20, View.Bounds.Width, View.Bounds.Height);
InternalView.Frame = new RectangleF(0, 20, View.Bounds.Width, View.Bounds.Height);
}
else
{
InternalView.Frame = new RectangleF(0, 20, View.Bounds.Width,
View.Bounds.Height - AdBannerView.Bounds.Height);
AdBannerView.Frame = new RectangleF(0, InternalView.Bounds.Height, View.Bounds.Width,
AdBannerView.Bounds.Height);
InternalView.Frame = new RectangleF(0, 20, View.Bounds.Width,
View.Bounds.Height - AdBannerView.Bounds.Height);
AdBannerView.Frame = new RectangleF(0, InternalView.Bounds.Height, View.Bounds.Width,
AdBannerView.Bounds.Height);
}
foreach (UIView view in View.Subviews)
{
var adView = view as AdView;
if (adView != null)
{
adView.Resize();
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}