iPhone: UITableView-Suchleiste standardmäßig ausblenden


85

Ich habe den Interface Builder verwendet, um eine Tabellenansicht zu erstellen, zu der ich die Suchleiste und den Search Display Controller der Bibliothek hinzugefügt habe, um Suchfunktionen hinzuzufügen. IB hat es jedoch so eingerichtet, dass die Leiste oben auf dem Bildschirm sichtbar ist, wenn die Ansicht zum ersten Mal angezeigt wird.

Ich möchte wissen, wie die Suchleiste standardmäßig ausgeblendet wird, aber dennoch mit der Tabellenansicht gescrollt werden kann (ein Beispiel finden Sie in der Mail-Anwendung von Apple). Ich habe versucht Aufruf scrollRectToVisible:animated:in viewDidLoaddie Tabellen - Ansicht nach unten scrollen , aber ohne Erfolg. Was ist die bevorzugte Methode, um die Suchleiste standardmäßig auszublenden?

Antworten:


116

Stellen Sie zunächst sicher, dass Sie die UISearchBar zur tableHeaderView der UITableView hinzufügen, damit sie mit dem Inhalt der Tabelle gescrollt wird und nicht am oberen Rand der Ansicht fixiert ist.

Die Suchleiste wird in der Tabellenansicht nicht als Zeile gezählt. Wenn Sie also oben in der Tabellenansicht zur ersten Zeile scrollen, wird die Suchleiste ausgeblendet:

[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];

oder in Swift:

yourTableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: false)

scrollToRowAtIndexPathStellen Sie sicher, dass Sie nicht durch die Tabellenansicht scrollen, bevor sie Daten enthält ( löst eine Ausnahme aus, wenn der angegebene Indexpfad nicht auf eine gültige Zeile verweist (dh wenn die Tabellenansicht leer ist)).


12
Tatsächlich tritt ein Problem auf, bei dem die Tabellenansicht nicht gescrollt wird, wenn nicht genügend Zeilen vorhanden sind, um den Bildschirm auszufüllen. In einer Tabelle mit einer oder zwei Zeilen führt dieser Code nichts aus. Ist das erwartetes Verhalten? Kann ich es irgendwie umgehen?
Tim

18
Ich habe einen Weg gefunden: Anstatt zu einem Indexpfad zu scrollen, ändern Sie den Inhaltsversatz der Bildlaufansicht der Tabelle in einen CGRect bei 0.0, 44.0
Tim

107
Tim, das ist der richtige Weg! Ich habe self.tableView.contentOffset = CGPointMake verwendet (0, self.searchDisplayController.searchBar.frame.size.height);
Joe D'Andrea

1
Übrigens - als ich diesen Code nach einem Aufruf von [tableView reloadData] einfügte, wodurch meine Tabelle von 2 Zeilen auf genügend Zeilen verschoben wurde, um ein normales Scrollen zu ermöglichen, stellte ich fest, dass die Verwendung der contentOffset-Methode ein ruckartiges Ein- und Ausblenden der Suche verursachte Box hatte bei Verwendung der scrollToRowAtIndexPath-Methode nicht das gleiche Ruckeln.
Chris R

1
Dies ist der einzige ultimative Weg, der unter JEDEN Umständen funktioniert. Die Einstellung contentOffsetmit einem beliebigen Wert wird unterbrochen, wenn Sie ein komplexes View-Controller-Layout verwenden. Ich empfehle es nicht.
Eonil

45

Fügen Sie die UISearchBar nicht als Unteransicht der UITableView hinzu, dies ist nicht erforderlich.

Die UITableView verfügt über eine tableHeaderView-Eigenschaft, die dafür perfekt geeignet ist:

- (void) viewDidLoad {
    [super viewDidLoad]; 
    self.searchBar = [[[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)] autorelease];
    self.searchBar.showsCancelButton = YES;    
    self.searchBar.delegate = self;
    self.tableView.tableHeaderView = self.searchBar;     
}

Wenn Sie es nicht standardmäßig sehen möchten:

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.tableView setContentOffset:CGPointMake(0, 44)];
}

Ich bekomme auch die Schaltfläche Abbrechen, um es wieder auszublenden .... (und entfernen Sie die Tastatur)

- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar {
    [self.tableView setContentOffset:CGPointMake(0, 44) animated:YES];
    [self.searchBar resignFirstResponder];
}

Für mich war dies die einzige Lösung, die eine versteckte UISearchBar-Implementierung hervorbrachte, die sich wie im Einklang mit der HIG anfühlte. Die anderen Lösungen, bei denen es oben in der Tabellenansicht "hängen bleibt", fühlen sich unnatürlich an.
Kurtzmarc

1
Diese Lösung hat am besten funktioniert. Dies sollte meiner Meinung nach die Antwort sein.
Darwindeeds

Diese Lösung ist schön (+1). In einigen Fällen versteckt tableView die Suchleiste jedoch nicht richtig (in meinem Fall: Wenn der Tableview-Controller von einem anderen View-Controller zurückgeschoben wird). Es gibt eine Frage zu diesem Problem: stackoverflow.com/questions/15222186/… Ich denke, die Antwort auf diese Frage ist jedoch nicht ganz gut. @bandejapaisa, hast du eine Idee?
Brian

3
Dies hat bei mir gut funktioniert, obwohl ich anstelle der durchgängigen Hardcodierung 44 die Verwendung von self.tableView.tableHeaderView.frame.size.height in viewWillAppear vorschlage, um Änderungen zu berücksichtigen, die Apple möglicherweise in Zukunft an der Höhe der Suchleiste vornehmen wird.
John Stephen

Dies viewWillAppeareinzufügen ist eine schlechte Idee, da es jedes Mal ausgeführt wird, wenn Sie zurück zu Ihrer Ansicht navigieren. Dies bedeutet, dass Ihre Tabellenansicht langsam nach unten geht. Irritierender Bug!
Sirenen

25

Das contentOffset wurde in den Kommentaren von Tim und Joe D'Andrea vermerkt, dies wird jedoch durch Hinzufügen einer Animation zum Ausblenden der Suchleiste etwas erweitert. Mir ist aufgefallen, dass es etwas unerwartet ist, dass die Suchleiste einfach verschwindet.

Versuchen Sie Folgendes, ein kleines Update für diejenigen, die auf iOS 4.0 und höher abzielen möchten:

[UIView animateWithDuration:0.4 animations:^{
    self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height);
 } completion:nil];

Vorherige Antwort:

[UIView beginAnimations:@"hidesearchbar" context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationBeginsFromCurrentState:YES];

self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height);

[UIView commitAnimations];


9
Ich habe festgestellt, dass die Animation der Schlüssel zu dieser Lösung ist. Der Versuch, den Inhaltsversatz ohne die Animation einzustellen, scheint nichts zu bewirken. Anstatt jedoch die Animationsmethoden (oder -blöcke) in diesem Beispiel zu verwenden, funktioniert das Aufrufen von [self.tableView setContentOffset: CGPointMake (0,44) animiert: TRUE] gut genug.
Quickthyme

Ohne die Animation scheint es überhaupt nicht zu funktionieren. @quickthyme hat die gleiche Beobachtung gemacht.
Thilo

5
Ich hatte Erfolg damit, ohne die Animationen zu benötigen, wenn Sie es viewDidAppear:stattdessen implementieren viewDidLoad.
wbyoung

8

Es gibt viele Antworten auf diese Lösung, aber keine hat für mich sehr gut funktioniert.

Das funktioniert perfekt. Keine Animation und wird erledigt-viewDidLoad

 - (void)viewDidLoad {
     [super viewDidLoad];
     self.tableView.contentOffset = CGPointMake(0,  self.searchBar.frame.size.height - self.tableView.contentOffset.y);
 }

Hinweis:

Code setzt voraus, dass Sie das haben, searchBar @propertywas mit der Suchleiste verknüpft ist. Wenn nicht, können Sie self.searchDisplayController.searchBarstattdessen verwenden


Dies ist der einzige, der für mich gearbeitet hat! , aber es wird nur un viewdidload ... also zum ersten Mal ausgeblendet, aber dann nicht mehr ausgeblendet, während die App ausgeführt wird. Und ich habe versucht, es in viewwillappear und viewdidappear zu setzen, aber es funktioniert falsch. Vielen Dank!
fguespe

@fguespe das ist seltsam .. Die viewDidLoad sollte jedes Mal aufgerufen werden, wenn die Ansicht instanziiert wird. Mir ist nie passiert, dass die UISearchBar sichtbar war, nachdem ich aus einer anderen Ansicht zurückgekehrt war.
Matej

Ich benutze eine Anwendung mit Registerkarten. Vielleicht das?
fguespe

@fguespe Ich sehe, das könnte das Problem sein, hmm. Leider bin ich mir nicht sicher, wie Sie das lösen sollen, wenn -viewWillAppeares nicht funktioniert. Wird es aufgerufen, wenn der Tab-Controller zur Ansicht wechselt?
Matej

viewwillappear und viewdidappear werden aufgerufen, aber ich habe es mit beiden versucht und die Ansicht ist wie falsch versetzt. Das erwartete Ergebnis wird nicht zurückgegeben. Ich meine, etwas tut es, aber es tut es schlecht.
fguespe

7

Für Swift 3+

Ich war das:

Erklären Sie dies var:

    var searchController = UISearchController()

Und in der viewDidLoad()Methode

    searchController = UISearchController(searchResultsController: nil)
    searchController.searchResultsUpdater = self
    searchController.hidesNavigationBarDuringPresentation = false
    searchController.dimsBackgroundDuringPresentation = true
    searchController.searchBar.placeholder = NSLocalizedString("Search", comment: "")
    definesPresentationContext = true
    tableView.tableHeaderView = searchController.searchBar

    tableView.contentOffset = CGPoint(x: 0, y: searchController.searchBar.frame.size.height)

5

Mein Ziel war es, die zu tableHeaderView hinzugefügte Suchleiste des einfachen TableView-Stils im Storyboard auszublenden, wenn der View-Controller geladen ist, und die Leiste anzuzeigen, wenn der Benutzer oben in UITableView nach unten scrollt. Also benutze ich Swift und habe eine Erweiterung hinzugefügt:

extension UITableView {
    func hideSearchBar() {
        if let bar = self.tableHeaderView as? UISearchBar {
            let height = CGRectGetHeight(bar.frame)
            let offset = self.contentOffset.y
            if offset < height {
                self.contentOffset = CGPointMake(0, height)
            }
        }
    }
}

In viewDidLoad () rufen Sie einfach auf:

self.tableView.hideSearchBar()

5

Alle vorhandenen Lösungen funktionieren unter iOS 8 nicht, wenn nicht genügend Zeilen vorhanden sind, um die Tabellenansicht zu füllen, da iOS den Einschub in dieser Situation automatisch anpasst. (Bestehende Antworten sind gut, wenn genügend Zeilen vorhanden sind.)

Nachdem ich ungefähr 6 Stunden mit diesem Problem verschwendet hatte, bekam ich endlich diese Lösung.

Kurz gesagt, Sie müssen leere Zellen in die Tabellenansicht einfügen, wenn nicht genügend Zellen vorhanden sind. Daher ist die Inhaltsgröße der Tabellenansicht groß genug, damit iOS den Einschub nicht für Sie anpasst.

So habe ich es in Swift gemacht:

1.) Deklarieren Sie eine Variable minimumCellNumals Klasseneigenschaft

var minimumCellNum: Int?

2.) berechnen minimumCellNumund SET tableView.contentOffsetinviewWillAppear

let screenHeight = Int(UIScreen.mainScreen().bounds.height)

// 101 = Height of Status Bar(20) + Height of Navigation Bar(44) + Height of Tab Bar(49)
// you may need to subtract the height of other custom views from the screenHeight. For example, the height of your section headers.
self.minimumCellNum = (screenHeight - 103 - heightOfOtherCustomView) / heightOfYourCell
self.tableView.contentOffset = CGPointMake(0, 44)

3.) in tableView(tableView: UITableView, numberOfRowsInSection section: Int))

let numOfYourRows = YOUR LOGIC
if numOfYourRows > minimumCellNum {
    return numOfYourRows
} else {
    return minimumCellNum!
}

4.) Registrieren Sie eine leere Zelle mit dem selectionAttribut Noneim Storyboard und intableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)

if indexPath.row < numOfYourRows {
    return YOUR CUSTOM CELL
} else {
    let cell = tableView.dequeueReusableCellWithIdentifier("EmptyCell", forIndexPath: indexPath) as! UITableViewCell
    return cell
}

5.) in tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)

if tableView == self.tableView {
    if numOfYourRows < (indexPath.row + 1) {
        return
    }
    YOUR LOGIC OF SELECTING A CELL
}

Dies ist keine perfekte Lösung, aber es ist die einzige Problemumgehung, die unter iOS 8 wirklich für mich funktioniert. Ich würde gerne wissen, ob es eine bessere Lösung gibt.


Ich musste dies für iOS 11 tun. Das Festlegen von contentOffset allein funktionierte für iOS 9/10 für 0 oder mehr Zellen und auch für iOS 11 für 8+ Zellen. Alles andere erforderte diese Lösung. Gibt es einen Grund warum?
Tony

Ich denke, der erste Absatz dieses Beitrags erklärt, warum.
Brian

Ich habe den ersten Absatz verstanden, aber es war immer noch seltsam, dass er nur unter iOS 11 für mich "kaputt" war. Ich hätte ein ähnliches Verhalten für iOS 9, 10 und 11 erwartet, wenn die Anzahl der Zellen gleich ist (weniger als genug). Nochmals vielen Dank und Entschuldigung, dass Sie einen alten Beitrag veröffentlicht haben!
Tony

4

Keiner der oben genannten Punkte hat bei mir funktioniert, also nur für den Fall, dass jemand das gleiche Problem hat.

Ich habe searchBarwie tableHeaderViewauf einer gruppierten Tabelle unter iOS7 eingestellt. In viewDidLoadIch habe tableView.contentOffset = CGPointMake(0, 44);zu halten searchBarzunächst „versteckt“. Wenn der Benutzer einen searchBarBildlauf nach unten durchführt, wird dies angezeigt

Tor: Suchleiste beim Tippen auf die Schaltfläche Abbrechen ausblenden

Im searchBarCancelButtonClicked(searchBar: UISearchBar!)

Dies funktionierte nicht: [yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; tableView scrollte zu stark nach oben, was dazu führte, dass Zeile 0 hinter toolBar stand.

Das hat nicht funktioniert: tableView.ContentOffset = CGPointMake(0, 44) - nichts passiert

Das hat nicht funktioniert: tableView.ContentOffset = CGPointMake(0, searchBar.frame.size.height) - nichts passiert

Dies funktionierte nicht: tableView.setContentOffset(CGPointMake(0, 44), animated: true); Auch hier scrollte tableView zu stark nach oben, was dazu führte, dass Zeile 0 hinter toolBar stand.

Dies funktionierte teilweise: ging tableView.setContentOffset(CGPointMake(0, 0) aber titleForHeaderInSectionhinter toolBar

DAS ARBEITETE: tableView.setContentOffset(CGPointMake(0, -20)

Scheint nicht logisch, aber nur -20 hat es in die richtige Position gebracht


Sie sollten Ihre Punkte wirklich nicht hart codieren, warum verwenden Sie sie nicht CGRectGetHeight(searchBar.bounds)?
Zorayr

Ich denke, Sie müssen dies in viewDidLoad () / init () tun, wo kein Frame festgelegt wurde, damit Sie die Höhe der Suchleiste ermitteln können. Vielleicht sollten Sie es mit viewDidLayoutSubviews ()
Kaushil Ruparelia

Wenn das Laden der tableView noch nicht abgeschlossen ist, ContentOffsetfunktioniert keine der Lösungen
Maor

4

Content Offset ist der richtige Weg, funktioniert aber nicht 100% der Zeit.

Es funktioniert nicht, wenn estimatedRowHeighteine feste Zahl eingestellt ist. Ich kenne die Arbeit noch nicht. Ich habe ein Projekt mit den Problemen erstellt und mit Apple ein Radar erstellt .

Schauen Sie sich das Projekt an, wenn Sie schnell ein Beispiel für die Einrichtung wünschen.


1
Danke dir! Das war es, wonach ich gesucht habe. Du musst weit nach oben gehen.
user2387149

3

Beachten Sie, dass die akzeptierte Antwort abstürzt, wenn die Tabellenansicht keine Daten enthält. Das Hinzufügen zu viewDidLoad funktioniert unter bestimmten Umständen möglicherweise nicht.

[yourTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO]; // crashes if no rows/data

Fügen Sie stattdessen diese Codezeile hinzu:

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

    [yourTableView setContentOffset:CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height)];
}

2

Ehrlich gesagt, keine der Antworten hat das Problem wirklich gelöst (für mich). Wenn Ihre Tabellenansicht keine Zeilen enthält ODER die Zeilenhöhe unterschiedlich ist, reichen diese Antworten nicht aus.

Das einzige was funktioniert:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.tableView.contentOffset = (CGPoint){.y =  self.tableView.contentOffset.y + self.searchController.searchBar.frame.size.height};
}

Gute Lösung für das Offset-Problem. Funktioniert bei mir mit einem UINavigationController.
Andreas Kraft

1
Die Lösung funktioniert nicht, wenn die Anzahl der Zeilen nicht den gesamten Bildschirm abdeckt. Würden Sie eine Problemumgehung dafür kennen?
Zorayr

Ich bin mir nicht sicher, ob ich das vollständig verstehe. Dies funktioniert bei mir, wenn ich nur wenige Zeilen in der Tabelle habe. Ich verwende jedoch Folgendes : self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];.
p0lAris

2

Die scrollToRowAtIndexPathMethode verursacht einen Absturz, wenn die Tabelle keine Zeilen enthält.

UITableView ist jedoch nur eine Bildlaufansicht, sodass Sie den Inhaltsversatz einfach ändern können.

Dadurch wird überprüft, ob Sie etwas als tableHeaderView haben, und es wird davon ausgegangen, dass Sie einen Bildlauf durchführen, um es auszublenden

    if let searchHeight = tableView.tableHeaderView?.frame.height {
        tableView.setContentOffset(CGPoint.init(x: 0, y:searchHeight ), animated: false)
    }

1

Ich finde, dass die App "Notizen" keine Elemente suchen kann, wenn die Tabellenansicht leer ist. Also ich denke es benutzt nur-(void)addSubview:(UIView *)view , um eine leere Tabelle hinzuzufügen. Wenn Sie ein Element zu seinem Datenquellenarray hinzufügen, wird ein weiteres Stück Code ausgeführt, um tableView zu laden.

Meine Lösung lautet also:

if([self.arrayList count] > 0)
{
     [self.tableView reloadData];     //use jdandrea's code to scroll view when cell==nil in cellForRowAtIndexPath
     self.tableView.scrollEnabled = YES;
}
else
{
     tableBlank = [[UITableView alloc]initWithFrame:CGRectMake(0,0,320,416) style:UITableViewStylePlain] autorelease];
     tableBlank.delegate = self;
     tableBlank.dataSource = self;
     [self.view addSubview:tableBlank];
}

Hoffe das hilft :-)


1

Ändern Sie die Grenzen der tableView. Dies kann innerhalb viewDidLoadder Tabelle erfolgen. Außerdem müssen Sie sich keine Gedanken darüber machen, ob die Tabelle leer ist oder nicht (um die Ausnahme zu vermeiden).

CGRect newBounds = self.tableView.bounds;
newBounds.origin.y = newBounds.origin.y + self.searchBar.bounds.size.height;
self.tableView.bounds = newBounds;

Sobald der Benutzer in der Tabelle gescrollt hat, wird die Suchleiste angezeigt und verhält sich normal


1

Die anderen Antworten auf diese Frage funktionierten entweder überhaupt nicht, hatten ein merkwürdiges Verhalten, wenn die tableView 0 Zeilen hatte, oder sie haben die Bildlaufposition beim Hin- und Herwechseln zwischen übergeordneten und verschachtelten Werbebuchungen durcheinander gebracht. Dies hat bei mir funktioniert (das Ziel war es, die UISearchBar beim Laden auszublenden):

public override func viewWillAppear(animated: Bool) {        
    if self.tableView.contentOffset.y == 0 {
        self.tableView.contentOffset = CGPoint(x: 0.0, y: self.searchBar.frame.size.height) 
    }
}

Erläuterung
Immer das tableViewerscheint, ist dieser Code überprüft, ob die UISearchBar sichtbar ist (dh die yPosition der contentOffset, auch bekannt als Scroll - Position ist 0). Wenn dies der Fall ist, wird einfach die Höhe der Suchleiste nach unten gescrollt. Wenn die Suchleiste nicht sichtbar ist (denken Sie an eine größere Liste von Elementen in tableView), wird nicht versucht tableView, durch die Suchleiste zu scrollen , da dies die Positionierung beeinträchtigen würde, wenn Sie von einer verschachtelten Werbebuchung zurückkehren.

Randnotiz
Ich würde empfehlen, diesen Code in eine separate Methode einzufügen, um die Einzelverantwortung sicherzustellen und Ihnen die Wiederverwendbarkeit zu geben, ihn jederzeit in Ihrem Code aufzurufen.


1

Wenn Ihre Tabelle immer mindestens eine Zeile enthält, scrollen Sie einfach zur ersten Zeile der Tabelle, und die Suchleiste wird automatisch ausgeblendet.

let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)

self.tableView.selectRowAtIndexPath (firstIndexPath, animiert: false, scrollPosition: .Top)

Wenn Sie den obigen Code in viewDidLoad einfügen , wird ein Fehler ausgegeben , da die tableView noch nicht geladen wurde. Sie müssen ihn daher in viewDidAppear einfügen, da die tableView zu diesem Zeitpunkt bereits geladen ist.

Wenn Sie es auf viewDidAppear platzieren , wird es bei jedem Öffnen der tableView nach oben gescrollt.

Möglicherweise möchten Sie dieses Verhalten nicht, wenn die tableView geöffnet bleibt, z. B. wenn es sich um einen UITabBar View Controller handelt oder wenn Sie einen Übergang durchführen und dann zurückkehren. Wenn Sie nur möchten, dass es beim ersten Laden nach oben gescrollt wird, können Sie eine Variable erstellen, um zu überprüfen, ob es sich um ein anfängliches Laden handelt, sodass es nur einmal nach oben scrollt.

Definieren Sie zuerst eine Variable namens isInitialLoad in der View Controller-Klasse und setzen Sie sie auf "true":

var isInitialLoad = true

Überprüfen Sie dann, ob isInitialLoad in viewDidAppear true ist. Wenn dies der Fall ist, scrollen Sie nach oben und setzen Sie die Variable isInitialLoad auf false:

if isInitialLoad {
            let firstIndexPath = NSIndexPath(forRow: 0, inSection: 0)
            self.tableView.selectRowAtIndexPath(firstIndexPath, animated: false, scrollPosition: .Top)

            isInitialLoad = false
        }

1

Der folgende Code funktioniert für mich

self.tableView.contentOffset = CGPointMake(0.0, 44.0);

1

Ich habe versucht, den Inhaltsoffset und den scrollToIndexpath festzulegen, aber nichts hat zufriedenstellend funktioniert. Ich habe die Einstellung von tableHeaderView als searchBar aus viewDidLoad entfernt und sie wie unten in scrollview delegate festgelegt

override func scrollViewWillBeginDragging(scrollView: UIScrollView) {
    if scrollView.contentOffset.y < 0 && tableView.tableHeaderView == nil {
        tableView.tableHeaderView = searchController.searchBar
        tableView.setContentOffset(CGPointMake(0, scrollView.contentOffset.y + searchController.searchBar.frame.size.height), animated: false)
    }
}

Dies funktionierte wie ein Zauber. Die Einstellung für den Inhaltsversatz dient dem reibungslosen Scrollen


0

Vergessen Sie nicht, die Statusleiste und die Navigationsleiste zu berücksichtigen. Mein Table View Controller ist in einen Navigationscontroller eingebettet in viewDidAppear:

tableView.contentOffset = CGPointMake(0, -20) // -20 = 44 (search bar height) - 20 (status bar height) - 44 (navigation bar height)

arbeitete für mich.


0

Für Swift:

Machen Sie einfach den Inhalt der Tabellenansicht y versetzt, was der Höhe der Suchleiste entsprechen sollte.

self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height)

0

Swift 3

funktioniert auch mit leerem Tisch!

In meiner Umgebung lade ich benutzerdefinierte Zellen per XIB-Datei und die Zeilenhöhe wird automatisch festgelegt.

    override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        self.tableView.contentOffset = CGPoint(x: 0, y: self.tableView.contentOffset.y + self.searchController.searchBar.bounds.height)
}

0

Ich hatte ein ähnliches Problem. Die einzige Möglichkeit, dieses Problem zu lösen, bestand darin, einen Schlüsselwertbeobachter für die Eigenschaft UITableView contentOffset zu verwenden.

Nach einigem Debuggen wurde mir klar, dass das Problem nur auftritt, wenn der Inhalt der Tabellenansicht kleiner als die Tabellenansicht ist. Ich starte KVO, wenn ich auf viewWillAppear bin. Und Versandstopp KVO 0,3 Sekunden nach Erscheinen der Ansicht. Jedes Mal, wenn contentOffset auf 0.0 gesetzt wurde, reagiert KVO und setzt contentOffset auf die Höhe der Suchleiste. Ich stoppe KVO asynchron nach 0,3 Sekunden, da das Ansichtslayout contentOffset auch nach dem Anzeigen der Ansicht zurücksetzt.

- (void)viewWillAppear:(BOOL)animated {
  [super viewWillAppear:animated];
  [self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}

-(void)viewDidAppear:(BOOL)animated{
   __weak typeof (self) weakSelf = self;
   dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [weakSelf.tableView removeObserver:self forKeyPath:@"contentOffset"];});
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if ([keyPath isEqualToString:@"contentOffset"] && self.tableView.contentOffset.y == 0.0) {
       self.tableView.contentOffset = CGPointMake(0, CGRectGetHeight(self.tableView.tableHeaderView.frame));
    }
}

-(void)dealloc {
    [self.tableView removeObserver:self forKeyPath:@"contentOffset"];
}
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.