webentwicklung-frage-antwort-db.com.de

Kann UIStackView einen Bildlauf durchführen?

Nehmen wir an, ich habe in UIStackView weitere Ansichten hinzugefügt, die angezeigt werden können. Wie kann ich die Variable UIStackView scrollen lassen?

147
itsaboutcode

Für den Fall, dass jemand nach einer Lösung ohne Code sucht, habe ich ein Beispiel erstellt, um dies vollständig im Storyboard mit Auto Layout zu tun.

Sie können es von github bekommen.

Um das Beispiel neu zu erstellen:

  1. Erstellen Sie ein UIScrollView und legen Sie die Einschränkungen fest.
  2. Fügen Sie der UIStackView eine UIScrollView hinzu.
  3. Legen Sie die Einschränkungen fest: Leading, Trailing, Top und Bottom sollten mit denen von UIScrollView
  4. Richten Sie eine Width-Einschränkung zwischen UIStackView und UIScrollView ein. 
  5. Setze Achse = Vertikal, Ausrichtung = Füllung, Verteilung = Gleicher Abstand und Abstand = 0 in der UIStackView
  6. Fügen Sie dem UIViews eine Zahl von UIStackView hinzu.
  7. Lauf
436
Arjan

Apples Handbuch für das automatische Layout enthält einen ganzen Abschnitt zu Arbeiten mit Bildlaufansichten . Einige relevante Ausschnitte:

  1. Befestigen Sie die oberen, unteren, führenden und hinteren Kanten der Inhaltsansicht an den entsprechenden Kanten der Bildlaufansicht. Die Inhaltsansicht definiert jetzt den Inhaltsbereich der Bildlaufansicht.
  2. (Optional) Um den horizontalen Bildlauf zu deaktivieren, stellen Sie die Breite der Inhaltsansicht auf die Breite der Bildlaufansicht ein. Die Inhaltsansicht füllt jetzt die Bildlauf horizontal.
  3. (Optional) Um den vertikalen Bildlauf zu deaktivieren, stellen Sie die Höhe der Inhaltsansicht auf die Höhe der Bildlaufansicht ein. Die Inhaltsansicht füllt jetzt die Bildlaufansicht horizontal.

Außerdem:

Ihr Layout muss die Größe der Inhaltsansicht vollständig definieren (mit Ausnahme von .__, sofern in Schritt 5 und 6 definiert). … Wenn die Inhaltsansicht höher ist als die Bildlaufansicht, ermöglicht die Bildlaufansicht einen vertikalen Bildlauf. Wenn die Inhaltsansicht breiter als die Bildlaufansicht ist, ermöglicht die Bildlaufansicht einen horizontalen Bildlauf.

Zusammenfassend muss festgehalten werden, dass die Inhaltsansicht der Bildlaufansicht (in diesem Fall eine Stapelansicht) an den Kanten und fixiert ist, deren Breite und/oder Höhe ansonsten eingeschränkt ist. Das bedeutet, dass der Inhalt der Stack-Ansicht (direkt oder indirekt) in die Richtung (s) beschränkt werden muss, in der ein Scrollen gewünscht wird. Dies kann beispielsweise bedeuten, dass jeder Ansicht innerhalb einer vertikal scrollenden Stack-Ansicht eine Höhenbeschränkung hinzugefügt wird. Das folgende Beispiel zeigt, wie ein vertikaler Bildlauf einer Bildlaufansicht mit Stapelansicht möglich ist:

// Pin the edges of the stack view to the edges of the scroll view that contains it
stackView.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
stackView.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
stackView.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true

// Set the width of the stack view to the width of the scroll view for vertical scrolling
stackView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
33
titaniumdecoy

Wie Eik sagt, spielen UIStackView und UIScrollView gut zusammen, siehe hier

Der Schlüssel ist, dass die UIStackView die variable Höhe/Breite für verschiedene Inhalte verarbeitet und die UIScrollView dann ihre Aufgabe erfüllt, diesen Inhalt zu scrollen/zu bouncen:

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)       
}
12
user1307434

Die Einschränkungen in der am besten bewerteten Antwort hier funktionierten für mich, und ich habe ein Bild der Einschränkungen eingefügt, die in meinem Storyboard erstellt wurden.

Ich habe jedoch zwei Probleme gefunden, von denen andere wissen sollten: 

  1. Nachdem Sie Bedingungen hinzugefügt haben, die denen in der akzeptierten Antwort ähneln, wird der rote Fehler "AutoLayout" Need constraints for: X position or width angezeigt. Dies wurde gelöst, indem ein UILabel als Unteransicht der Stapelansicht hinzugefügt wurde.

    Ich füge die Unteransichten programmgesteuert hinzu, daher hatte ich ursprünglich keine Unteransichten auf dem Storyboard. Fügen Sie dem Storyboard eine Unteransicht hinzu und entfernen Sie sie beim Laden, bevor Sie Ihre echten Unteransichten und Einschränkungen hinzufügen.

  2. Ich habe ursprünglich versucht, der UIStackView UIButtons hinzuzufügen. Die Schaltflächen und Ansichten würden geladen, aber die Scroll-Ansicht würde nicht scrollen . Dies wurde durch Hinzufügen von UILabels zur Stack-Ansicht anstelle von Schaltflächen gelöst. Unter Verwendung der gleichen Einschränkungen scrollen diese Ansichtshierarchien mit den UILabels, die UIButtons jedoch nicht.

    Ich bin durch dieses Problem verwirrt, da die UIButtons do über eine IntrinsicContentSize verfügen (die von der Stack-Ansicht verwendet wird). Wenn jemand weiß, warum die Tasten nicht funktionieren, würde ich gerne wissen, warum.

Hier sind meine Ansichtshierarchie und Einschränkungen als Referenz:

constraints for stack view in scroll view[1]

11
pkamb

Ich habe versucht, das Gleiche zu tun und stolperte über diesen exzellenten Beitrag. Wenn Sie dies programmgesteuert mit der Anker-API tun möchten, ist dies der richtige Weg. 

Um es zusammenzufassen, binden Sie Ihre UIStackView in Ihre UIScrollView ein und setzen Sie die Ankerbedingungen der UIStackView so, dass sie denen der UIScrollView entsprechen:

stackView.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
stackView.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
stackView.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
stackView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
8
Dalmazio

Fügen Sie dies einfach zu viewdidload hinzu:

let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
scrollVIew.contentInset = insets
scrollVIew.scrollIndicatorInsets = insets

source: https://developer.Apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/LayoutUsingStackViews.html

5
rashad.z

Hier ist die einfachste mögliche Erklärung:

  1. Haben Sie eine leere Vollbildszene

  2. Fügen Sie eine Bildlaufansicht hinzu. Ziehen Sie bei gedrückter Strg-Taste aus der Bildlaufansicht in die Basisansicht, fügen Sie links-rechts-oben-unten alle Null hinzu.

  3. Fügen Sie in der Bildlaufansicht eine Stapelansicht hinzu. Ziehen Sie bei gedrückter Strg-Taste aus der Stapelansicht in die Bildlaufansicht, fügen Sie links-rechts oben oben und unten Null hinzu.

  4. Fügen Sie ein UILabel in die Stapelansicht ein.

Machen Sie die Hintergrundfarbe zur Verdeutlichung rot; Setzen Sie die Höhe auf 100, und legen Sie in Ihrer Stapelansicht den Abstand auf 20 fest.

  1. Stellen Sie nun die Breite des UILabels ein:

    Überraschenderweise ziehen Sie bei gedrückter Strg-Taste von der UILabel in die Bildlaufansicht, nicht der Stapelansicht und wählen Sie gleiche Breiten aus.

Wiederholen:

Kontrollieren Sie nicht das Ziehen vom UILabel zum übergeordneten Element des UILabel - gehen Sie zum Großelternteil. (Mit anderen Worten, gehen Sie bis zur Bildlaufansicht, nicht in die Stapelansicht.)

So einfach ist das. Das ist das Geheimnis.

  1. Als Nächstes klicken Sie Muss auf das eine UILabel, und Sie Muss klicken einige Male wortwörtlich Kopieren und Einfügen. Es funktioniert nicht mit nur einem Element. (Klicken Sie NICHT auf "Duplizieren", klicken Sie auf "Kopieren, dann Einfügen".)

Sie sind fertig. So einfach ist das.

Tipp: Fügen Sie der Stack-Ansicht ein neues Element hinzu, beispielsweise eine UIView (möglicherweise als Leerzeichen verwendet). Beachten Sie, dass alles schief geht. In der Tat müssen Sie muss jedem neuen Element eine Höhe hinzufügen} (sagen Sie "100"). Jedes Mal, wenn Sie ein neues Element hinzufügen, ist Sie müssen ihm irgendwie eine Höhe geben.


Eine andere Sichtweise:

Im oberen Teil heißt es dazu: überraschenderweise setzen Sie die Breite der UILabels auf die Breite der Bildlaufansicht (nicht die Stapelansicht). Das funktioniert perfekt.

Abwechselnd...

Beachten Sie, dass die Stapelansicht links und rechts an der übergeordneten Ansicht, der Bildlaufansicht, befestigt ist. Versuche dies:

Ziehen Sie aus der Stapelansicht in die Bildlaufansicht, und fügen Sie eine Einschränkung "Breite gleich" hinzu. Dies erscheint seltsam, weil Sie bereits links-rechts festgesteckt haben, aber so machen Sie es. Egal wie seltsam es scheint, das ist das Geheimnis.

Sie haben also zwei Möglichkeiten:

  1. Stellen Sie überraschenderweise die Breite der UILabels auf die Breite des scrollview-Großelternteils ein (nicht das übergeordnete Stackview).

oder

  1. Überraschenderweise setzen Sie eine "Breite gleich" der Stapelansicht auf die Bildlaufansicht - obwohl Sie haben die linke und rechte Kante der Stapelansicht trotzdem an der Bildlaufansicht fixiert.

Um klar zu sein, führen Sie EINE dieser Methoden aus, NICHT beide.

2
Fattie

Sie können versuchen, ScrollableStackView: https://github.com/gurhub/ScrollableStackView

Es ist eine mit Objective-C und Swift kompatible Bibliothek. Es ist über CocoaPods verfügbar.

Beispielcode (Swift)

import ScrollableStackView

var scrollable = ScrollableStackView(frame: view.frame)
view.addSubview(scrollable)

// add your views with 
let rectangle = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 55))
rectangle.backgroundColor = UIColor.blue
scrollable.stackView.addArrangedSubview(rectangle)
// ...

Beispielcode (Objective-C)

@import ScrollableStackView

ScrollableStackView *scrollable = [[ScrollableStackView alloc] initWithFrame:self.view.frame];
scrollable.stackView.distribution = UIStackViewDistributionFillProportionally;
scrollable.stackView.alignment = UIStackViewAlignmentCenter;
scrollable.stackView.axis = UILayoutConstraintAxisVertical;
[self.view addSubview:scrollable];

UIView *rectangle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 55)];
[rectangle setBackgroundColor:[UIColor blueColor]];

// add your views with
[scrollable.stackView addArrangedSubview:rectangle]; 
// ...
2
mgyky

Für verschachtelte oder einzelne Stack-Ansicht muss für die Scroll-Ansicht eine feste Breite in der Stammansicht festgelegt werden. Die Hauptstapelansicht, die sich in der Bildlaufansicht befindet, muss dieselbe Breite haben. [Meine Scroll-Ansicht ist eine Ansicht, die ignoriert wird]

Richten Sie eine gleich breite Breite zwischen UIStackView und .__ ein. UIScrollView.

 enter image description here

0

Wenn Sie die Stapelansicht vertikal innerhalb der Bildlaufansicht zentrieren möchten, entfernen Sie sie einfach.

0
Ahmed Elashker

Platzieren Sie eine Bildlaufansicht in Ihrer Szene und passen Sie die Größe so an, dass sie die Szene ausfüllt. Platzieren Sie dann eine Stapelansicht in der Bildlaufansicht und die Schaltfläche Element hinzufügen in der Stapelansicht. Sobald alles vorhanden ist, legen Sie die folgenden Einschränkungen fest:

Scroll View.Leading = Superview.LeadingMargin
Scroll View.Trailing = Superview.TrailingMargin
Scroll View.Top = Superview.TopMargin
Bottom Layout Guide.Top = Scroll View.Bottom + 20.0
Stack View.Leading = Scroll View.Leading
Stack View.Trailing = Scroll View.Trailing
Stack View.Top = Scroll View.Top
Stack View.Bottom = Scroll View.Bottom
Stack View.Width = Scroll View.Width

enter image description here

code: Stack View.Width = Scroll View.Width ist der Schlüssel.

0
Joshua Cleetus

Beispiel für eine vertikale Stapelansicht/Scrollansicht (unter Verwendung der EasyPeasy für Autolayout)

let scrollView = UIScrollView()
self.view.addSubview(scrollView)
scrollView <- [
    Edges(),
    Width().like(self.view)
]

let stackView = UIStackView(arrangedSubviews: yourSubviews)
stackView.axis = .vertical
stackView.distribution = .fill    
stackView.spacing = 10
scrollView.addSubview(stackView)
stackView <- [
    Edges(),
    Width().like(self.view)
]

Stellen Sie einfach sicher, dass jede Höhe Ihrer Unteransicht definiert ist!

0
dOM

Horizontales Scrollen (UIStackView in UIScrollView)

Zum horizontalen Scrollen. Erstellen Sie zunächst eine UIStackView und eine UIScrollView und fügen Sie sie auf folgende Weise Ihrer Ansicht hinzu:

let scrollView = UIScrollView()
let stackView = UIStackView()

scrollView.addSubview(stackView)
view.addSubview(scrollView)

Denken Sie daran, die translatesAutoresizingMaskIntoConstraints auf false für die UIStackView und die UIScrollView zu setzen:

stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false

Damit alles funktioniert, müssen die nachlaufenden, führenden, oberen und unteren Anker der UIStackView den UIScrollView-Ankern entsprechen:

stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

Der Breitenanker der UIStackView muss gleich oder größer als die Breite des UIScrollView-Ankers sein:

stackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor).isActive = true

Verankern Sie nun Ihre UIScrollView, zum Beispiel:

scrollView.heightAnchor.constraint(equalToConstant: 80).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true

scrollView.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo:view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo:view.trailingAnchor).isActive = true 

Als Nächstes würde ich vorschlagen, die folgenden Einstellungen für die Ausrichtung und Verteilung von UIStackView auszuprobieren:

topicStackView.axis = .horizontal
topicStackView.distribution = .equalCentering
topicStackView.alignment = .center

topicStackView.spacing = 10

Schließlich müssen Sie die addArrangedSubview:-Methode verwenden, um Ihrer UIStackView Subviews hinzuzufügen.

Texteinfügungen

Eine zusätzliche Funktion, die Sie möglicherweise als nützlich erachten, ist die Tatsache, dass Sie nun auf Texteinfügungen zugreifen können, da die Variable UIStackView in einer Variable UIScrollView enthalten ist, um die Dinge ein bisschen schöner aussehen zu lassen.

let inset:CGFloat = 20
scrollView.contentInset.left = inset
scrollView.contentInset.right = inset

// remember if you're using insets then reduce the width of your stack view to match
stackView.widthAnchor.constraint(greaterThanOrEqualTo: topicScrollView.widthAnchor, constant: -inset*2).isActive = true
0
sketchyTech
  1. Gestalten Sie in erster Linie Ihre Ansicht, vorzugsweise in etwas wie Sketch, oder machen Sie sich eine Vorstellung davon, was Sie als scrollbaren Inhalt wünschen.

  2. Danach machen Sie den View-Controller frei (wählen Sie aus dem Attribut Inspektor) und legen Sie die Höhe und Breite gemäß dem Inhalt fest Größe Ihrer Ansicht (kann vom Größeninspektor ausgewählt werden).

  3. Danach in den View-Controller eine Scroll-Ansicht eingefügt, und dies ist eine -Logik, die ich in iOS fast immer gearbeitet habe (es kann erforderlich sein, die Dokumentation dieser View-Klasse durchzusehen, die man per Befehl erhalten kann + klick auf diese Klasse oder über googeln)

    Wenn Sie mit zwei oder mehr Ansichten arbeiten, beginnen Sie zuerst mit einer Ansicht, die zuvor eingeführt wurde oder primitiver ist, und wechseln Sie dann zu der Ansicht, die später eingeführt wurde oder die moderner ist. Da hier die Bildlaufansicht zuerst eingeführt wurde, beginnen Sie zuerst mit der Bildlaufansicht, und wechseln Sie dann zur Stapelansicht. Setzen Sie hier die Scroll-Ansichtseinschränkungen in alle Richtungen gegenüber der Superansicht auf Null. Fügen Sie alle Ihre Ansichten in diese Bildlaufansicht und dann in die Stapelansicht ein.

Während der Arbeit mit der Stapelansicht 

  • Beginnen Sie zuerst mit Gründen nach oben (Bottom-Up-Ansatz), dh, wenn Sie Beschriftungen, Textfelder und Bilder in Ihrer Ansicht haben, legen Sie diese Ansichten zuerst (in der Bildlaufansicht) und anschließend in die Stapelansicht. 

  • Danach Tweak die Eigenschaft der Stack-Ansicht. Wenn die gewünschte Ansicht immer noch nicht erreicht wird, verwenden Sie eine andere Stapelansicht. 

  • Wenn immer noch nicht erreicht wird, spielen Sie mit der Priorität der Komprimierungsresistenz oder des Inhalts.
  • Danach fügen Sie der Stack-Ansicht Einschränkungen hinzu.
  • Denken Sie auch an die Verwendung einer leeren UIView als Fülleransicht, wenn alle oben genannten Ergebnisse nicht zufriedenstellend sind.

Nachdem Sie Ihre Ansicht erstellt haben, setzen Sie eine Einschränkung zwischen der Mutterstapelansicht und der Bildlaufansicht, während die Kinder-Stapelansicht die Zwangsstapelansicht mit der Mutterstapelansicht . Hoffentlich sollte es funktionieren, oder Sie erhalten eine Warnung von Xcode, die Vorschläge enthält , lesen Sie, was es sagt und setzen Sie diese um. Hoffentlich sollten Sie jetzt eine funktionierende Sicht haben, wie es Ihren Erwartungen entspricht :).

0
Nikhil Pandey

Wenn jemand nach horizontalem Bildlauf sucht

func createHorizontalStackViewsWithScroll() {

 self.view.addSubview(stackScrollView)
 stackScrollView.translatesAutoresizingMaskIntoConstraints = false
 stackScrollView.heightAnchor.constraint(equalToConstant: 85).isActive = true
 stackScrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
 stackScrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
 stackScrollView.bottomAnchor.constraint(equalTo: visualEffectViews.topAnchor).isActive = true
 stackScrollView.addSubview(stackView)

 stackView.translatesAutoresizingMaskIntoConstraints = false
 stackView.topAnchor.constraint(equalTo: stackScrollView.topAnchor).isActive = true
 stackView.leadingAnchor.constraint(equalTo: stackScrollView.leadingAnchor).isActive = true
 stackView.trailingAnchor.constraint(equalTo: stackScrollView.trailingAnchor).isActive = true
 stackView.bottomAnchor.constraint(equalTo: stackScrollView.bottomAnchor).isActive = true
 stackView.heightAnchor.constraint(equalTo: stackScrollView.heightAnchor).isActive = true

 stackView.distribution = .equalSpacing
 stackView.spacing = 5
 stackView.axis = .horizontal
 stackView.alignment = .fill


 for i in 0 ..< images.count {
 let photoView = UIButton.init(frame: CGRect(x: 0, y: 0, width: 85, height: 85))
 // set button image
 photoView.translatesAutoresizingMaskIntoConstraints = false
 photoView.heightAnchor.constraint(equalToConstant: photoView.frame.height).isActive = true
 photoView.widthAnchor.constraint(equalToConstant: photoView.frame.width).isActive = true

 stackView.addArrangedSubview(photoView)
 }
 stackView.setNeedsLayout()

 }
0
user1039695