Wie verwende ich UIScrollView in Interface Builder?

95

Während ich UIScrollViewin der Vergangenheit erfolgreich programmgesteuert gearbeitet habe, habe ich Probleme, es zum Laufen zu bringen, indem ich es ausschließlich in Interface Builder einrichte.

Ich habe eine einfache "Über" -Seite in meiner iPhone-App. Es hat ein UITextView, einige Symbole und Links zu meinen anderen Apps. Ich habe alle diese Ansichten zu meinen hinzugefügt UIScrollViewund sie so angeordnet, dass ihre Gesamtgröße> 480 ist. Wenn ich meine App starte, zeigt die Bildlaufansicht nur den Inhalt an, der auf den Bildschirm passt, und nichts scrollt.

Ist dies vollständig über IB möglich oder muss ich die contentSize per Code bearbeiten?

George Armhold
quelle

Antworten:

130

Sie haben vergessen, die contentSize-Eigenschaft von UIScrollView festzulegen. Seltsamerweise können Sie dies nicht mit Interface Builder tun. Sie müssen dies über den Ansichts-Controller tun, der diese Bildlaufansicht verwaltet.

Stefan Arentz
quelle
42
Wow, macht IB eher sinnlos ... Das hat den Trick gemacht, danke.
George Armhold
20
Sie können eine Unterklasse von UIScrollvView erstellen, die prüft, ob nur eine Unteransicht bei (0,0) vorhanden ist, und dann automatisch die Inhaltsgröße basierend auf dieser Unteransicht festlegt.
Stefan Arentz
1
Das ist der beste Rat, den ich seit einiger Zeit erhalten habe. Ich konnte nicht herausfinden, warum meine Bildlaufansicht nicht funktionierte, und fand diese Informationen zu contentSize nirgendwo anders. Vielen Dank.
Drew C
46
Ich habe versucht, herauszufinden, wie contentSize in Interface Builder festgelegt wird, und diese Diskussion gefunden. Zumindest für mich kann ich es in Xcode 4.5 mithilfe von „Benutzerdefinierten Laufzeitattributen“ festlegen, indem ich einen Eintrag mit dem Namen contentSizetype hinzufüge Sizeund den gewünschten Wert festlege .
Nlogax
5
Ich bin immer noch verblüfft darüber, warum iOS die Bildlaufansicht nicht automatisch contentSizebasierend auf den Abmessungen seiner Unteransichten festlegt , zumindest nicht als Standardverhalten.
aroth
113

Die Antwort von Boby_Wan brachte mich zum Nachdenken und ich fand die folgende Lösung, um die contentSize von UIScrollView über Interface Builder zu konfigurieren:

  1. Wählen Sie die UIScrollViewin der Storyboard-Szene aus
  2. Gehen Sie zum Identitätsinspektor und erstellen Sie ein neues benutzerdefiniertes Laufzeitattribut (klicken Sie auf die Schaltfläche +).
  3. Ändern Sie das Attribut Schlüsselpfad incontentSize
  4. Ändern Sie das Attribut Typ inSize
  5. Stellen Sie nun den Wert auf { gewünschte Inhaltsbreite , gewünschte Inhaltshöhe } ein

Wenn Sie beispielsweise den Wert auf {320, 920} setzen, kann der Benutzer auf dem iPhone einen ganzen zusätzlichen Bildschirm nach unten scrollen.

(Ich verwende xcode 4.3.3, das iOS-Bereitstellungsziel des Projekts ist 5.1.)

Als ich dies zum ersten Mal tat, erhielt ich die folgende Fehlermeldung:

Unzulässige Konfiguration:
     Benutzerdefinierte Laufzeitattribute vom
     Größentyp mit Xcode-Versionen vor 4.3 MainStoryboard.storyboard

Wenn auch dieser Fehler auftritt, ist er einfach zu beheben: Wählen Sie das Storyboard im Projektnavigator aus und rufen Sie den Dateiinspektor auf . Suchen / erweitern Sie den Abschnitt Interface Builder-Dokument , und es gibt eine Dropdown-Liste für die Entwicklung . Stellen Sie sicher, dass dies auf eingestellt istXcode 4.3

Herr Grumps
quelle
7
Super Fund! PS: Ich bin fassungslos, dass dies das Beste ist, was Apple tun kann. Ich denke, dies zeigt, dass selbst Apple-Mitarbeiter niemals ihr eigenes Tool (Interface Builder) verwenden :).
Adam
Genial, das hat gerade bei mir in Xcode 4.4 funktioniert. Aber wie füge ich jetzt Schaltflächen in den Teil der Bildlaufansicht ein, den ich in IB nicht "sehen" kann?
Robert Atkins
1
Ich habe es gerade herausgefunden - Sie müssen das Ziehen loslassen, wenn sich der Zeiger noch im "Bildschirm" befindet, andernfalls wird er auf den Zeitpunkt zurückgesetzt, an dem Sie begonnen haben. Was für ein Schmerz.
Robert Atkins
Ich habe es so versucht, aber ich erhalte eine Fehlermeldung. "this class is not key value coding-compliant for the key keyPath"Können Sie mir bitte helfen, was mache ich falsch? Bitte beachten Sie, dass ich xamarin-ios-c #
SoftSan
25

Mit Autolayout (iOS6 +) können Sie Einstellungen vermeiden contentSize. Legen Sie stattdessen die folgenden Einschränkungen fest:

  1. Stecken Sie den oberen Rand der Bildlaufansicht an den oberen Rand des obersten untergeordneten Elements.
  2. Und stecken Sie den Boden an den Boden des untersten Kindes.
Danyal Aytekin
quelle
1
Vielen Dank - Einstellung contentSizefunktioniert nicht mit Xcode 5 und iOS 7
colincameron
18

Sie können dies nur mit dem Interface Builder tun, zum Identitätsinspektor (der dritten Registerkarte des Inspektors) wechseln und ein neues benutzerdefiniertes Laufzeitattribut mit hinzufügen

  • Schlüsselpfad: contentSize
  • Typ: Größe
  • Wert: {Breite, Höhe}
Anton Banchev
quelle
14

Jetzt gibt es eine Möglichkeit, eine UIScrollViewSchriftrolle zu erstellen, ohne das Storyboard zu verlassen :

  1. Wählen Sie das UIScrollViewim Storyboard, gehen Sie auf die Größe des Inspektors und ändern Sie den Bottom - Wert (oder was auch immer anderer Wert , den Sie ändern müssen) im Inhalt Insets Abschnitt der Höhe des Inhaltsbereich.
  2. Gehen Sie nun zum Identitätsinspektor und erstellen Sie ein neues benutzerdefiniertes Laufzeitattribut (indem Sie auf die Schaltfläche + klicken) und benennen Sie es contentSize. Es spielt keine Rolle, welchen Typ oder Wert Sie eingeben (Sie können sogar den Standardwert beibehalten).

Dies wird die UIScrollViewArbeit richtig machen, obwohl ich nicht weiß, warum der zweite Schritt notwendig ist (ich habe es zufällig herausgefunden). :(

RoberRM
quelle
Ändern Sie den unteren Wert auf was?
Zakdances
Ändern Sie es auf die Höhe des Inhaltsbereichs. Es scheint zu funktionieren und überschreibt den Wert, den Sie für das benutzerdefinierte Attribut "contentSize" angeben.
Reid Ellis
Ja, Reid, Sie haben Recht: Sie sollten den unteren Wert auf die Höhe des Inhaltsbereichs ändern. Ich habe meinen ursprünglichen Beitrag bearbeitet, um dies widerzuspiegeln. Danke dir!
RoberRM
4

Ein Ansatz, den ich in der Vergangenheit verwendet habe, besteht darin, die Bildlaufansicht aus der enthaltenen Ansicht im Interface Builder zu ziehen und die tatsächliche Größe auf die gewünschte Größe von contentSize festzulegen.

Was an Interface Builder nicht von Natur aus offensichtlich ist, ist, dass Sie nicht zugeordnete Ansichten haben können, die in der Schreibfeder gespeichert sind, aber nicht Teil der Hauptansicht sind, für die die Schreibfeder in erster Linie bestimmt ist.

Platzieren Sie in der Ansicht, in der die Bildlaufansicht angezeigt werden soll, eine einfache UIView, die Sie als Platzhalter verwenden. (Dies ist einfach, damit Sie den Standort visuell gestalten können. Wenn Sie nur die gesamte Ansicht verwenden, können Sie diesen Schritt überspringen und das zweite Code-Snippet verwenden, das ich am Ende dieser Antwort angegeben habe.)

Anschließend können Sie die Bildlaufansicht mit Steuerelementen füllen und sie visuell so anordnen, wie Sie es möchten. Geben Sie sowohl die Platzhalter- als auch die Bildlaufansichtseigenschaften in Ihrem Ansichts-Controller an, damit Sie zur Laufzeit darauf zugreifen können.

zur Laufzeit in - (void) viewDidLoad

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

alternativ (wenn Sie keinen Platzhalter verwendet haben):

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

Wenn Sie Ihre Bildlaufansicht im Interface Builder "verlieren" (es ist möglich, sie zu schließen, damit sie aus dem Entwurfsraster verschwindet), geraten Sie nicht in Panik. Klicken Sie einfach in der Objektliste links neben dem Entwurfsraster darauf.

nicht synchronisiert
quelle
1
Danke - das hat gut funktioniert. Außerdem müssen Sie IBOutlets in YourViewController.h für die Platzhalter- und Bildlaufansichten deklarieren und im Interface Builder verbinden. Und schließlich wurde dot.notation von xCode für die 3. Zeile nicht geschätzt, also wurde die normale Syntax zum Senden von Nachrichten verwendet - dann hat alles super funktioniert!
13.
Keine Bange. Beim Posten von Codefragmenten besteht immer die Gefahr, dass manche Leute sie nicht verwenden können, um das Konzept zu erhalten, anstatt zu erwarten, dass der "genaue" Code in jeder Situation funktioniert.
synchronisiert
Dies ist die Methode, die ich tatsächlich benutze. Ich muss die Größe dieses Programms überhaupt nicht ändern. Ich denke, es ist so, wie es gemacht werden soll. Es ist die einzig wahre Antwort.
user4951
Nachdem ich es nach draußen gezeichnet habe, verschiebe ich es einfach in die Superansicht. Tada.
user4951
Ich habe tatsächlich angefangen, einige Ansichten außerhalb einer Szene für Notizblöcke zu entwerfen, und so macht es das Leben in einigen Situationen viel einfacher, auch wenn es nichts mit dieser zu tun hat. Danke für diese Antwort.
Benjamin
4

In Xcode 4.5 mit Autolayout habe ich in meinem Größeninspektor keinen Abschnitt mit Inhaltseinfügungen. Also musste ich es unter Benutzerdefinierte Laufzeitattribute hinzufügen und dann funktionierte es einwandfrei.

Was Sie in "Benutzerdefinierte Laufzeitattribute" hinzufügen, ist keyPath == contentInset vom Typ "Rect" (UIEdgeInsets, das dieselbe Eingabe wie ein Rect hat) und definiert als {oben, links}, {unten, rechts}. Die contentSize definiert nur den Bereich des Bildlauffensters. contentInset definiert den scrollbaren Bereich.

Ich hoffe das hilft jemandem in der gleichen Situation.

Robert Wasmann
quelle
Für UITextView verwenden Sie "textContainerInset" keyPath
Dima Deplov
4

Viele der obigen Antworten sind irreführend oder veraltet. Ab 2017 (möglicherweise viel früher) Interface Builder funktioniert Unterstützung scrollviews mit automatisch Größe Inhalt. Der Trick besteht darin, dass XCode den Einschränkungen zwischen der Bildlaufansicht und dem darin enthaltenen Inhalt eine spezielle, nicht standardmäßige Bedeutung verleiht. Diese "inneren" Einschränkungen wirken sich nicht auf die Größe des Inhalts aus, wie Sie es sonst erwarten würden.

Dies bedeutet, dass Sie beispielsweise Ihre Bildlaufansicht mit einem Rand von Null am unteren Rand der Hauptansicht anheften und den Inhalt Ihrer Bildlaufansicht mit einem Rand am unteren Rand der Bildlaufansicht anheften können, der Inhalt jedoch dadurch nicht wirklich gedehnt wird. Stattdessen erhält der Inhalt seine selbstbestimmte Größe (siehe unten) und dies ist auch die Größe des scrollbaren Bereichs in der Bildlaufansicht.

Stellen Sie sich das so vor: Es gibt eine Asymmetrie bei der Bindung von Einschränkungen an eine Bildlaufansicht: Einschränkungen von der Bildlaufansicht zur "äußeren" (übergeordneten) Welt bestimmen wie gewohnt die Größe und Position der Bildlaufansicht. Einschränkungen "innerhalb" der Bildlaufansicht legen jedoch die Größe und Position des scrollbaren Bereichs der Bildlaufansicht fest, indem sie an den Inhalt gebunden werden.

Dies ist völlig nicht offensichtlich, da XCode beim Festlegen der Einschränkungen immer den aktuellen Abstand vorschlägt und es Ihnen möglicherweise nie in den Sinn kommt, die nach innen und außen gerichteten Einschränkungen absichtlich so zu ändern, dass Konflikte auftreten. Aber Sie können und sie haben die oben beschriebene Bedeutung: Eine steuert das Layout der Bildlaufansicht und eine steuert die Größe des scrollbaren Inhaltsbereichs.

Ich bin zufällig darauf gestoßen, und als ich dann sah, wie es zu funktionieren schien, kam ich zu diesem Artikel, der es vollständig erklärt und die Quelle der Apple-Dokumente dafür zitiert:

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

Eine letzte wichtige Information über die selbstbestimmte Größe des Inhalts: Möglicherweise haben Sie das Gefühl, dass Sie sich hier in einem Catch-22 befinden, da Sie Ihren Inhalt normalerweise auf die Breite der übergeordneten Ansicht skalieren. In diesem Fall ist die übergeordnete Ansicht jedoch die Bildlaufansicht und Wie oben beschrieben - Die Einschränkung wirkt sich nicht auf Ihre Inhaltsgröße aus. Die Antwort hier ist, sich daran zu erinnern, dass Sie Elemente auf Elemente beschränken können, die in Ihrer Ansichtshierarchie nicht direkt benachbart sind: Sie können beispielsweise die Breite Ihrer Inhaltsansicht auf die Breite der Hauptansicht festlegen, anstatt vergeblich zu versuchen, die Bildlaufansicht dazu zu bringen für dich.

Pat Niemeyer
quelle
2

Wenn Sie in Interface Builder auf das Eigenschaftensymbol eines View Controllers klicken, können Sie es in Simulated Metrics auf eine "Freeform" -Größe einstellen und die Größe der Hauptansicht so ändern, dass sie der gewünschten Inhaltsgröße entspricht.

Auf diese Weise können Sie den Inhalt Ihrer ScrollView so erstellen, als wäre es eine große Ansicht. Da es sich nur um eine simulierte Metrik handelt, wird die Größe Ihres View Controllers beim Laden an die Grenzen des Fensters angepasst.

oliland
quelle
2

Das Einrichten einer UIScrollView über Interface Builder ist nicht intuitiv. Hier ist meine Checkliste zum Einrichten:

  1. Wählen Sie die XIB-Datei des UIViewControllers aus. Ändern Sie im "Identity Inspector" des Interface Builders die UIView in den Klassentyp UIScrollView

  2. Deaktivieren Sie unter "Dateiinspektor" die Option "Autolayout"

  3. Ändern Sie unter "Attributes Inspector" die Größe in Freeform. Sie können die Bildlaufansicht dann manuell dehnen oder unter "Größeninspektor" eine benutzerdefinierte Breite und Höhe angeben.

  4. Fügen Sie in "Identity Inspector" ein neues benutzerdefiniertes Laufzeitattribut mit dem Namen "contentSize" vom Typ "Size" hinzu und ändern Sie es in einen Wert wie {320, 1000}. Sie können dies nicht mehr programmgesteuert einstellen und benötigen daher diesen Schritt, damit die Bildlaufansicht weiß, dass der Inhalt der Bildlaufansicht größer als das Fenster ist.

Freier Maurer
quelle
2

Entfernen Sie einfach das AutoLayout in Ihrer Bildlaufansicht. dann ist der Code so einfach:

scrollviewName.contentSize = CGSizeMake(0, 650);

Erstellen Sie einfach eine iboulet-Eigenschaft für die .h-Datei und synthetisieren Sie sie für die .m-Datei. Stellen Sie sicher, dass das Scrollen aktiviert ist.

Aldrin Equila
quelle
1

Ja, st3fan hat recht, die contentSize-Eigenschaft von UIScrollView muss festgelegt werden. Sie sollten das Autolayout zu diesem Zweck jedoch nicht deaktivieren. Sie können contentSize von UIScrollView problemlos mit Autolayout nur in IB ohne Code einrichten.

Es ist wichtig zu verstehen, dass bei Verwendung von Autolayout die Inhaltsgröße von UIScrollView nicht direkt festgelegt wird, sondern basierend auf den Einschränkungen aller Unteransichten von UIScrollView berechnet wird. Sie müssen lediglich die richtigen Einschränkungen für Unteransichten für beide Richtungen festlegen.

Wenn Sie beispielsweise nur eine Unteransicht haben, können Sie deren Höhe und Abstand von oben und unten auf die Übersicht (in unserem Fall die Bildlaufansicht) einstellen. ContentSize.height wird als Summe berechnet

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

contentSize.width wird auf ähnliche Weise aus horizontalen Einschränkungen berechnet.

Wenn zu wenige Einschränkungen für die Berechnung der Inhaltsgröße vorhanden sind, wird neben dem Element "View Controller-Szene" eine kleine rote Schaltfläche angezeigt, um über die Mehrdeutigkeit des Layouts zu informieren.

Wenn es viele Unteransichten gibt, kann es sich um eine "Kette" von Einschränkungen handeln: von oben nach oben, Höhen und Abstände zwischen Unteransichten und unterste Unteransicht nach unten, wie in der Antwort von Danyal Aytekin .

In der Praxis ist es jedoch in den meisten Fällen bequemer, nur eine leere Ansicht mit der erforderlichen Größe hinzuzufügen und die Leerzeichen oben, links, unten und rechts von scrollView auf 0 zu setzen. Sie können diese Ansicht als "Inhaltsansicht" verwenden, dh alle anderen Unteransichten einfügen Wenn Sie bereits viele Unteransichten haben und diese nicht verschieben und das Layout erneut einrichten möchten, können Sie diese Hilfsansicht zu vorhandenen Unteransichten hinzufügen und ausblenden.

Damit scrollView scrollbar ist, muss die berechnete Inhaltsgröße größer als die scrollView-Größe sein.

Vladimir
quelle
1

Sie können UIScrollView in StoryBoard mit Autolayouts verwenden. Grundsätzlich brauchen Sie:

  1. Fügen Sie UIScrollView hinzu
  2. Fügen Sie alle Einschränkungen hinzu (z. B. Einfügungen von der oberen, linken, rechten und unteren Kante).
  3. Fügen Sie UIScrollView eine 'Container'-UIView hinzu
  4. Wenn Sie nur in eine Richtung scrollen möchten (z. B. vertikal): Legen Sie die Höhe explizit fest (z. B. 600) und verknüpfen Sie die Breite mit der Breite von UIScrollView.
  5. Wenn Sie in zwei Richtungen scrollen möchten, stellen Sie einfach Breite und Höhe ein.

Storyboard-Setup

Eugene Braginets
quelle
0

Hier ist eine Lösung zum Entwerfen von ScrollView mit einem Inhalt, der größer als der Bildschirm ist, vollständig in Storyboard (fast vollständig müssen Sie auch eine einzelne Codezeile hinzufügen).

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

Ronny Webers
quelle
0

Ich finde einen bequemeren Weg.

1: Skalieren Sie die Größe der Bildlaufansicht so, dass die gesamte Benutzeroberfläche darin enthalten ist.

2: Fügen Sie ein Iboutlet der Bildlaufansicht hinzu.

3: Speichern Sie in viewDidLoad die frame.size der Bildlaufansicht.
(zB _scrollSize = _scrollView.frame.size;)

4: Legen Sie in viewWillAppear die contentSize anhand der zuvor gespeicherten CGSize fest.
(zB _scrollView.contentSize = _scrollSize;)

5: Fertig ~

Agas
quelle
0
  1. Fügen Sie UIViewController hinzu
  2. In UIViewController 'Attributinspektor -> Simulierte Metriken' festgelegte Größe Freiform
  3. Stellen Sie in UIViewController 'Size Inspector -> View Controller' die Höhe 800 ein
  4. Fügen Sie UIScrollView in UIViewController hinzu
  5. Fügen Sie UIScrollView alle Einschränkungen hinzu (oben, links, rechts, unten) und fügen Sie die Ausrichtung X = Mitte hinzu
  6. Fügen Sie UIView in UIScrollView hinzu
  7. Fügen Sie UIView alle Einschränkungen hinzu (oben, links, rechts, unten) und fügen Sie die Ausrichtung X = Mitte hinzu. Ja, wie für UIScrollView in # 3, jedoch für UIView
  8. Fügen Sie UIView eine Höhenbeschränkung hinzu. Zum Beispiel 780
  9. Lauf

Storyboard

Alexander
quelle