iOS 11 SearchBar in der Navigationsleiste

70

Mit iOS 11 hat Apple die UISearchBar neu gestaltet, indem die Ecken runder und die Höhe größer gemacht wurden. Das Hinzufügen einer UISearchBar zur Navigationsleiste ist ziemlich einfach, indem Sie sie einfach als Titelansicht des verwendeten Navigationsobjekts festlegen navigationItem.titleView = searchBar.

In iOS 11 scheint es jedoch nicht mehr wie erwartet zu funktionieren. Schauen Sie sich die Bildschirme an, auf denen wir das gleiche Setup mit iOS 10 und iOS 11 vergleichen

iOS 10 Geben Sie hier die Bildbeschreibung ein

iOS 11 Geben Sie hier die Bildbeschreibung ein

Sie können deutlich sehen, dass die Suchleiste die Navigationsleiste vergrößert, die Balkentasten jedoch nicht richtig ausgerichtet sind. Auch die Suchleiste nutzt den verfügbaren Platz auf der linken Seite nicht mehr.

Wenn Sie die Suchleiste in eine Wrapper-Ansicht einfügen , um die Abbrechen-Schaltfläche auf dem iPad wie hier beschrieben zu erhalten, wird die Schaltfläche Abbrechen in der UISearchBar nicht angezeigt nicht mehr scheint ebenfalls nicht mehr zu funktionieren, da die Suchleiste dann überhaupt nicht sichtbar ist.

Wenn jemand ähnliche Probleme hat oder bereits weiß, wie dies behoben / verbessert werden kann, wäre ich sehr dankbar.

Dies wurde mit Xcode 9 Beta 4 erstellt. Möglicherweise wird dieses Problem durch zukünftige Versionen behoben.

AKTUALISIEREN:

Da dies nicht behoben wird, haben wir uns für die folgende Lösung entschieden. Wir haben der NavBar ein neues UIBarButtonItem hinzugefügt, das dann einen neuen ViewController enthält, in dem wir nur eine Suchleiste und nichts anderes in die NavBar einfügen, was zu funktionieren scheint. Die Verwendung der ausgewählten Antwort ist möglicherweise die beste Lösung, da Apple mit iOS 11 möchte, dass wir dieses neue Design verwenden, auch wenn es uns nicht das ursprünglich gewünschte Ergebnis liefert. Eine andere Möglichkeit, dies zu lösen, könnte eine benutzerdefinierte Suchleiste sein, dies ist jedoch ein anderes Thema.

PatrickDotStar
quelle
Ich habe ein paar Stunden damit verbracht, das gleiche Problem zu lösen. Bitte überprüfen Sie meine Antwort hier: stackoverflow.com/a/53264329/3231194 :) Ich habe dies als Antwort gepostet, damit es leicht gesehen werden kann. Vielen Dank!
Glenn Posadas

Antworten:

52

In NavigationItem in iOS 11 gibt es eine neue searchController-Eigenschaft.

https://developer.apple.com/documentation/uikit/uinavigationitem/2897305-searchcontroller

Verwenden Sie so ...

if #available(iOS 11.0, *) {
     navigationItem.searchController = searchController
} else {
     // Fallback on earlier versions
     navigationItem.titleView = searchController?.searchBar
}

In Objective-C sieht die if-Anweisung folgendermaßen aus:

if (@available(iOS 11.0, *)) {

Wenn Sie unter iOS 11 nichts festlegen navigationItem.hidesSearchBarWhenScrolling = false, wird die Suchleiste möglicherweise zunächst ausgeblendet, es sei denn, der Benutzer scrollt nach unten, um sie anzuzeigen. Wenn Sie den Wert auf "false" setzen, wird er unter dem Titel gestapelt angezeigt, ohne dass der Benutzer einen Bildlauf durchführen muss.

Justin Domnitz
quelle
1
Meine Antwort ähnelt der Antwort von @cook, aber ich dachte, der Link und der Code könnten helfen, ein bisschen Klarheit zu schaffen.
Justin Domnitz
41
Dies führt nicht zu den ursprünglich beschriebenen Ergebnissen. Wenn Sie die Eigenschaft searchController verwenden, wird die Suchleiste unter der Navigation angezeigt.
Molanda
Dies funktioniert auf dem iPhone, aber auf dem iPad für mich nicht.
Starchand
Kennen Sie die Höhe der Navigationsleiste in diesem Fall? Wird es sich ändern?
technisch versierte
16

Sie können die Höhe von UISearchBar in iOS 11 ändern, indem Sie eine Einschränkung für Höhe 44 hinzufügen:

if #available(iOS 11.0, *) {
    searchBar.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
}
zgjie
quelle
Dies macht die obere und untere Lünette kürzer. Ich habe diese Objective-C-Lösung ausprobiert: [[self.notesSearchBar.heightAnchor ConstraintEqualToConstant: 44.0] setActive: YES], aber ich mag diese Lösung nicht, weil sie den oberen unteren Rand dünner und seltsamer macht.
coolcool1994
Das hat bei mir funktioniert. Es positioniert meine Suchleiste neu und behält das richtige Layout bei.
Christian Ascone
Dies ist jedoch die richtige Lösung, insbesondere wenn Sie mit Ihrer App sowohl auf iOS 10 als auch auf iOS 11
abzielen
Dies löst das Höhenproblem, behebt jedoch nicht das vom Autor angegebene Breitenproblem.
Delorean
4

Ich hatte das gleiche Problem und nach ein paar Tagen, in denen ich das Problem gegoogelt habe, fand ich diese Seite - https://translate.google.com/translate?hl=de&sl=zh-CN&u=http://www.jianshu.com/ p / 262f6e34a7d3 & prev = search .

Diese Seite führt zu diesem Git-Repo - https://github.com/DreamTravelingLight/searchBarDemo - Dieses Demo-Projekt zeigt, wie Sie mit titleView den alten Weg verwenden, um weiterhin eine SearchBar ohne Größenprobleme zu haben.

Die Schlüsselzeilen sind diese

_searchBar = [self addSearchBarWithFrame:CGRectMake(0, 0, kScreenWidth - 2 * 44 - 2 * 15, 44)];
UIView *wrapView = [[UIView alloc] initWithFrame:_searchBar.frame];
[wrapView addSubview:_searchBar];
self.navigationItem.titleView = wrapView;

Wenn Sie die UISearchBar in eine Ansicht einbetten und diese WrapView als titleView festlegen, hat die UISearchBar die von Ihnen festgelegte Größe und passt wie vorgesehen in die Navigationsleiste.

Danke, David

David Schechter
quelle
Warum kScreenWidth - 2 * 44 - 2 * 15?
Kepa Santos
3

Wenn Sie das native System wirklich in iOS 11+ verwenden möchten UISearchBar (und das Erstellen Ihrer benutzerdefinierten Komponenten vermeiden möchten) navigationBar, können Sie eine Containeransicht erstellen, damit Sie searchBardie vollständige Kontrolle über den Frame haben. Diese Containeransicht ist die Übersicht der von searchBarIhnen übergebenen Container .

Etwas wie:

class SearchBarContainerView: UIView {

    let searchBar: UISearchBar

    required init?(coder aDecoder: NSCoder) {
        searchBar = UISearchBar()
        super.init(coder: aDecoder)
    }

    init(searchBar: UISearchBar) {
        self.searchBar = searchBar
        super.init(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: 44.0))
        addSubview(searchBar)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        searchBar.frame = bounds
    }
}

Und dann:

let containerView = SearchBarContainerView(searchBar: searchController.searchBar)
containerView.frame.size.width = navigationController?.navigationBar.frame.size.width ?? 0.0
navigationItem.titleView = containerView

Beachten Sie, dass dies nur eine kurze Demo ist und nicht für navigationBarRahmenänderungen (Drehung des Displays usw.) bereit ist . Sie könnten das mit zB lösen autoresizingMask.

Jakub Truhlář
quelle
Das funktioniert! Auch das Aktualisieren von containerView.frame in override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { coordinator.animate(alongsideTransition: { // here }... } ist ausreichend.
Ethanhuang13
1

Ich denke, Sie müssen sich mit dem Festlegen der neuen UINavigationItem.searchController-Eigenschaft für Ihr UISearchController-Objekt befassen. Auf diese Weise erhalten Sie den neuen Effekt, wie er in Nachrichten angezeigt wird. Es sieht so aus, als ob das alte Verhalten einfach weg ist. Ich hoffe, ich liege falsch, aber die gesamte API wurde für 11 überarbeitet. Ich weiß, dass sie im Allgemeinen fehlerhaft ist, also werden wir bei neueren Betas und dem GM sehen, ob dies behoben wird. (Schreiben zum Zeitpunkt der Beta 6)

gekochtes Nick
quelle
1

Das hat mir geholfen:

    if ([self.navigationItem respondsToSelector:@selector(setSearchController:)])
    {
        [self.navigationItem performSelector:@selector(setSearchController:) withObject:self.searchController];
    }
    else
    {
        self.tableView.tableHeaderView = self.searchController.searchBar;
    }
Raunak
quelle
0

Ich habe es mit ausprobiert searchControllerund searchBarfestgestellt, dass searchBares meinen Anforderungen entspricht (Suche durch Klicken auf die Schaltfläche "Suchen").

-(void)searchBarSetUp{
//Search button to reload the radio content.
self.searchButton.action = @selector(addSearchBarToNavigationTitleView);
self.searchButton.target = self;

//search bar initialization
searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];
searchBar.delegate = self;
searchBar.showsCancelButton = YES;
[searchBar sizeToFit]; }

-(void)addSearchBarToNavigationTitleView {
// Install the search bar as the table header.
self.navigationItem.titleView = searchBar;}

Auch ich hatte Schwierigkeiten, mit dem schwarzen Bildschirm umzugehen, wenn ich ihn benutze searchControl.

Kalpa
quelle
0

Machen Sie eine Zusammenfassung in iOS 14+

Zuerst, um den Druck zu beheben, verursachen Sie zusätzliche Höhe:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    navigationController?.view.setNeedsLayout() // force update layout
    navigationController?.view.layoutIfNeeded() // to fix height of the navigation bar
}

Zweitens, um Pop auf Ursprungshöhe zu fixieren:

extendedLayoutIncludesOpaqueBars = true

Alle oben genannten Codes in der Steuerung mit Suchleiste eingestellt.

Yuanjilee
quelle