jak używać UIScrollView w programie Interface Builder?

95

Chociaż UIScrollVieww przeszłości z powodzeniem korzystałem z niego, manipulując nim programowo, mam problem z uruchomieniem go, konfigurując go wyłącznie w Interface Builder.

Mam prostą stronę „informacje” w mojej aplikacji na iPhone'a. Ma UITextViewkilka ikon i łącza do innych moich aplikacji. Dodałem wszystkie te widoki do mojego UIScrollView, układając je tak, aby ich łączny rozmiar wynosił> 480. Kiedy uruchamiam moją aplikację, widok przewijania wyświetla tylko zawartość, która mieści się na ekranie i nic się nie przewija.

Czy można to zrobić całkowicie przez IB, czy też muszę manipulować contentSize za pomocą kodu?

George Armhold
źródło

Odpowiedzi:

130

Zapomniałeś ustawić właściwość contentSize UIScrollView. O dziwo nie możesz tego zrobić z Interface Builder. Będziesz musiał to zrobić z kontrolera widoku zarządzającego tym widokiem przewijania.

Stefan Arentz
źródło
42
Wow, trochę sprawia, że ​​IB jest raczej bezcelowe ... To załatwiło sprawę, dzięki.
George Armhold,
20
Można utworzyć podklasę UIScrollvView, która sprawdza, czy jest tylko jeden widok podrzędny w (0,0), a następnie automatycznie ustawia contentSize na podstawie tego widoku podrzędnego.
Stefan Arentz,
1
To najlepsza rada, jaką otrzymałem od jakiegoś czasu. Nie mogłem dowiedzieć się, dlaczego mój widok przewijania nie działa, i nie znalazłem informacji o rozmiarze contentSize nigdzie indziej. Dzięki.
Drew C
46
Próbowałem dowiedzieć się, jak ustawić contentSize w Interface Builder i znalazłem tę dyskusję. Przynajmniej dla mnie, w Xcode 4.5, mogę ustawić to za pomocą „User Defined Runtime Attributes”, dodając wpis o nazwie contentSizetype Sizei ustawiając żądaną wartość.
nlogax
5
Wciąż jestem zaskoczony tym, dlaczego iOS nie ustawia automatycznie widoku contentSizeprzewijania na podstawie wymiarów jego podglądów podrzędnych , przynajmniej jako zachowanie domyślne.
aroth
113

Odpowiedź Boby_Wana dała mi do myślenia i znalazłem następujące rozwiązanie do skonfigurowania contentSize UIScrollView z Interface Builder:

  1. Wybierz UIScrollVieww scenie Storyboard
  2. Przejdź do Inspektora tożsamości , utwórz nowy atrybut wykonawczy zdefiniowany przez użytkownika (kliknij przycisk +)
  3. Zmień atrybut Key Path nacontentSize
  4. Zmień typ atrybutu naSize
  5. Teraz ustaw wartość na { pożądana szerokość treści , żądana wysokość treści }

np. ustawienie wartości na {320, 920} pozwoli użytkownikowi przewinąć w dół cały dodatkowy ekran na iPhonie.

(Używam xcode 4.3.3, docelowy cel wdrożenia systemu iOS w projekcie to 5.1)

Kiedy wykonałem to po raz pierwszy, otrzymałem następujący błąd:

Niedozwolona konfiguracja:
     zdefiniowane przez użytkownika atrybuty środowiska wykonawczego typu rozmiaru z wersjami Xcode
     starszymi niż 4.3 MainStoryboard.storyboard

Jeśli również pojawi się ten błąd, można go łatwo naprawić: wybierz Storyboard w Nawigatorze projektu i wywołaj Inspektora plików . Znajdź / rozwiń sekcję Interface Builder Document , a pojawi się lista rozwijana dla programowania . Upewnij się, że jest to ustawione naXcode 4.3

Herr Grumps
źródło
7
Niesamowite znalezisko! PS: Jestem zdumiony, że to najlepsze, co Apple może zrobić. Myślę, że to pokazuje, że nawet pracownicy Apple'a nigdy nie używają własnego narzędzia (konstruktora interfejsu) :).
Adam
Świetnie, to właśnie zadziałało dla mnie w Xcode 4.4. Ale jak teraz umieścić przyciski w części widoku przewijania, której nie mogę „zobaczyć” w IB?
Robert Atkins
1
Właśnie to rozpracowałem - musisz zwolnić przeciągnięcie, gdy wskaźnik nadal znajduje się wewnątrz "ekranu", w przeciwnym razie powróci do momentu, w którym zacząłeś. Co za ból.
Robert Atkins
Próbowałem tego w ten sposób, ale pojawia się błąd, "this class is not key value coding-compliant for the key keyPath"czy możesz mi pomóc, co robię źle? Należy pamiętać, że używam xamarin-ios-c #
SoftSan
25

Dzięki Autolayout (iOS6 +) możesz uniknąć ustawiania contentSize. Zamiast tego ustaw następujące ograniczenia:

  1. Przypnij górę widoku przewijania do jego najwyższego elementu podrzędnego.
  2. I przypnij dół do dołu jego najniższego dziecka.
Danyal Aytekin
źródło
1
Dziękuję - ustawienie contentSizenie działa z Xcode 5 i iOS 7
colincameron
18

Możesz to zrobić za pomocą samego Interface Builder, przejść do Inspektora tożsamości (trzecia zakładka inspektora) i dodać nowy atrybut User Defined Runtime z

  • Ścieżka klucza: contentSize
  • Typ: Rozmiar
  • Wartość: {szerokość, wysokość}
Anton Banchev
źródło
14

Teraz jest sposób na zrobienie UIScrollViewzwoju bez opuszczania Storyboard :

  1. Wybierz UIScrollVieww Storyboard, przejdź do Inspektora rozmiaru i zmień Dolną wartość (lub jakąkolwiek inną wartość, którą musisz zmienić) w sekcji Wstawki zawartości na wysokość obszaru zawartości.
  2. Teraz przejdź do Inspektora tożsamości i utwórz nowy atrybut wykonawczy zdefiniowany przez użytkownika (klikając przycisk +) i nazwij go contentSize. Nie ma znaczenia, jaki typ lub wartość wpiszesz (możesz nawet zostawić ich wartość domyślną).

To sprawi, że będzie UIScrollViewdziałać poprawnie, chociaż nie wiem, dlaczego drugi krok jest konieczny (przypadkiem się dowiedziałem). :(

RoberRM
źródło
Zmień wartość Bottom na co?
zakany
Zmień go na wysokość obszaru zawartości. Wydaje się, że działa i zastępuje wartość podaną dla atrybutu „contentSize” zdefiniowanego przez użytkownika.
Reid Ellis
Tak, Reid, masz rację: powinieneś zmienić wartość Bottom na wysokość obszaru zawartości. Zredagowałem mój oryginalny post, aby to odzwierciedlić. Dziękuję Ci!
RoberRM
4

Jednym z podejść, które stosowałem w przeszłości, jest przeciągnięcie widoku przewijania poza jego widok w narzędziu do tworzenia interfejsu i ustawienie jego rzeczywistego rozmiaru na taki, jaki ma mieć rozmiar contentSize.

co nie jest z natury oczywiste w konstruktorze interfejsów to to, że możesz mieć niepowiązane widoki, które są przechowywane w końcówce, ale nie są częścią widoku głównego, dla którego jest ona przeznaczona.

w widoku, w którym chcesz, aby przewijany widok był aktywny, umieść prosty UIView, którego używasz jako miejsca. (po prostu możesz wizualnie zaprojektować jego lokalizację. Jeśli używasz tylko całego widoku, możesz pominąć ten krok i użyć drugiego fragmentu kodu, który podam na końcu tej odpowiedzi).

możesz następnie wypełnić widok przewijania kontrolkami, wizualnie układając go tak, jak chcesz. podaj zarówno symbol zastępczy, jak i właściwości widoku przewijania w kontrolerze widoku, aby uzyskać do nich dostęp w czasie wykonywania.

w czasie wykonywania, w - (void) viewDidLoad

scrollView.contentSize = scrollView.frame.size;
scrollView.frame = placeholder.frame;
[placeholder.superview addSubView:scrollView];
[placeholder removeFromSuperview];

alternatywnie (jeśli nie użyłeś symbolu zastępczego):

CGRect f = self.view.frame;
scrollView.contentSize = f.size;
f.origin.x = 0;
f.origin.y = 0;
scrollView.frame = f;
[self.view addSubView:scrollView];

na koniec, jeśli „zgubisz” widok przewijania w konstruktorze interfejsu (można go zamknąć, aby zniknął z siatki projektu), nie panikuj. po prostu kliknij go na liście obiektów po lewej stronie siatki projektu.

niezsynchronizowane
źródło
1
Dzięki - to działało dobrze. Należy również zadeklarować IBOutlets w YourViewController.h dla widoków zastępczych i przewijania oraz połączyć je w programie Interface Builder. I wreszcie, dot.notation nie został doceniony przez xCode dla trzeciej linii, więc użyłem normalnej składni wysyłania wiadomości - wtedy wszystko działało świetnie!
jiy
bez obaw. Podczas publikowania fragmentów kodu zawsze istnieje niebezpieczeństwo, że niektórzy ludzie nie mogą ich użyć do zrozumienia koncepcji, zamiast oczekiwać, że „dokładny” kod zadziała w każdej sytuacji.
niezsynchronizowany
To jest metoda, której faktycznie używam. W ogóle nie muszę zmieniać rozmiaru tego programu. Myślę, że tak to powinno być zrobione. To jedyna prawdziwa odpowiedź.
user4951
Po narysowaniu go na zewnątrz po prostu przeniosę go do super widoku. Tada.
user4951
Właściwie zacząłem używać projektowania niektórych widoków poza sceną dla scratchpadów, co znacznie ułatwia życie w niektórych sytuacjach, nawet niezwiązanych z tą. Dzięki za tę odpowiedź.
Benjamin,
4

W Xcode 4.5 używającym Autolayout nie mam sekcji Wstawki zawartości w moim Inspektorze rozmiaru. Musiałem więc dodać go do atrybutów środowiska wykonawczego zdefiniowanych przez użytkownika, a potem działało dobrze.

To, co dodajesz w „atrybutach środowiska wykonawczego zdefiniowanych przez użytkownika”, to keyPath == contentInset, który jest typu „Rect” (UIEdgeInsets, który ma to samo wejście co Rect) i jest zdefiniowany jako {top, left}, {bottom, right}. ContentSize definiuje tylko region okna scrollview. contentInset definiuje przewijalny obszar.

Mam nadzieję, że to pomoże komuś w tej samej sytuacji.

Robert Wasmann
źródło
W przypadku UITextView użyj „textContainerInset” keyPath
Dima Deplov
4

Wiele z powyższych odpowiedzi jest mylących lub nieaktualnych. Począwszy od 2017 roku (prawdopodobnie znacznie wcześniej) Interfejs budowniczy robi scrollviews wsparcia z automatycznie wielkości zawartości. Sztuczka polega na tym, że XCode nadaje specjalne, niestandardowe znaczenie ograniczeniom między widokiem przewijania a zawartością w nim. Te „wewnętrzne” ograniczenia w rzeczywistości nie wpłyną na rozmiar treści, jak można by się spodziewać.

Oznacza to, że możesz np. Przypiąć widok przewijania do dołu głównego widoku z zerowym marginesem, a także przypiąć zawartość widoku przewijania do dołu widoku przewijania z zerowym marginesem, ale zawartość nie zostanie w rzeczywistości przez to rozciągnięta. Zamiast tego zawartość otrzyma swój własny rozmiar (więcej poniżej) i będzie to również rozmiar przewijalnego obszaru w przewijanym widoku.

Pomyśl o tym w ten sposób - istnieje asymetria w wiązaniu ograniczeń z widokiem przewijania: ograniczenia od widoku przewijania do świata „zewnętrznego” (nadrzędnego) określają rozmiar i położenie widoku przewijania, jak zwykle. Jednak ograniczenia „wewnątrz” widoku przewijanego w rzeczywistości określają rozmiar i położenie przewijalnego obszaru widoku przewijanego, wiążąc go z treścią.

Jest to całkowicie nieoczywiste, ponieważ kiedy idziesz do ustawiania ograniczeń, XCode zawsze zasugeruje bieżące odstępy i może nigdy nie przyjść do głowy celowa zmiana ograniczeń skierowanych do wewnątrz i na zewnątrz w sposób powodujący konflikty. Ale możesz i mają znaczenie opisane powyżej: jeden kontroluje układ widoku przewijania, a drugi kontroluje rozmiar przewijalnego obszaru zawartości.

Natknąłem się na to przez przypadek, a potem widząc, jak wyglądało to działa, doprowadziło mnie do tego artykułu, który wyjaśnia to całkowicie i cytuje źródło dokumentów Apple:

https://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/

Ostatnia krytyczna informacja na temat rozmiaru treści, który sam się określił: Możesz odnieść wrażenie, że znajdujesz się w punkcie 22, ponieważ zwykle dostosowujesz rozmiar treści do np. Szerokości widoku nadrzędnego, ale w tym przypadku nadrzędnym jest widok przewijania i jak opisano powyżej - ograniczenie nie wpłynie na rozmiar zawartości. Odpowiedź jest taka, aby pamiętać, że możesz ograniczyć pozycje do elementów, które nie są bezpośrednio sąsiadujące w twojej hierarchii widoku: np. Możesz ustawić szerokość widoku zawartości na szerokość widoku głównego zamiast na próżno próbować uzyskać widok przewijania, aby to zrobić dla Ciebie.

Pat Niemeyer
źródło
2

Jeśli klikniesz ikonę Właściwości dowolnego kontrolera widoku w programie Interface Builder, możesz ustawić go na „Dowolny” rozmiar w Symulowane metryki i zmienić rozmiar głównego widoku na żądany rozmiar zawartości.

W ten sposób możesz utworzyć zawartość swojego ScrollView tak, jakby była jednym dużym widokiem. Ponieważ jest to tylko symulowana metryka, rozmiar kontrolera widoku zostanie zmieniony do granic okna po załadowaniu.

oliland
źródło
2

Konfigurowanie UIScrollView za pomocą Interface Builder nie jest intuicyjne. Oto moja lista kontrolna, jak ją skonfigurować:

  1. Wybierz plik XIB UIViewControllera. W „Inspektorze tożsamości” konstruktora interfejsu zmień UIView na typ klasy UIScrollView

  2. W sekcji „Inspektor plików” usuń zaznaczenie opcji Automatyczne układanie

  3. W sekcji „Inspektor atrybutów” zmień rozmiar na Dowolny. Następnie możesz ręcznie rozciągnąć widok przewijania lub możesz określić niestandardową szerokość i wysokość w „Inspektorze rozmiaru”.

  4. W „Inspektorze tożsamości” dodaj nowy atrybut wykonawczy zdefiniowany przez użytkownika o nazwie „contentSize” typu „Size” i zmień go na wartość taką jak {320, 1000}. Nie można już ustawić tego programowo i dlatego potrzebny jest ten krok, aby widok przewijania wiedział, że zawartość widoku przewijania jest większa niż okno.

Uwolnij Masona
źródło
2

Po prostu usuń autoLayout z widoku przewijania. wtedy kod jest tak prosty:

scrollviewName.contentSize = CGSizeMake(0, 650);

wystarczy utworzyć właściwość iboulet w pliku .h, a następnie zsyntetyzować w pliku .m. Upewnij się, że przewijanie jest włączone.

Aldrin Equila
źródło
1

Tak, st3fan ma rację, należy ustawić właściwość contentSize UIScrollView. Nie należy jednak w tym celu wyłączać automatycznego układu. Możesz łatwo ustawić contentSize UIScrollView z automatycznym układem tylko w IB, bez żadnego kodu.

Ważne jest, aby zrozumieć, że podczas korzystania z autoukładania content Rozmiar elementu UIScrollView nie jest ustawiany bezpośrednio, jest on obliczany na podstawie ograniczeń wszystkich widoków podrzędnych UIScrollView. Wszystko, czego potrzebujesz, to zapewnienie odpowiednich ograniczeń dla widoków podrzędnych dla obu kierunków.

Np. Jeśli masz tylko jeden podgląd podrzędny, możesz ustawić jego wysokość i przestrzeń od góry i od dołu do superviewu (czyli scrollView w naszym przypadku). ContentSize.height jest obliczana jako suma

Vertical Space (aSubview.top to Superview.top) + aSubview.height + Vertical Space (aSubview.top to Superview.top)

contentSize.width jest obliczana podobnie na podstawie ograniczeń poziomych.

Jeśli jest zbyt mało ograniczeń do obliczenia contentSize, mały czerwony przycisk jest wyświetlany obok elementu View Controller Scene informując o niejednoznaczności układu.

Jeśli istnieje wiele subviews to może być „łańcuch” ograniczeń: od góry do najwyższych wysokościach podrzędny, a przestrzenie między subviews i najniżej podrzędny do dołu jak w Danyal Aytekin odpowiedź.

Ale w praktyce w większości przypadków wygodniej jest po prostu dodać pusty widok o wymaganym rozmiarze i ustawić spacje na górze, po lewej, na dole i po prawej stronie scrollView na 0. Możesz używać tego widoku jako "widoku zawartości" tj. Umieścić wszystkie inne podwidoki na nim lub jeśli masz już wiele widoków podrzędnych i nie chcesz ich przenosić i ponownie konfigurować układu, możesz dodać ten widok pomocniczy do istniejących widoków podrzędnych i ukryć go.

Aby umożliwić przewijanie scrollView obliczonej zawartości, rozmiar musi być większy niż rozmiar scrollView.

Vladimir
źródło
1

Możesz mieć UIScrollView w StoryBoard z Autolayouts. Zasadniczo potrzebujesz:

  1. Dodaj UIScrollView
  2. Dodaj do niego wszystkie wiązania (takie jak wstawki z górnej, lewej, prawej, dolnej krawędzi)
  3. Dodaj UIView „kontenera” do UIScrollView
  4. Jeśli chcesz przewijać tylko w jednym kierunku (powiedzmy, w pionie): ustaw wysokość jawnie (na przykład 600) i szerokość łącza na szerokość UIScrollView.
  5. Jeśli chcesz przewijać w dwóch kierunkach, po prostu ustaw szerokość i wysokość.

konfiguracja scenorysu

Eugene Braginets
źródło
0

Oto rozwiązanie umożliwiające zaprojektowanie ScrollView z zawartością większą niż ekran w całości w Storyboard (cóż, prawie całkowicie, musisz też dodać 1 pojedynczy wiersz kodu)

https://stackoverflow.com/a/19476991/1869369

Ronny Webers
źródło
0

Znajduję wygodniejszy sposób.

1: Skaluj rozmiar widoku przewijania, aby zawierał cały interfejs użytkownika w nim.

2: Dodaj iboutlet widoku przewijania.

3: W viewDidLoad zapisz rozmiar ramki widoku przewijania.
(np. _scrollSize = _scrollView.frame.size;)

4: W viewWillAppear ustaw contentSize na CGSize, który zapisałeś wcześniej.
(np. _scrollView.contentSize = _scrollSize;)

5: Done ~

Agas
źródło
0
  1. Dodaj UIViewController
  2. W UIViewController „Attribute Inspector -> Simulated Metrics” ustaw rozmiar Freeform
  3. W UIViewController 'Size Inspector -> View Controller' ustaw wysokość 800
  4. Dodaj UIScrollView w UIViewController
  5. Dodaj wszystkie ograniczenia do UIScrollView (góra, lewo, prawo, dół) i dodaj wyrównanie X = środek
  6. Dodaj UIView w UIScrollView
  7. Dodaj wszystkie wiązania do UIView (góra, lewo, prawo, dół) i dodaj wyrównanie X = środek. Tak, to samo, co dla UIScrollView w # 3, ale dla UIView
  8. Dodaj ograniczenie wysokości do UIView. Na przykład 780
  9. Biegać

Storyboard

Alexander
źródło
0

Utwórz nowy projekt Xcode

Przejdź do pliku Main.storyboard

Wybierz ScrollView z biblioteki obiektów.

Ustaw ramkę dla ScrollView.

Dodaj kolejny widok, aby przewijać widok i zachować tę samą ramkę, co w ScrollView.

Teraz, aby dynamicznie ustawić jego wysokość i szerokość, możesz to skonfigurować UIScrollView przy użyciu automatycznego układu w XIB

Dilraj Singh
źródło