2014-03-29 14 views
10

我開始使用Xamarin,因爲我想留在Visual Studio 2013環境中,而不必學習新的環境。無論如何,我會在下面粘貼我的控制器的代碼,希望有人比我更聰明(幾乎可以肯定),並且可以讓我回到正軌。iOS自動佈局Xamarin僅使用Visual Studio 2013中的C#代碼,無XCode或Interface Builder

我剛發現AutoLayout。在我看來,AutoLayout的理解對加速開發至關重要。但是,我沒有在Visual Studio 2013中使用純C#使用AutoLayout的許多信息。也許我只是沒有在正確的位置尋找。

無論如何,讓我們用一個簡單的控制器開始這個新的討論,該控制器完全在C#中使用AutoLayout,根本不使用任何.nib或Interface Builder的東西。而不使用Xamarin Studio。在Visual Studio 2013年

這裏只是做了所有的要求是:

  1. 做一個UIViewController,這將有助於實現蘋果的iAd的。
  2. 基本上,我們希望在屏幕底部放置一個iAD橫幅,佔據全寬。
  3. 我們將把視圖放在iAD橫幅的上方,讓它填充屏幕的其餘部分。
  4. 如果沒有AD存在,橫幅視圖可能會不時消失,因此我們需要處理該問題。
  5. 當設備旋轉以適應新的方向時,我們需要處理。
  6. 我們需要處理不同的設備。 iPod,iPad,iPhone,版本4和5

    這應該是微不足道的,但我一直在鍵盤上敲我的頭2天試圖讓這個工作。任何建議,例子或想法都會非常有幫助。請記住,我們只想在Visual Studio中使用C#而不使用Interface Builder。這是我的非工作嘗試:

使用下面的代碼,我結束AdBanner在屏幕下面的InternalView。此外,內部視圖比屏幕更長,只有屏幕寬度的一半。這裏發生了什麼?我需要在某處打開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(); 
     } 
    } 
} 
+2

看一看弗蘭克的EasyLayout:http://praeclarum.org/post/ 45690317491/easy-layout-a-dsl-for-nslayoutconstraint – Krumelur

+0

由於Xamarin實際上是AutoLayout的實現,所以我已經開始手動佈局了。我基本上在我的控制器上實現了一個'Resize'方法,當DidRotate或ViewDidAppear發生時被調用。 – Curtis

回答

8

在創建代碼約束的自動版式手動帶有外露的iOS方法是繁瑣的過程

AutoLayout有很多好處,並使用它來實現諸如方向更改和總體佈局之類的東西,這是一件不費腦筋的事情。要達到什麼樣的要求,你只用VS2013,我建議在

FluentLayouts

它是由創建MVVMCross筆者製成,它有相當一些文件,讓你開始在看看。

Blog Post

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

所以對於你的情況,

你prolly希望有廣告橫幅視圖固定到超視圖的頂部,還有超視圖左右的引腳。如果需要,可以增加一個固定的高度。然後固定在超視圖的左側和右側將迎合設備方向變化並相應地縮放寬度。頂部位置將會迎合頂部針腳和橫幅高度的固定高度。

AutoLayout本身要求您提供元素的X,Y位置,並讓元素知道所需的尺寸。像按鈕這樣的一些控件有一個隱含的大小,所以你不需要明確地設置這個寬度/高度。然而像普通的UIView這樣的東西沒有。所以你也必須用約束來指定它們的大小。

最後有像FluentLayouts的工具將幫助我們建立約束非常非常容易,但自動版式是什麼基本面以及如何使用它只是在主題的一般知識,你實際上可能會更好訪問蘋果文檔的或者一些教程,如these。是的,它在XCode中顯示它,但它也解釋了我們需要理解的主題。該網站還有一些關於代碼限制的文章,它們解釋了常量和乘數的基本內容,並且對那些值得一讀的約束進行分類。一旦你理解了概念以及你可以用它做什麼,然後選擇一個像流利佈局的工具,你的需求應該很好地落實到位。

+0

我需要在相同的頂部和相鄰的兩個控件。 lblShowPassword.Below(txtfldPwd,2 * lrMargin) lblShowPassword.WithSameLeft(segmentControl) lblShowPassword.ToLeftOf(switchShowPassword,4 * lrMargin) lblShowPassword.Height()。GreaterThanOrEqualTo(2 * lrMargin) switchShowPassword.WithSameTop (lblShowPassword), switchShowPassword.AtRightOf(lblShowPassword,4 * lrMargin), 但是兩個控件在相同的位置上彼此重疊。 我在這裏錯過了什麼? –

0

我發現以下工作非常適合顯示iAd AdBannerView和普通視圖的簡單控制器。下面的代碼還呼籲那些類型的「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()); 
     } 
    } 
4

弗蘭克·克魯格有一個優雅的解決這個問題,你可以讀到這裏的所有子視圖「調整大小」的方法: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 
    ); 
} 
相關問題