iOS AutoLayout-get frame size width

Rozwijam się przy użyciu układu automatycznego iOS 6

Chciałbym zarejestrować komunikat wyświetlający szerokość ramki widoku.

Widzę widok tekstu na ekranie.

Ale dostaję szerokość i wysokość jako zero, czy coś mi umyka ?

NSLog(@"textView    = %p", self.textView);
NSLog(@"height      = %f", self.textView.frame.size.height);
NSLog(@"width       = %f", self.textView.frame.size.width);

textView    = 0x882de00
height      = 0.000000
width       = 0.000000
Author: user1046037, 2012-09-21

9 answers

Myślę, że auto layout nie miał czasu, aby układać swoje widoki do czasu, gdy to nazywasz. Automatyczny układ nie wystąpił przed wywołaniem viewDidLoad, ponieważ jest wywoływany zaraz po załadowaniu widoków i dopiero po tym widoki są umieszczane w hierarchii widoku kontrolera widoku i ostatecznie rozkładane(w metodzie widoku layoutSubviews).

Edit: ta odpowiedź wskazuje, dlaczego scenariusz w pytaniu nie działa. @dreamzor ' s answer wskazuje, gdzie umieścić swój kod, aby go rozwiązać.

 56
Author: Jesper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:07

W zasadzie powyższe odpowiedzi nie są do końca poprawne. Śledziłem ich i ciągle otrzymywałem zera.

Sztuką jest umieszczenie kodu zależnego od klatek na metodzie viewDidLayoutSubviews, która

Powiadamia kontroler widoku, że jego widok właśnie rozplanował swoje podglądy.

Nie zapominaj, że ta metoda jest wywoływana wielokrotnie i nie jest częścią cyklu życia Viewcontrollera, więc bądź ostrożny podczas jej używania.

Mam nadzieję, że komuś to pomoże.

Po prostu chciałem dodać, że dla mojego programu bez trybu poziomego nie używającego Auto layoutu jest znacznie prostsze... Próbowałem, chociaż =D

 150
Author: dreamzor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-08 01:28:12

Rozwiązanie

  • Umieść ten kod w viewDidAppear

Reason

  • viewDidLoad dzieje się przed zakończeniem autolayout. Tak więc pozycja nie jest jeszcze ustawiona przez autolayout, który został określony w xib
  • viewDidAppear dzieje się po zakończeniu autolayout.
 29
Author: user1046037,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-28 03:01:09

Include in your viewDidLoad ()

self.view.setNeedsLayout()
self.view.layoutIfNeeded()

Przed uzyskaniem dostępu do yourview.rama.rozmiar.szerokość

 26
Author: diegosantiviago,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-04 15:29:24

Faktycznie udało mi się wymusić aktualizację układu przed moim kodem w viewDidLoad:

override func viewDidLoad() {
        super.viewDidLoad()

        println("bounds before \(self.previewContainer.bounds)");
        //on iPhone 6 plus -> prints bounds before (0.0,0.0,320.0,320.0)

        self.view.setNeedsLayout()
        self.view.layoutIfNeeded()

        println("bounds after \(self.previewContainer.bounds)");
        //on iPhone 6 plus -> prints bounds after (0.0,0.0,414.0,414.0)

        //Size dependent code works here
        self.create()
    }

UPDATE: to już nie działa

 13
Author: Francescu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-12 15:46:13

To naprawdę dziwna cecha. Ale znalazłem:

Jeśli chcesz uzyskać ramkę bez użycia metody layoutsubviews, Użyj tej:

dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"View frame: %@", NSStringFromCGRect(view.frame));
    });
To naprawdę dziwne!!!
 9
Author: SamSol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-29 13:02:02

Żadna z powyższych odpowiedzi nie zadziałała całkowicie dla mnie, z wyjątkiem viewDidLoad, ale to ma efekt uboczny nie wyświetlania tego, co chcę, dopóki widok nie zostanie animowany, co wygląda słabo.

viewDidLayoutSubviews powinno być właściwym miejscem do uruchomienia kodu, który polega na tym, że autolayout jest kompletny, ale jak zauważyli inni, jest wywoływany wiele razy w ostatnich wersjach iOS i nie możesz wiedzieć, które jest ostateczne wywołanie.

Więc rozwiązałem to małym hackiem. W moim storyboard, mySubview powinien być mniejszy niż jego zawierający self.view. Ale kiedy viewDidLayoutSubviews jest wywołane po raz pierwszy, mySubview nadal ma szerokość 600, podczas gdy self.view wydaje się być ustawione poprawnie (jest to projekt iPhone ' a). Więc wszystko, co muszę zrobić, to monitorować kolejne połączenia i sprawdzać względne szerokości. Gdy {[3] } jest mniejszy niż self.view, mogę być pewien, że został prawidłowo ułożony.

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if self.mySubview.bounds.size.width < self.view.bounds.size.width {

        // mySubview's width became less than the view's width, so it is
        // safe to assume it is now laid out correctly...

    }
}

Zaletą tego rozwiązania jest to, że nie polega ono na kodowanych na twardo numerach, dzięki czemu może działać na przykład na wszystkich obudowach iPhone ' a. Z oczywiście może to nie być panaceum we wszystkich przypadkach lub na wszystkich urządzeniach, ale prawdopodobnie istnieje wiele pomysłowych sposobów, aby zrobić podobne kontrole względnych rozmiarów.

I nie, nie powinniśmy tego robić, ale dopóki Apple nie da nam bardziej wiarygodnych połączeń zwrotnych, wszyscy z tym utknęliśmy.

 7
Author: Echelon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-04 20:44:46

IOS AutoLayout-get frame size width

 -(void) layoutSubviews{
        [self layoutIfNeeded];
        //right you code to set frame its will work to get frame and set frame.
        CALayer *bottomBorder = [CALayer layer];
        bottomBorder.frame = CGRectMake(0.0f, bkView.frame.size.height - 1, bkView.frame.size.width, 1.0f);
        bottomBorder.backgroundColor = [UIColor blackColor].CGColor;
        [bkView.layer addSublayer:bottomBorder];
    }
 2
Author: Ravi H Malviya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-16 11:08:28

Rozmiar można sprawdzić dopiero po pierwszym przejściu układu. Lub po prostu zadzwoń poniżej metody, a następnie po masz rzeczywistą szerokość widoku.

[yourView layoutIfNeeded];
 0
Author: Bhavesh Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-08 10:39:32