webentwicklung-frage-antwort-db.com.de

iOS: Dehnen/Ändern der Größe des UITableView-Headers, wenn der Benutzer nach unten zieht?

Mit dem Storyboard habe ich einen imageView als tableView'sheaderView in einen ViewController gestellt.

So ist mein Storyboard aufgebaut:

enter image description here

Abhängig davon, welche Daten der Benutzer anzeigt, wird viewController entweder headerView angezeigt oder ausgeblendet. Meine Frage ist, dass, wenn das headerView sichtbar ist und der Benutzer das tableView herunterzieht, wie kann ich das imageView sowohl am navigationBar als auch am tableView haften lassen, wenn es den Raum dazwischen abdeckt?

Dies tut es derzeit:

enter image description here

Aber das ist was ich will:

enter image description here

Jede Hilfe wäre sehr dankbar. Ich habe mir Parallax-Bibliotheken angesehen, aber keine unterstützen sectionTitles, und ich werde nicht unbedingt den Parallax-Effekt anstreben. Wenn der Benutzer einen Bildlauf nach oben durchführt, möchte ich, dass er zur regularView zurückspringt und die headerView nicht versteckt. Vielen Dank!

AKTUALISIEREN:

Ich habe die Ratschläge von Dany unten befolgt und die folgende:

-(void)scrollViewDidScroll:(UIScrollView*)scrollView {

CGRect initialFrame = CGRectMake(0, 0, 320, 160);

if (scrollView.contentOffset.y < 0) {

    initialFrame.size.height =! scrollView.contentOffset.y;
    childHeaderView.frame = initialFrame;
} }

childHeaderView ist eine ImageView und aus irgendeinem Grund... Das Bild wird nach oben verschoben (wie die Hälfte hinter der navBar) und kehrt nicht zurück. Jeder Rat wäre sehr geschätzt!! Vielen Dank!

27
KingPolygon

Ich habe kürzlich in einem Blogpost einen Beitrag darüber geschrieben, wie man dies mit Hilfe von Einschränkungen erreicht, die helfen könnten.

Hier der Link: Erstellen eines Parallax-Effekts in UIScrollView mithilfe von Einschränkungen

7
petehare

Zunächst sollten Sie die Variable UIImageView aus der Kopfzeile entfernen und als einfache Variable __UIImageView über der Variable UITableView hinzufügen. Da das Protokoll UITableViewDelegate dem Protokoll UIScrollViewDelegate entspricht, können Sie die Methode scrollViewDidScroll: implementieren, um zu prüfen, wann die Variable tableView herunterrollt und einen Effekt bouncing hat . etwas wie das:

-(void)someInitMethod {
   initialFrame = yourHeaderView.frame;
}
-(void)scrollViewDidScroll:(UIScrollView*)scrollView {
    if(scrollView.contentOffset.y < 0) {
       initialFrame.size.height -= scrollView.contentOffset.y;
       yourHeaderView.frame = initialFrame;
    }
}

Stellen Sie außerdem sicher, dass Sie die richtige contentMode für Ihre UIImageView einstellen. Ich denke auch, dass diese Implementierung einen Bouncing-Effekt erzeugen wird, aber ich bin mir nicht sicher, weil ich sie momentan nicht testen kann, aber ich denke, das ist ein guter Ausgangspunkt für Sie.

5
danypata

So habe ich es erreicht, in meinem Fall benutzte ich oben eine Kartenansicht:

  1. Erstellen Sie einen Ansichts-Controller im Storyboard.
  2. Fügen Sie eine Tabellenansicht hinzu und setzen Sie die Einschränkungen von allen Seiten auf 0.
  3. Fügen Sie eine Kartenansicht (oder eine andere Ansicht) unter der Tabellenansicht hinzu, damit sie über dem oberen Rand gerendert wird. Es sieht so aus, als ob es sich überschneidet.
  4. Fügen Sie Einschränkungen oben links und rechts hinzu.
  5. Fügen Sie im View-Controller viewDidLoad Folgendes hinzu: tableView.contentInset = UIEdgeInsetsMake(200, 0, 0, 0) Dabei steht 200 für die Höhe der View. Dadurch wird der Inhalt der Tabellenansicht nach unten verschoben.
  6. Fügen Sie im View-Controller den folgenden Code hinzu, der die Größe der Ansicht basierend auf dem Bildlauf ändert:

    func scrollViewDidScroll(scrollView: UIScrollView) {
        var scrollOffset = scrollView.contentOffset.y
        var headerFrame = mapView.frame
        if (scrollOffset < 0) {
            // Adjust map
            headerFrame = CGRect(x: mapView.frame.Origin.x,
                y: mapView.frame.Origin.y,
                width: mapView.frame.size.width,
                height: -scrollOffset)
        } else {
            // Adjust map
            headerFrame = CGRect(x: mapView.frame.Origin.x,
                y: mapView.frame.Origin.y,
                width: mapView.frame.size.width,
                height: 0)
        }
        mapView.frame = headerFrame
    }
    

Wenn ich contentInset aus dem Storyboard setzen könnte, wäre das noch schöner

2
geometrikal

Die früheren Lösungen auf dieser Seite bereiteten mir einige Schwierigkeiten, als ich dies brauchte, um mit den Abschnittsüberschriften und der Indexleiste zusammenzuarbeiten. Daher habe ich selbst die folgende Alternative gefunden. Bitte beachten Sie; Ich verwende in meinem Projekt kein Autolayout, und ich habe dies nur unter iOS9 + getestet.

Im Storyboard deines Projekts:

  1. Erstellen Sie eine UITableView in einem UIViewController (oder versuchen Sie es mit einem UITableViewController).
  2. Legen Sie eine UIView oben (aber innerhalb) der UITableView ab, sodass sie zu einer Tabellenüberschrift über der ersten Zelle wird.
  3. Geben Sie dieser Kopfansicht eine gewünschte Höhe (z. B. 200px) und setzen Sie die Hintergrundfarbe auf "Farbe löschen". Die klare Farbe ist wichtig, die Ansicht muss durchsichtig sein.
  4. Legen Sie eine zweite UIView innerhalb der UIView-Kopfzeile der Tabelle ab und legen Sie dieselbe Größe wie die übergeordnete Tabelle fest. Dies ist die eigentliche Kopfzeile, Sie können also jede Farbe angeben, eine Bildansicht oder einen anderen Inhalt einrichten.
  5. Verbinden Sie diesen 2. UIView mit Ihrem UIViewController IBOutlet, ich habe ihn in meinem Fall "headerView" genannt.

Gehen Sie als Nächstes zu UIViewController.m:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Remove view from table header and place it in the background instead.
    [self.headerView removeFromSuperview];
    UIView *backgroundView = [UIView new];
    [backgroundView addSubview:self.headerView];
    self.tableView.backgroundView = backgroundView;
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    /* Set initialScrollOffset ivar to start offset, because in my case
       the scroll offset was affected by the statusbar + navigation bar heights
       and the view controller's "extend edges under top bars" option. */
    initialScrollOffset = self.tableView.contentOffset.y;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    /* Modify headerView height only if the table content gets pulled
       beyond initial offset. */
    if (scrollView.contentOffset.y < initialScrollOffset) {
        CGRect frame = self.headerView.frame;
        frame.size.height = self.tableView.tableHeaderView.frame.size.height + -scrollView.contentOffset.y;
        self.headerView.frame = frame;
    }
}

Diese Implementierung benötigte ich nur für einen Stretching-Header mit Hintergrundfarbe und Beschriftungen. Es sollte jedoch leicht sein, diesem Header eine UIImageView hinzuzufügen.

Die Schritte 1 bis 5 sind natürlich völlig optional. Sie können Ihre Kopfansicht programmgesteuert erstellen oder stattdessen eine XIB verwenden. Solange Sie sicherstellen, dass für die Tabelle eine Kopfzeilenansicht "Farbe löschen" mit derselben Höhe wie die gewünschte Kopfzeile festgelegt ist, wird diese als Abstandhalter verwendet, um die Zellen und Abschnittstitel in einer Linie zu halten.

BEARBEITEN:

Ich habe einen noch saubereren Weg gefunden, um dies zu erreichen.

  1. Erstellen Sie Ihren Tabellenheader im Interface Builder wie oben beschrieben: 1 UIView als Container mit einem zweiten eingebetteten UIView.
  2. Überspringen Sie den viewDidLoad-Code oben. Es ist nicht erforderlich, die UIView aus dem Container zu ziehen, und wir müssen sie nicht als Tabellenhintergrund festlegen.
  3. Ändern Sie die scrollViewDidScroll:-Methode folgendermaßen:

UIViewController.m:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
      if (scrollView.contentOffset.y < initialScrollOffset) {
           CGRect frame = self.headerView.frame;
           frame.size.height = self.tableView.tableHeaderView.frame.size.height - scrollView.contentOffset.y;
           frame.Origin.y = self.tableView.tableHeaderView.frame.Origin.y + scrollView.contentOffset.y;
           self.headerView.frame = frame;
    }
}

Das ist es. Der einzige visuelle Unterschied zu der anderen Lösung besteht darin, dass der Inhalt nun zusammen mit den übrigen Zellen nach oben gescrollt wird und nicht von ihnen überlappt wird.

1
Tonnie

Bitte schauen Sie sich diesen https://github.com/matteogobbi/MGSpotyViewController an , der den gleichen Effekt wie in Ihrer Anforderung implementiert.

1
Prabhu

Ich weiß nicht, ob das dir helfen würde oder nicht .. 

Stellen Sie Ihren Scroll-Delegaten auf "selbst".

und dann das implementieren:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    float scrollViewHeight = scrollView.frame.size.height;
    float scrollContentSizeHeight = scrollView.contentSize.height;
    float scrollOffset = scrollView.contentOffset.y;

    if (scrollOffset == 0)
    {
        // then we are at the top
    }
    else if (scrollOffset + scrollViewHeight == scrollContentSizeHeight)
    {
        // then we are at the end
        // Do what you need here 
    }
}
0
Islam Adel