2015-03-06 14 views
7

Buduję aplikację na iOS 8, która korzysta z nowego kontrolera UISearch. W widoku tabeli dotyczącym kontrolera wyszukiwania używam indeksu sekcji, aby umożliwić użytkownikom szybkie przechodzenie z jednej sekcji tabeli do drugiej. Działa dobrze, ale indeks sekcji pokrywa się z paskiem wyszukiwania w tabeli/kontrole wyszukiwania. Czy ktokolwiek napotkał ten problem wcześniej, a jeśli tak, to w jaki sposób go rozwiązałeś? Poniżej jest jak ja inicjalizacji mojego kontrolera wyszukiwarki:UISearchController: Indeks przekrojów UITableView pokrywa się z wyszukiwarkąBar

self.resultsTableController = [self.storyboard instantiateViewControllerWithIdentifier:[SelectSpecialtySearchResultsTVC storyboardId]]; 
UINavigationController *searchResultsNavController = [[UINavigationController alloc]initWithRootViewController:self.resultsTableController]; 
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsNavController]; 

self.searchController.searchResultsUpdater = self; 
self.searchController.hidesNavigationBarDuringPresentation = NO; 
self.searchController.searchBar.barTintColor = [UIColor colorWithHexString:kColorGrayLight]; 
self.searchController.searchBar.translucent = NO; 
self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, [self.view bounds].size.width, 44.0); 
self.searchController.searchBar.delegate = self; 

self.tableView.tableHeaderView = self.searchController.searchBar; 

//present the search display controller within the confines of this class's table view 
self.definesPresentationContext = YES; 

// we want to be the delegate for our filtered table so didSelectRowAtIndexPath is called for both tables 
self.resultsTableController.tableView.delegate = self; 
self.searchController.delegate = self; 

enter image description here

+1

Podejrzewam, że ma to coś wspólnego z faktem, że są instancji paska wyszukiwania i dodawania go do widoku nagłówka tabeli, dzięki czemu działa jak każdy inny nagłówku tabeli. Czy chcesz, aby pasek wyszukiwania pozostawał u góry widoku, lub znikał, gdy użytkownik przewija w dół tabeli? – andrewbuilder

+0

Pasek wyszukiwania obecnie znika, gdy użytkownik przewija, i uważam, że jest to pożądane zachowanie mojego zespołu. –

+0

Pomyślałem o tym jeszcze trochę po twoim komentarzu. Jeśli pomoże mi pozbyć się pokrywającego się indeksu, to posiadanie paska wyszukiwania na górze na przewijaniu jest dla mnie w porządku. Mam ochotę dodać pasek jako osobny widok (poza stołem), ale jeszcze nie wymyślę wygrywającego rozwiązania. –

Odpowiedz

1

W końcu udało się znaleźć akceptowalne rozwiązanie tego pytania. Ta odpowiedź opiera się na powyższym pytaniu (używam tego samego kodu minus to, co tutaj zostało zmienione). Najważniejszą rzeczą, na którą należy zwrócić uwagę, jest to, że @andrewbuilder miał rację - dodanie paska wyszukiwania jako widoku nagłówka tabeli zagwarantuje, że pasek wyszukiwania porusza się po przewijaniu; działa po prostu jak każdy inny widok nagłówka tabeli.

To co zrobiłem, było kombinacją rzeczy. Główną zmianą w moim podejściu była zmiana sposobu, w jaki mój główny kontroler prezentuje mój kontroler wyszukiwania. W szczególności przeszedłem od self.definesPresentationContext = YES; do self.definesPresentationContext = NO;

To, co robi, to zasadniczo przedstawia kontroler wyszukiwania na głównym ekranie, a nie w jego obrębie. Stwarza to kompromis projektowy polegający na tym, że musisz teraz zajmować się układem dwóch kontrolerów widoku, a nie tylko jednego. Ale było to coś, z czym byłem w porządku.

Następną rzeczą, którą zrobiłem, było stworzenie silnego wskaźnika do UISearchBar w moim głównym kontroler widoku, który nazwałem searchBar.Potem ustawić, że nieruchomość będzie równa searchBar moje wyszukiwanie sterownika i dodaje go do mojego podrzędny tak:

self.searchBar = self.searchController.searchBar; 
[self.view addSubview:self.searchBar]; 

w celu uzyskania tego, aby wyglądać dobrze, musiałem się upewnić, pozycja mojego stołu x była równa w dolnej części ramki paska wyszukiwania. Możesz to zrobić na wiele sposobów: albo w kodzie, w Konstruktorze interfejsu, albo w kombinacji obu. Zostawię ci, abyś sam wybrał właściwy wybór.

Tu znowu chodzi o to, że musisz skonfigurować dwa kontrolery widoku i sprawić, że będzie wyglądać tak samo, jak na tym samym ekranie, mimo że nie jest (dostosowywanie paska nawigacji, obsługa seguesów itp.). To wydaje się być koniecznym złem, które ja i mój zespół chcieliśmy zaakceptować. Stąd następnymi krokami w uzyskaniu tego wszystkiego działającego było zakłócanie właściwości edgesForExtendedLayout na obu kontrolerach widoku (a także contentInset widoków tabel). Nie będę tutaj pisać tego kodu, ponieważ prawdopodobnie będzie inny dla każdego w zależności od jego projektu. Jednak to jest sedno tego.

Nie krępuj się dodać do tego tematu, jeśli znajdziesz prostsze rozwiązanie. Szukałem daleko i szeroko, ale z UISearchController jest bardzo nowy kontroli, nie ma wiele dokumentacji/informacji na ten temat (i jego dziwactw).

1

jakie miałem podobne obawy budowanie widok tabeli, która zawiera pasek wyszukiwania.

Spróbuj zmienić wygląd następujących właściwości ... może to pomóc w znalezieniu odpowiedniego rozwiązania.

Jeśli używasz interfejsu Konstruktor/storyboard, w atrybucie Inspektor ustawić pasek wyszukiwania z następującymi właściwościami:

  • Search style = Minimal
  • Bar style = Domyślny
  • Translucent = TAK
  • Bar Odcień = Domyślny

Storyboard Attribute Inspector

Właściwości te można oczywiście ustawić w kodzie:

self.searchController.searchBar.searchBarStyle = UISearchBarStyleMinimal; 
self.searchController.searchBar.barStyle = UIBarStyleDefault; 
self.searchController.searchBar.translucent = NO; 
// By not setting the barTintColor property, it remains default 
// self.searchController.searchBar.barTintColor = [UIColor yourColor]; 

Następnie w tabeli kodu widok kontrolera ustaw następujące UITableView właściwości:

// Prepare custom colours as needed 
UIColor *brightBlueColour = [UIColor colorWithRed:0.40 green:0.90 blue:1.00 alpha:1.00]; 

// Set section index properties for your table view 
[yourTableView setSectionIndexColor:[UIColor brownColor]]; 
[yourTableView setSectionIndexTrackingBackgroundColor:[UIColor brightBlueColor]]; 
if ([yourTableView respondsToSelector:@selector(sectionIndexBackgroundColor)]) 
    [yourTableView setSectionIndexBackgroundColor:[UIColor clearColor]]; 

// Set additional properties for background colour 
CGRect frame = self.tableView.bounds; 
frame.origin.y = -frame.size.height; 
UIView *viewBackground = [[UIView alloc] initWithFrame:frame]; 
[viewBackground setBackgroundColor:self.brightBlueColour]; 
[yourTableView addSubview:viewBackground]; 

Kombinacja ta zapewnia bardziej akceptowalny wygląd w moja opinia, i używam tego w moich aplikacjach, które używają widoków tabel z paskiem wyszukiwania.

+0

Doceniam odpowiedź. Ustawienie sectionIndexBackgroundColor to fajny mały hack, ale myślę, że pierwsza sugestia dotycząca uczynienia paska wyszukiwania częścią super widoku, a nie widokiem nagłówka tabeli, była bliższa temu, czego szukam. Nadal nie udało się namówić tej opcji, ale jest to przyzwoita droga do zejścia. –

+0

Niestety nie ma zbyt wielu samouczków o UISearchController, a te, które tam są, nie używają indeksu sekcji (stąd dlaczego nie mają do czynienia z tym problemem). Ponieważ jestem kierowany na system iOS 8, nie chcę przywracać do UISearchDisplayController. –

+0

Zaktualizuję odpowiedź, ale prawdopodobnie nie zajmie mi to około 12 godzin. W międzyczasie pomyśl o hierarchii widoku i miejscu, w którym ma się znajdować pasek wyszukiwania. Użyj storyboardu z tym lub innym projektem testowym, aby pomóc sobie zobrazować tę hierarchiczną strukturę. Warto również zauważyć, że od czasu iOS 7 możesz przewinąć pasek wyszukiwania do paska nawigacji u góry ekranu. – andrewbuilder

8

wystarczy zmienić kolor tła sectionIndex:

SWIFT:

tableView.sectionIndexBackgroundColor = UIColor.clearColor() 
+0

To powinna być zaakceptowana odpowiedź! – VivienG

0

Najbardziej brudne i proste rozwiązanie (działa jak chcesz), wystarczy utworzyć drugą tableView. Jak (Swift 3):

tableView = UITableView(frame: CGRect.zero, style: .grouped) 
    tableView.delegate = self 
    tableView.dataSource = self 
    tableView.translatesAutoresizingMaskIntoConstraints = false 
    view.addSubview(tableView) 
    let cnt1 = NSLayoutConstraint(item: tableView, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1, constant: 0) 
    let cnt2 = NSLayoutConstraint(item: tableView, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 0) 
    let cnt3 = NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: tableView, attribute: .trailing, multiplier: 1, constant: 0) 
    let cnt4 = NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: tableView, attribute: .bottom, multiplier: 1, constant: -1) 
    constraintTableViewBottom = cnt4 
    view.addConstraints([cnt1, cnt2, cnt3, cnt4]) 

    let tableView2 = UITableView(frame: CGRect.zero, style: .grouped) 
    tableView2.sectionIndexColor = .black 
    tableView2.sectionIndexBackgroundColor = .clear 
    tableView2.delegate = self 
    tableView2.dataSource = self 
    tableView2.translatesAutoresizingMaskIntoConstraints = false 
    tableView2.backgroundColor = .clear 
    view.addSubview(tableView2) 
    let cnt5 = NSLayoutConstraint(item: tableView2, attribute: .height, relatedBy: .equal, toItem: view, attribute: .height, multiplier: 1, constant: 0) 
    let cnt6 = NSLayoutConstraint(item: tableView2, attribute: .centerY, relatedBy: .equal, toItem: view, attribute: .centerY, multiplier: 1, constant: 0) 
    let cnt7 = NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: tableView2, attribute: .trailing, multiplier: 1, constant: 0) 
    let cnt8 = NSLayoutConstraint(item: tableView2, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 13) 
    tableView2.addConstraint(cnt8) 
    view.addConstraints([cnt5, cnt6, cnt7]) 

i

func sectionIndexTitles(for tableView: UITableView) -> [String]? { 
    if tableView == self.tableView { return nil } 
    if searchController.isActive && searchController.searchBar.text != "" { 
     return filteredCells.keys.map { return sections[$0] } 
    } 
    return sections 
} 

func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int { 
    self.tableView.scrollToRow(at: IndexPath(row: 0, section: index), at: .top, animated: true) 
    return sections.index(of: title)! 
} 

final func numberOfSections(in tableView: UITableView) -> Int { 
    if tableView != self.tableView { return 0 } 
    return sections.count 
} 

i na przykład

final func updateSearchResults(for searchController: UISearchController) { 
    filterCells(searchText: searchController.searchBar.text!) 
    tableView.reloadSectionIndexTitles() 
} 
1

wiem, jest to stara sprawa, ale widziałem to wymyślić kilka razy. Zamiast powyższych rozwiązań łatwiej jest utworzyć nowe UIView z oryginalnymi granicami, a następnie iOS nie zmniejsza szerokości, aby pomieścić indeks tabeli.

tj. w viewDidLoad

let headerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: searchController.searchBar.bounds.size.height)) 
headerView.addSubview(searchController.searchBar) 
tableView.tableHeaderView = headerView 
Powiązane problemy