Pytanie iOS AutoLayout z Xamarinem przy użyciu TYLKO kodu C # w Visual Studio 2013, bez XCode lub konstruktora interfejsu


Zacząłem używać Xamarin, ponieważ chciałem pozostać w środowisku Visual Studio 2013 i nie muszę uczyć się nowego środowiska. W każdym razie wklejam kod mojego kontrolera poniżej i mam nadzieję, że ktoś jest mądrzejszy ode mnie (prawie pewny) i może przywrócić mnie na właściwe tory.

Właśnie odkryłem AutoLayout. Wydaje mi się, że zrozumienie AutoLayout ma kluczowe znaczenie dla przyspieszenia rozwoju. Jednak nie znajduję wiele informacji o korzystaniu z AutoLayout z czystym C # w Visual Studio 2013. Być może po prostu nie patrzę w odpowiednie miejsca.

W każdym razie Zacznijmy tę nową dyskusję od prostego kontrolera, który używa AutoLayout CAŁKOWICIE w C # bez użycia w ogóle jakichkolwiek narzędzi .nib lub Interface Builder. I bez użycia Xamarin Studio. Po prostu wszystko zrobione w Visual Studio 2013.

Oto wymagania:

  1. Stwórz kontroler UIViewController, który ułatwi implementację Apple iAD.
  2. Zasadniczo chcemy umieścić baner iAD na dole ekranu, zajmując całą szerokość.
  3. Umieścimy widok powyżej banera iAD i wypełni on resztę ekranu.
  4. Widok banerów może od czasu do czasu zniknąć, jeśli nie ma żadnych reklam, więc musimy to załatwić.
  5. Musimy postępować, gdy urządzenie obraca się, aby dostosować się do nowej orientacji.
  6. Musimy obsługiwać różne urządzenia. iPod, iPad, iPhone, wersja 4 i 5

    To powinno być trywialne, ale walczę z klawiaturą przez 2 dni, próbując to zrobić. Wszelkie zalecenia, przykłady lub pomysły byłyby WIELE POMOCNE. Pamiętaj, że chcemy TYLKO używać C # w Visual Studio i nie używać w ogóle Buildera interfejsu. Oto moja nieskuteczna próba:

Korzystając z poniższego kodu, kończę z AdBanner na ekranie poniżej InternalView. Widok wewnętrzny jest dłuższy niż ekran i tylko połowa szerokości ekranu. Co tu się dzieje? Czy muszę włączyć gdzieś funkcję AutoLayout? Czy mogę to zrobić w kodzie C # lub ukrywa gdzieś w Ustawieniach projektu?

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

10
2018-03-29 23:06


pochodzenie


Rzuć okiem na EasyLayout Franka: praeclarum.org/post/45690317491/... - Krumelur
Ponieważ Xamarin jest bardzo błędny w implementacji AutoLayout, zacząłem ręcznie układać rzeczy. Zasadniczo zaimplementuję na moim kontrolerze metodę "Resize", która zostanie wywołana, gdy zdarzy się DidRotate lub ViewDidAppear. - Curtis


Odpowiedzi:


Ręczne tworzenie ograniczeń w kodzie do automatycznego wylogowywania z wyeksponowanymi metodami iOS to nudny proces.

AutoLayout ma wiele zalet, a używanie go do osiągania takich rzeczy, jak zmiany orientacji i ogólny układ, jest niczym nieskrępowanym. Aby osiągnąć to, czego potrzebujesz, wystarczy VS2013, chciałbym zasugerować spojrzenie

FluentLayouts

Został stworzony przez autora, który stworzył MVVMCross i ma sporo dokumentacji, aby zacząć.

Post na blogu

Youtube Vid Tutorial

Zasadniczo za jego pomocą można pisać ograniczenia, takie jak:

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

A więc w twoim przypadku

na pewno chcesz, aby widok banera reklamowego był przypięty do góry superwizsu za pomocą pinezek z lewej i prawej strony widoku. Prolly dodaj stałą wysokość, jeśli potrzebujesz. Przypinanie z lewej i prawej strony podglądu będzie wtedy uwzględniać zmiany orientacji urządzenia i odpowiednio skalować szerokość. Górna pozycja będzie pokryta górną szpilką i stałą wysokością dla wysokości banera.

AutoLayout sam poprosi o pozycję X, Y elementu i aby element poznał pożądany rozmiar. Niektóre elementy sterujące, takie jak przyciski, mają domyślny rozmiar, więc nie trzeba ustawiać jawnie tej szerokości / wysokości. Jednak rzeczy takie jak zwykły UIView nie. Więc musisz określić ich rozmiar z ograniczeniami.

W końcu posiadanie takiego narzędzia jak FluentLayouts pomaga nam tworzyć ograniczenia o wiele łatwiejsze, ale podstawą tego, czym jest AutoLayouts i jak z niego korzystać, jest ogólna wiedza na ten temat, który może być lepszy dla osób, które odwiedzają Apple Docs lub niektóre tutoriale takie jak te. Tak, pokazuje to w XCode, ale wyjaśnia również temat, który musimy zrozumieć niezależnie. Ta strona zawiera także artykuły o ograniczeniach z kodu, które wyjaśniają zasadnicze wartości stałe i mnożniki oraz sortowania z ograniczeniami, które warto przeczytać. Kiedy zrozumiesz pojęcia i co możesz z nimi zrobić, wybierz narzędzie, takie jak płynne układy, a twoje wymagania powinny znaleźć się na właściwym miejscu.


8
2018-03-31 10:12



Muszę użyć dwóch kontrolek na tym samym szczycie i sąsiadujących ze sobą. 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), ale obie kontrolki są ze sobą powiązane w tej samej pozycji. Czego mi brakuje? - Ajay Sharma


Frank Krueger ma eleganckie rozwiązanie tego problemu, o którym można przeczytać tutaj: http://praeclarum.org/post/45690317491/easy-layout-a-dsl-for-nslayoutconstraint. Kod jest dostępny tutaj: https://gist.github.com/praeclarum/5175100

Po prostu dodaj klasę do projektu iOS i możesz napisać kod:

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

4
2017-08-21 00:49





Zauważyłem, że poniższe działa całkiem dobrze dla prostego kontrolera, który wyświetla AdBannerView iAd wraz ze zwykłym widokiem. Poniższy kod wywołuje również metodę "Zmień rozmiar" dla wszystkich subskrybentów typu "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());
        }
    }

0
2018-04-10 19:31