iOS AutoLayout con Xamarin que usa UNICAMENTE el código C # en Visual Studio 2013, sin XCode o el Generador de interfaces

Comencé a usar Xamarin porque quería quedarme en el entorno de Visual Studio 2013 y no tener que aprender un nuevo entorno. De todos modos, voy a pegar el código de mi controller a continuación y ojalá que alguien sea más inteligente que yo (casi seguro) y pueda volver a encarrilarme.

Acabo de descubrir AutoLayout. Me parece que la comprensión de AutoLayout es fundamental para acelerar el desarrollo. Sin embargo, no estoy encontrando mucha información para usar AutoLayout con C # puro en Visual Studio 2013. Quizás no estoy buscando en los lugares correctos.

De todos modos, comencemos esta nueva discusión con un controller simple que use AutoLayout TOTALMENTE en C # sin utilizar ninguna característica de .nib o Interface Builder. Y sin usar Xamarin Studio. Simplemente TODO hecho en Visual Studio 2013.

Estos son los requisitos:

  1. Haga un UIViewController que facilite la implementación del iAD de Apple.
  2. Básicamente, queremos colocar un banner iAD en la parte inferior de la pantalla ocupando todo el ancho.
  3. Pondremos la vista encima de la pancarta iAD y hacer que llene el rest de la pantalla.
  4. La vista del banner puede desaparecer de vez en cuando si no hay AD presentes, por lo que debemos manejarlo.
  5. Necesitamos manejar cuando el dispositivo gira para acomodar una nueva orientación.
  6. Necesitamos manejar diferentes dispositivos. iPod, iPad, iPhone, versión 4 y 5

    Esto debería ser trivial, pero he estado golpeando mi cabeza en el keyboard durante 2 días tratando de hacer que esto funcione. Cualquier recomendación, ejemplo o idea sería GRANDEMENTE ÚTIL. Recuerde, queremos SOLO usar C # en Visual Studio y no usar Interface Builder en absoluto. Aquí está mi bash no laborable:

Usando el código a continuación, termino con el AdBanner fuera de la pantalla debajo de InternalView. Además, la vista interna es más larga que la pantalla y solo la mitad del ancho de la pantalla. ¿Que está pasando aqui? ¿Necesito encender la function AutoLayout en alguna parte? ¿Puedo hacerlo en código C # o se esconde en alguna parte de la configuration del proyecto?

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(); } } } 

Crear restricciones en el código para AutoLayout manualmente con methods iOS expuestos es un process tedioso .

AutoLayout tiene muchos beneficios y usarlo para lograr cosas como cambios de orientación y layout general es un poco obvio. Para lograr lo que necesita solo con VS2013, sugiero echar un vistazo a

FluentLayouts

Está hecho por el autor que creó MVVMCross y tiene bastante documentation para comenzar.

Entrada en el blog

Tutorial de YouTube Vid

Esencialmente con esto puedes escribir restricciones como:

 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) ); 

Entonces, para tu caso,

usted querrá tener la vista del banner publicitario fijada en la parte superior de la vista de supervisión con pines para la izquierda y la derecha de la vista de supervisión también. Prolly agrega una altura fija si es necesario. Fijar a la izquierda y la derecha de la supervisión supervisa cuando la orientación del dispositivo cambia y escala el ancho en consecuencia. La position superior se cubriría con el alfiler superior y la altura fija para la altura de la pancarta.

AutoLayout por sí mismo le pide la position X, Y de un elemento y que el elemento sepa que es el tamaño deseado. Algunos controles, como botones, tienen un tamaño implícito, por lo que no es necesario que establezca explícitamente este ancho / alto. Sin embargo, cosas como una llanura UIView no. Por lo tanto, debería especificar su tamaño también con restricciones.

Finalmente tener una herramienta como FluentLayouts nos ayuda a crear restricciones mucho más fáciles , pero los fundamentos de lo que AutoLayouts es y cómo usarlo son los conocimientos generales sobre el tema, en los que es mejor que visite los documentos de Apple o algunos tutoriales como este . Sí, lo muestra en XCode pero también explica el tema que debemos entender independientemente. Ese sitio también tiene artículos sobre restricciones del código que explica el arenoso asunto sobre constantes y multiplicadores y clasificaciones con restricciones que valen la pena leer. Una vez que entienda los conceptos y lo que puede hacer con él, elija una herramienta como layouts fluidos y sus requisitos deberían quedar bien en su lugar.

Frank Krueger tiene una solución elegante a este problema que puede leer aquí: http://praeclarum.org/post/45690317491/easy-layout-a-dsl-for-slayoutconstraint . El código está disponible aquí: https://gist.github.com/praeclarum/5175100

Simplemente agregue la class a su proyecto de iOS y puede escribir un código como este:

 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 ); } 

Encontré que lo siguiente funciona bastante bien para un controller simple que está mostrando una iAd AdBannerView junto con una vista normal. El código a continuación también llama al método 'Resize' para todas las subvenciones que son de tipo 'AdView'

  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()); } }