UIScrollView scrollt nicht


128

Ich habe eine, UIScrollViewdie viele UIImageViews, UILabels usw. enthält. Die Beschriftungen sind viel länger als die UIScrollView, aber wenn ich die App starte, kann ich nicht klicken und nach unten scrollen ...

Warum könnte das sein?

Vielen Dank


Neu 26.03.2013 Ich bin auf einen einfacheren Weg gestoßen, dies ohne Code zu tun (Einstellung contentSize) stackoverflow.com/a/15649607/1705353
Dickey Singh

Antworten:


169

Es ist immer gut, ein vollständiges Arbeitscode-Snippet anzuzeigen:

// in viewDidLoad (if using Autolayout check note below):

UIScrollView *myScrollView;
UIView *contentView;
// scrollview won't scroll unless content size explicitly set

[myScrollView addSubview:contentView];//if the contentView is not already inside your scrollview in your xib/StoryBoard doc

myScrollView.contentSize = contentView.frame.size; //sets ScrollView content size

Swift 4.0

let myScrollView
let contentView

// scrollview won't scroll unless content size explicitly set

myScrollView.addSubview(contentView)//if the contentView is not already inside your scrollview in your xib/StoryBoard doc

myScrollView.contentSize = contentView.frame.size //sets ScrollView content size

Ich habe keine Möglichkeit gefunden, contentSize in IB (ab Xcode 5.0) festzulegen .

Hinweis: Wenn Sie Autolayout verwenden, befindet sich der beste Ort zum Einfügen dieses Codes in der -(void)viewDidLayoutSubviewsMethode.


12
Vergessen Sie nicht, myScrollView.delegate = selfAUCH einzustellen , wenn dies immer noch nicht funktioniert, hat die Antwort unter diesem einen GROSSEN Rat (gehen Sie zu Ihrem xib / StoryBoard und stellen Sie sicher, dass "AutoLayout" deaktiviert ist). Pro-Tipp: Sie können auch <UIScrollViewDelegate>in Ihre .h-Datei aufnehmen, wenn Sie beispielsweise programmgesteuert durch Ihre UIScrollView scrollen möchten.
Albert Renshaw

1
@ AlbertRenshaw, du hättest eine Antwort hinzufügen sollen, damit ich dir eine +1 hätte geben können :) AutoLayout war das Problem bei mir ... hat mich 4 Stunden lang verrückt gemacht.
Logixologe

2
Durch das Einfügen von Code viewDidLayoutSubviewshat es für mich funktioniert.
Amr Lotfy

Für mich war das Problem, dass es nicht scrollen musste, da alles auf den Bildschirm passte.
Daniel Springer

122

Wenn Sie die Ansicht auch nach korrekter Einstellung von contentSize nicht scrollen können, deaktivieren Sie im Interface Builder -> File Inspector das Kontrollkästchen "AutoLayout verwenden".


164
Alternativ können Sie contentSize in viewDidLayoutSubviews: festlegen. Diese wird nach Abschluss des automatischen Layouts angewendet.
Chris Vasselli

2
@ "Chris Vasselli" schob meine Ausgabe .. GR8 .. :-)
Ayaz

3
Chris 'Kommentar sollte eine separate Antwort sein!
Ninjaneer

1
Vielen Dank Chris Vasselli! Wenn das automatische Layout aktiviert ist, funktioniert es nicht in viewDidLoad, aber mit viewDidLayoutSubviews!
Romain

1
Woah, ich habe all diese Kommentare noch nie bemerkt! Ich bin froh, dass ich so vielen von euch helfen konnte! Ich habe gerade eine separate Antwort gepostet, damit es hoffentlich leichter zu finden ist.
Chris Vasselli

68

Sie müssen die contentSizeEigenschaft der Bildlaufansicht festlegen , damit sie ordnungsgemäß gescrollt wird.

Wenn Sie automatisches Layout verwenden, müssen Sie Satz contentSizein , viewDidLayoutSubviewsum es nach dem automatischen Layout abgeschlossen ist angewandt werden.

Der Code könnte folgendermaßen aussehen:

-(void)viewDidLayoutSubviews
{
    // The scrollview needs to know the content size for it to work correctly
    self.scrollView.contentSize = CGSizeMake(
        self.scrollContent.frame.size.width,
        self.scrollContent.frame.size.height + 300
    );
}

Vielen Dank. Dies hat funktioniert, weil aus irgendeinem Grund, selbst wenn ich den Wert von contentSizeauf contentViewdie Größe von setze, die Größe von scrollView und contentView gleich zu sein scheint. Aber wenn Sie die Höhe von contentSizeauf einen Wert einstellen, der größer als die Höhe von ist contentView, hat es funktioniert.
Skywalker

viewDidLayoutSubviewskann während eines Lebenszyklus mehrmals aufgerufen werden, sodass Sie das Risiko eingehen, die Höhe größer als erwartet zu erhöhen.
anon_nerd

@anon_nerd überprüfe einfach, ob es bereits aufgerufen wurde und füge nur dann die Höhe hinzu, wenn nicht
Daniel Springer

45

Die obige Antwort ist richtig - um das Scrollen zu ermöglichen, muss die Inhaltsgröße festgelegt werden.

Wenn Sie den Interface Builder verwenden, können Sie dies mit benutzerdefinierten Laufzeitattributen tun. Z.B:

Geben Sie hier die Bildbeschreibung ein


das hat nichts für mich getan.
coolcool1994

4
Hoppla, das Bild zeigt {0, 0}, aber Sie müssen natürlich genügend Zahlen eingeben. . Dieser Ansatz funktioniert nur für einfache Ansichten, bei denen Sie die Größe des Inhalts im Voraus kennen. . . (Tatsächlich empfehle ich für komplexe Ansichten ohnehin reinen Code).
Jasper Blues

Viel weniger hacky als programmgesteuert. Danke dir!
Jake Stoeffler

1
@ JakeStoeffler willkommen! :) Wenn ich IB benutze, möchte ich die gesamte Konfiguration dort behalten (nicht fragmentiert). Aber wenn die Dinge komplex werden (wiederverwendbare Ansichts-Widgets; Modelladapter, Ebenenmanipulationen; CAAnimations usw.), bevorzuge ich vollständig programmatische Ansichten. . . flüssiger.
Jasper Blues

Ich habe dies versucht, funktioniert, wenn die Ansicht angezeigt wird, aber bei einer Änderung der Ausrichtung wird die auf dem obigen Bildschirm definierte Inhaltsgröße ignoriert und in meinem Protokoll wird angegeben, dass die Inhaltsgröße auf 0,0 zurückgesetzt ist. Irgendeine Idee, wie man das behebt?
Shoogle

40

Versuchen Sie, die Größe des Inhalts auf große Zahlen zu ändern. Ich konnte nicht verstehen, warum meine Bildlaufansicht nicht scrollt, selbst wenn die Inhaltsgröße größer als die Steuerelementgröße zu sein scheint. Ich habe festgestellt, dass wenn der Inhalt kleiner als nötig ist, er auch nicht funktioniert.

self.scrollView.contentSize = CGSizeMake(2000, 2000);

Anstelle von 2000 können Sie Ihre eigenen großen Zahlen eingeben. Und wenn es funktioniert, bedeutet dies, dass Ihre Inhaltsgröße beim Ändern der Größe nicht groß genug ist.

Der Delegat ist nicht erforderlich, damit die Bildlaufansicht funktioniert.


2
Genie - so einfach zu überprüfen, was los ist. Vielen Dank!
Der verrückte Schimpanse

13

Stellen Sie sicher, dass die contentSize-Eigenschaft der Bildlaufansicht auf die richtige Größe eingestellt ist (dh eine, die groß genug ist, um Ihren gesamten Inhalt zu erfassen).


1
muss ich das programmatisch machen? oder kann ich es in IB machen?
Markieren Sie

Wenn Sie IB verwenden, können Sie es von dort aus einstellen - siehe unten. . (Separate Antwort, damit ich Bilder einfügen kann).
Jasper Blues

7

Deaktivieren Sie "Autolayout verwenden", um den Trick für mich zu erledigen.

Umgebung: xCode 5.0.2 Storyboards ios7


5

In meinem Fall musste ich delaysContentTouchesauf true setzen , da die Objekte in der scrollView alle die Berührungsereignisse erfassten und sich selbst handhabten, anstatt die scrollView selbst damit umgehen zu lassen.


Ich habe das gleiche Problem. Das Problem für mich ist, dass Sie durch Aktivieren von delayContentTouches mit Zeichnungen von geringerer Qualität mit einem Apfelstift enden. Aber dies ist ein
Randfall

4

Legen Sie die contentSizeEigenschaft der UIScrollviewin- ViewDidLayoutSubviewsMethode fest. Etwas wie das

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    scrollView.contentSize = CGSizeMake(view.frame.size.width, view.frame.size.height)
}

3

Die Idee, warum die Bildlaufansicht nicht gescrollt wird, weil Sie die Inhaltsgröße für das Scrollen weniger als die Größe der Bildlaufansicht festgelegt haben, ist falsch. Sie sollten die Inhaltsgröße größer als die Größe Ihrer Bildlaufansicht festlegen, um beim Scrollen durch die Ansicht zu navigieren.

Die gleiche Idee beim Zoomen ist, dass Sie den Min- und Max-Wert für das Zoomen festlegen, der durch Zoomen angewendet wird.

herzlich willkommen :)


3

Eine kleine Ergänzung, alle oben genannten sind die tatsächlichen Gründe, warum Ihre Bildlaufansicht möglicherweise nicht gescrollt wird, aber manchmal kann dies sinnlos der Grund sein, insbesondere wenn die Bildlaufansicht über Code und nicht über IB hinzugefügt wird. Möglicherweise haben Sie Ihre Unteransichten zur übergeordneten Ansicht hinzugefügt und nicht zu In der Bildlaufansicht wird die Unteransicht nicht gescrollt

und halten Sie die Inhaltsgröße festgelegt und größer als der übergeordnete Ansichtsrahmen (duhh !!)


3

Ich habe es bei meinem ersten Versuch geschafft. Mit automatischem Layout und allem, kein zusätzlicher Code. Dann ging eine Sammlungsansicht Banane, stürzte zur Laufzeit ab, ich konnte nicht finden, was falsch war, also habe ich sie gelöscht und neu erstellt (ich verwende Xcode 10 Beta 4. Es fühlte sich wie ein Fehler an) und dann war das Scrollen weg. Die Sammlungsansicht funktionierte jedoch wieder!

Viele Stunden später ... das hat es für mich behoben. Ich hatte folgendes Layout:

UIView

  • Sicherer Bereich
  • Bildlaufansicht
    • Inhaltsansicht

Es ist alles in den Zwängen. Der sichere Bereich wird vom System automatisch definiert. Im schlimmsten Fall entfernen Sie alle Beschränkungen für Scroll- und Inhalt Ansichten und haben nicht haben IB Zurücksetzen / sie für Sie zu schaffen. Machen Sie sie manuell, es funktioniert.

  • Für die Bildlaufansicht habe ich Folgendes getan: Nachlauf / Oben an sicherem Bereich ausrichten. Gleiche Breite / Höhe zum sicheren Bereich .
  • Für die Inhaltsansicht habe ich Folgendes getan: Nachlauf / Führen / Oben / Unten an der Übersicht ausrichten (die Bildlaufansicht)

Grundsätzlich besteht das Konzept darin, dass die Inhaltsansicht zur Bildlaufansicht passt, die zum sicheren Bereich passt.

Aber als solches hat es nicht funktioniert. Die Inhaltsansicht hat die Höhe verfehlt. Ich habe alles versucht, was ich konnte, und der einzige, der diesen Trick ausführte, war eine Höhe der Inhaltsansicht, die durch Ziehen und Ziehen der Inhaltsansicht zu sich selbst erstellt wurde . Das definierte eine feste Höhe, deren Wert von der Größe des Ansichts-Controllers (definiert als Freiform, länger als die reale Anzeige, bis zum Enthalten aller meiner Unteransichten) berechnet wurde, und schließlich funktionierte es wieder!


Gern geschehen! Ich weiß genau, wie du dich gefühlt hast .. ;-)
Michele Dall'Agata

Thaaaaks, ich habe viele Stunden verbracht und dies hat mein Problem gelöst
Andoni Da Silva

3

Wenn Sie eine Nachricht (IOS8 / swift) erhalten, viewDidLayoutSubviewsdie nicht vorhanden ist, verwenden Sie stattdessen Folgendes

override func viewDidAppear(animated: Bool)

Das hat es für mich behoben


2

Etwas, das vorher nicht erwähnt wurde!

Stellen Sie sicher, dass Ihre Steckdose korrekt mit der scrollView verbunden ist! Es sollte einen gefüllten Kreis haben, aber selbst wenn Sie einen gefüllten Kreis haben, ist scrollView möglicherweise nicht verbunden - überprüfen Sie dies also noch einmal! Bewegen Sie den Mauszeiger über den Kreis und prüfen Sie, ob die tatsächliche Bildlaufansicht hervorgehoben wird! (Dies war ein Fall für mich)

//Connect below well to the scrollView in the storyBoard
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;

2

Die meiste Zeit ist der Code korrekt, wenn Sie einem Tutorial gefolgt sind, aber was viele Anfänger nicht wissen, ist, dass die scrollView NICHT normal durch den Simulator scrollen wird. Es wird angenommen, dass Sie nur scrollen, wenn Sie auf das Mauspad drücken und gleichzeitig scrollen. Viele erfahrene XCode / Swift / Obj-C-Benutzer sind daran gewöhnt und wissen nicht, wie dies möglicherweise von Anfängern übersehen werden kann. Ciao :-)

@IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(scrollView)
    // Do any additional setup after the view
}

override func viewWillLayoutSubviews(){
    super.viewWillLayoutSubviews()
    scrollView.contentSize = CGSize(width: 375, height: 800)
}

Dieser Code funktioniert einwandfrei, solange Sie das tun, was ich oben gesagt habe


1

Wenn keine der anderen Lösungen für Sie funktioniert, überprüfen Sie, ob Ihre Bildlaufansicht tatsächlich ein UIScrollViewInterface Builder ist.

Irgendwann in den letzten Tagen wechselte mein UIScrollView Typ spontan zu a UIView, obwohl seine Klasse dies UIScrollViewim Inspektor sagte . Ich benutze Xcode 5.1 (5B130a).

Sie können entweder eine neue Bildlaufansicht erstellen und die Messungen, Einstellungen und Einschränkungen aus der alten Ansicht kopieren oder Ihre Ansicht manuell in eine UIScrollViewin der xibDatei ändern . Ich habe einen Vergleich durchgeführt und folgende Unterschiede festgestellt:

Original:

<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" directionalLockEnabled="YES" bounces="NO" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wsk-WB-LMH">
...
</scrollView>

Nach spontan geändertem Typ:

<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" customClass="UIScrollView" id="qRn-TP-cXd">
...
</view>

Also habe ich die <view>Leitung durch meine ursprüngliche <scrollView>Leitung ersetzt.

Ich habe auch das Close-Tag der Ansicht </view>durch ersetzt </scrollView>.

Stellen Sie sicher, dass die ID mit der aktuellen Ansicht übereinstimmt. In diesem Fall gilt Folgendes: id = "qRn-TP-cXd".

Ich musste auch die xib aus dem Xcode-Cache leeren, indem ich die abgeleiteten Daten der App löschte:

  • Xcode->Window->Organizer->ProjectsWählen Sie Ihr Projekt aus und klicken Sie in der Zeile Abgeleitete Daten auf Löschen ...

Oder wenn Sie ein Gerät verwenden:

  • Xcode->Window->Organizer->Device, wählen Sie Ihr Gerät-> Anwendungen, wählen Sie Ihre App, klicken Sie auf (-)

Bereinigen Sie nun das Projekt und entfernen Sie die App aus dem Simulator / Gerät:

  • Xcode->Product->Clean
  • iOS Simulator/device->pressund halten Sie das app->click(X) gedrückt, um es zu entfernen

Sie sollten dann in der Lage sein, Ihre App zu erstellen und auszuführen und wieder über Bildlauffunktionen zu verfügen.

PS Ich musste nicht die Inhaltsgröße der viewDidLayoutSubviewsBildlaufansicht einstellen oder das automatische Layout deaktivieren, sondern YMMV.


1

Wenn es sich bei Ihrer scrollViewAnsicht um eine Unteransicht eines containerViewbestimmten Typs handelt, stellen Sie sicher, dass Sie scrollViewsich innerhalb des Rahmens oder der Grenzen von befinden containerView. Ich hatte das, containerView.clipsToBounds = NOwas mir immer noch erlaubte, die scrollView zu sehen, aber weil scrollViewes nicht innerhalb der Grenzen war , konnte ich containerViewkeine Berührungsereignisse erkennen.

Beispielsweise:

containerView.frame = CGRectMake(0, 0, 200, 200);
scrollView.frame = CGRectMake(0, 200, 200, 200);
[containerView addSubview:scrollView];
scrollView.userInteractionEnabled = YES;

Sie können die scrollView sehen, aber es werden keine Benutzerinteraktionen empfangen.


1

Das Hinzufügen des folgenden Codes viewDidLayoutSubviewshat bei mir mit Autolayout funktioniert. Nachdem Sie alle Antworten ausprobiert haben:

- (void)viewDidLayoutSubviews
{
    self.activationScrollView.contentSize = CGSizeMake(IPHONE_SCREEN_WIDTH, 620);

}

//set the height of content size as required

1

Fügen Sie den UIScrollViewDelegatehinzu und fügen Sie den folgenden Code zu der viewDidAppearMethode hinzu, die für mich behoben wurde.

@interface testScrollViewController () <UIScrollViewDelegate>

-(void)viewDidAppear:(BOOL)animated {
    self.scrollView.delegate = self;
    self.scrollView.scrollEnabled = YES;
    self.scrollView.contentSize = CGSizeMake(375, 800);
}

1

Mein Problem wurde behoben durch:

  1. Setzen Sie die contentSize in der scrollView auf eine große Höhe
  2. ABER ich musste auch die oberen und / oder unteren Einschränkungen für Ansichten in der scrollView korrigieren, was bedeutete, dass die Bildlaufanzeigen auf dem Bildschirm angezeigt wurden, der Inhalt jedoch nicht gescrollt wurde

Sobald ich die oberen und / oder unteren Einschränkungen entfernt habe, die an den sicheren Bereich und / oder die Übersicht gebunden sind, konnten die Ansichten in der scrollView erneut gescrollt werden und blieben nicht am oberen Rand des Bildschirms fixiert!

Ich hoffe, dies hält jemand anderen von stundenlangen Schmerzen mit diesem speziellen Problem ab.


1

Noch ein lustiger Fall:

scrollview.superview.userInteractionEnabled muss true sein

Ich habe mehr als 2 Stunden damit verbracht, dies zu verfolgen, um herauszufinden, dass es sich bei dem übergeordneten Element um UIImageView handelt, das natürlich userInteractionEnabled == false hat


0

Nachdem ich mit den Antworten in diesem Thread versagt hatte, stieß ich auf diesen Artikel mit der Lösung.

Es gibt zwei Dinge, die beim Einrichten der Bildlaufansicht mit Autolayout nicht intuitiv sind:

  1. Die Einschränkungen, die Sie als Rand zwischen der Inhaltsansicht und der Bildlaufansicht festgelegt haben, haben keinen Einfluss auf die Größe der Inhaltsansicht. Sie sind wirklich Margen. Damit dies funktioniert, sollte die Inhaltsansicht eine feste Größe haben.
  2. Der Trick bei der festen Größe besteht darin, dass Sie die Breite der Inhaltsansicht gleich der des übergeordneten Elements der Bildlaufansicht festlegen können. Wählen Sie einfach beide Ansichten im Baum links aus und fügen Sie die Einschränkung für gleiche Breiten hinzu.

Dies ist der Kern dieses Artikels. Eine vollständige Erklärung, einschließlich Abbildungen, finden Sie hier.


@PredragManojlovic Wie kann es allgemeiner werden? Dies ist die einzige Möglichkeit, die Bildlaufansicht mithilfe des automatischen Layouts ordnungsgemäß zum Laufen zu bringen.
H. de Jonge

0

Ich habe festgestellt, dass bei diesem AutoLayout-Problem ... wenn ich nur die ViewControllerVerwendung UIViewanstelle UIScrollViewder Klasse verwende ... dann füge einfach UIScrollViewselbst ein ... hinzu, dass es funktioniert.


0

Ich hatte das gleiche Problem in IB.

Nachdem Sie den führenden, nachfolgenden, oberen und unteren Rand der scrollView auf ihre superView gesetzt haben. Ich habe die folgenden Änderungen vorgenommen, um die containerView scrollbar zu machen, was funktioniert hat.

Um die scrollView nur in horizontaler Richtung zu scrollen, nehmen Sie die Einschränkung mit scrollViews centerY = ContainerViews centerY vor

und um es vertikal scrollbar zu machen, machen Sie das centerX von scrollView = das centerX von ContainerView

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.