2009-07-31 17 views
42

In genere, un UISearchDisplayController, quando attivato, attenua il TableView e mette a fuoco la barra di ricerca. Non appena si inserisce del testo nella barra di ricerca, viene creato un oggetto SearchResultsTableView che viene visualizzato tra la barra di ricerca e la tastiera. Il delegato searchDisplayController viene chiamato quando viene caricato/mostrato/nascosto/scaricato questo secondo UITableView. Di solito mostra risultati di ricerca in tempo reale o voci di completamento automatico durante la digitazione.UISearchDisplayController senza tabella risultati Visualizza?

Nella mia app, voglio cercare un servizio web e non voglio chiamare il servizio web per ogni lettera che l'utente inserisce. Pertanto, voglio disabilitare completamente searchResultsTableView e mantenere l'overlay nero oscurato mentre entra nel testo. Vorrei quindi attivare la ricerca (con una schermata di caricamento) una volta che ha colpito il pulsante di ricerca.

Restituire solo zero righe per la searchResultsTableView non sembra gradevole poiché visualizza un searchResultsTableView vuoto con un messaggio "nessun risultato". Ho provato a nascondere il tavolo quando appare (searchDisplayController:didLoadSearchResultsTableView:) che funziona, ma anche l'overlay dimmerato in nero è nascosto in modo che la tabella sottostante sia completamente visibile di nuovo.

Qualsiasi idea oltre a ricreare la funzionalità UISearchDisplayController da zero?

risposta

38

ecco un piccolo trucco che ho appena capito e inoltre si deve restituire 0 risultati durante la modifica SearchString

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString 
{ 
    savedSearchTerm = searchString; 

    [controller.searchResultsTableView setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.8]]; 
    [controller.searchResultsTableView setRowHeight:800]; 
    [controller.searchResultsTableView setScrollEnabled:NO]; 
    return NO; 
} 

- (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView 
{ 
    // undo the changes above to prevent artefacts reported below by mclin 
} 

penso che sarete a capire cosa fare dopo

+0

Esattamente quello che stavo cercando. Molte grazie! – Zargony

+1

Funziona per la prima volta, ma se cerchi, fai clic sulla x per cancellare e quindi inserisci altro testo, mostra tutte le righe con sfondo nero opaco e linee di divisione bianche.Ho indovinato che potrebbe essere l'UITableCellViews, così ho aggiunto questo a voi funzione ed ha funzionato: per (UIView * visualizzazione secondaria in self.searchDisplayController.searchResultsTableView.subviews) { \t \t [visualizzazione secondaria removeFromSuperview]; } – mclin

+0

sembra non proprio pulito :( – Martin

2

dovrebbe essere sufficiente ad attuare il seguente metodo nella UISearchDisplayDelegate (che di solito è la vostra abitudine UITableViewController sottoclasse)

- (BOOL) searchDisplayController: (UISearchDisplayController *) controller shouldReloadTableForSearchString: (NSString *) searchString 
{ 
    [self startMyCustomWebserviceSearchAsBackgroundProcessForString: searchString]; //starts new NSThread 
    return NO; 
} 

Hai provato questo?

+0

questo modo si evita il searchDisplayController di inviare [reload searchResultsTableView], ma purtroppo continua ad essere visualizzato il searchResultsTableView (messaggio "non ha prodotto risultati") – Zargony

+0

in questo caso ho paura, che il comportamento predefinito del UISearchDisplayController non possono essere modificato ... scusa – xoconoxtle

+0

per puro caso ho notato ieri, che l'app YouTube lo fa esattamente come sto cercando. Purtroppo non ho ancora trovato un modo carino (oltre a creare UISearchDisplayController). – Zargony

19

Hai provato questo:

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_lookup:) object:nil]; 
[self performSelector:@selector(_lookup:) withObject:txt afterDelay:0.20]; 

In questo modo, se l'utente digita un altro char entro 1/5 sec, è solo rendono una chiamata web.

+1

Con l'oggetto: nil, la chiamata di annullamento corrisponderà effettivamente? Probabilmente stai meglio chiamando semplicemente vecchio [NSObject cancelPreviousPerformRequestsWithTarget: self] se non hai altre richieste di esecuzione in corso. – Thom

2

Sulla base di Il codice di user182820 di seguito è la mia versione. Nascondo la vista tabella di UISearchDisplayController. Quando si inserisce un carattere nella casella di ricerca, posiziono una "vista ombreggiata" in modo che assomigli alla "vista scura" di UISearchDisplayController, che non è mai stata rimossa e quindi rimossa quando la ricerca è terminata. Se si inseriscono alcuni caratteri e si preme cancel, la vista tabella diventa tutto bianca e non so come aggirarla.

- (void)viewDidLoad { 
    ... 
    tableViewMask=[UIView new]; 
    tableViewMask.backgroundColor = [UIColor blackColor]; 
    tableViewMask.alpha = 0.8; 
} 

- (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller{ 
    tableViewMask.frame=CGRectMake(self.tableView.frame.origin.x, self.tableView.frame.origin.y+controller.searchBar.frame.size.height, self.tableView.frame.size.width, self.tableView.frame.size.height-controller.searchBar.frame.size.height); 
    controller.searchResultsTableView.hidden=YES; 
} 

- (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller{ 
    [tableViewMask removeFromSuperview]; 
} 

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{ 
    if (searchString.length==0) 
     [tableViewMask removeFromSuperview]; 
    else 
     [self.tableView addSubview:tableViewMask]; 
    [searchText autorelease]; 
    searchText=[searchString retain]; 
    return NO; 
} 
1

ho foud un modo migliore, dal momento che c'è un bug con la "migliore risposta" - il separatore e le "Nessun risultato" sarà visualizzato quando si scorre la tabella sfondo nero.

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { 

    controller.searchResultsTableView.backgroundColor = [UIColor blackColor]; 
    controller.searchResultsTableView.alpha = 0.8; 
    controller.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleNone; 

    for(UIView *subview in tableView.subviews) { 
     if([subview isKindOfClass:UILabel.class]) { 
      subview.hidden = YES; 
     } 
    } 

    return NO; 
} 

- (void) searchBarSearchButtonClicked:(UISearchBar *)searchBar { 

    self.searchDisplayController.searchResultsTableView.backgroundColor = [UIColor whiteColor]; 
    self.searchDisplayController.searchResultsTableView.alpha = 1; 
    self.searchDisplayController.searchResultsTableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; 

    for(UIView *subview in tableView.subviews) { 
     if([subview isKindOfClass:UILabel.class]) { 
      subview.hidden = NO; 
     } 
    } 

    // search results and reload data .... 
} 
+0

Puoi disabilitare lo scroll e ottenere attorno a questo 'bug' si cita con questo: \t controller.searchResultsTableView.scrollEnabled = NO; – Chris

9

Nulla di quanto sopra sembrava funzionare bene, alla fine, così mi si avvicinò con la seguente (devi chiamare removeTableHeader quando si è pronti per visualizzare i risultati):

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar { 
    [self setTableHeader]; 
} 

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { 
    [self setTableHeader]; 
} 

- (void)setTableHeader { 
    UIView *headerView = [[UIView alloc] initWithFrame:self.searchDisplayController.searchResultsTableView.frame]; 
    headerView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.8]; 

    [self.searchDisplayController.searchResultsTableView setBackgroundColor:[UIColor clearColor]]; 
    [self.searchDisplayController.searchResultsTableView setScrollEnabled:NO]; 
    [self.searchDisplayController.searchResultsTableView setTableHeaderView:headerView]; 

    [headerView release]; 
} 

- (void)removeTableHeader { 
    [self.searchDisplayController.searchResultsTableView setBackgroundColor:[UIColor whiteColor]]; 
    [self.searchDisplayController.searchResultsTableView setScrollEnabled:YES]; 
    [self.searchDisplayController.searchResultsTableView setTableHeaderView:nil]; 
} 

Ovviamente , rende trasparente la tabella, aggiunge un'intestazione di tabella nera/traslucida con le stesse dimensioni della tabella e disabilita lo scorrimento sul tavolo in modo da non poter superare o superare l'intestazione. Come bonus, potresti aggiungere qualcosa alla vista dell'intestazione ("per favore aspetta ..." o un indicatore di attività).

+2

Questo tipo funziona, ma non è possibile fare clic sull'intestazione per ignorare – chaiwalla

+0

Questa soluzione è la più pulita e più efficace che ho trovato. Il problema principale con altre soluzioni qui è che quando la sovrapposizione dell'ombra 'fasulla' è visibile e si chiude l'interfaccia di ricerca, iOS costringe il TableView a diventare opaco e lo schermo lampeggia rapidamente in bianco, che è brutto. Questo non succede con questa implementazione. @chaiwalla, se vuoi imitare il comportamento predefinito di tap-to-dismiss basta aggiungere un UITapGestureRecognizer all'intestazioneView e chiamare setActive: animated: su searchDisplayController nel callback. –

+0

Solo un commento relativo allo stile. Potresti voler usare 'showTableHeader' invece di' setTableHeader' dato che in questo caso non è un vero setter. – Besi

0

Credo di aver trovato una migliore applicazione per questo problema. Tutte le risposte precedenti mostrano correttamente la vista oscurata identico a quello che l'UITableView appare come prima di una ricerca, ma ogni soluzione manca la funzionalità per toccare l'area al fine di annullare la ricerca.

Per questo motivo penso che questo codice funziona meglio.

Prima di tutto, creare un BOOL come searchButtonTapped per indicare se il pulsante di ricerca è stato sfruttato. Di default è NO.

Poi:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { 
if (!searchButtonTapped) {   
    // To prevent results from being shown and to show an identical look to how the tableview looks before a search 
    [controller.searchResultsTableView setBackgroundColor:[UIColor clearColor]]; 
    [controller.searchResultsTableView setRowHeight:160]; 
    self.searchDisplayController.searchResultsTableView.scrollEnabled = NO; 
} else { 
    // Restore original settings 
    [controller.searchResultsTableView setBackgroundColor:[UIColor whiteColor]]; 
    [controller.searchResultsTableView setRowHeight:44]; 
    self.searchDisplayController.searchResultsTableView.scrollEnabled = YES; 
} 

return YES; 
} 

Questo dovrebbe essere chiaro ora sulla base delle altre risposte. Assicurati di ripristinare anche le impostazioni originali quando l'utente tocca il pulsante Cerca.

Inoltre, nel metodo cellForIndexPath add:

cell.selectionStyle = UITableViewCellSelectionStyleNone; 
cell.contentView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.8]; 

Per creare la stessa vista inattivo che viene mostrata prima si immette testo. Assicuratevi di applicare queste proprietà alla cella destra, vale a dire, controllare che UITableView è attivo e che l'utente non ha sfruttato il pulsante Cerca.

Quindi, fondamentalmente, in didSelectRowAtIndexPath:

if (tableView == self.searchDisplayController.searchResultsTableView) { 
    if (searchButtonTapped) { 
      // Code for when the user select a row after actually having performed a search 
    { 
else 
    [self.searchDisplayController setActive:NO animated:YES]; 

Ora l'utente può toccare l'area in grigio, che non si tradurrà in una selezione visibile di un UITableViewCell, ma invece annulla la ricerca.

9

avuto lo stesso problema, come voi, ho gestito facendo a) impostazione della alfa del searchResultsTableView a 0 quando si inizia la ricerca, e poi da b) aggiungere/rimuovere l'OverlayView alla visualizzazione del viewController. Funziona come un fascino per me.

@interface MyViewController() 
//... 
@property(nonatomic, retain) UIView *overlayView; 
//... 
@end 

@implementation MyViewController 
@synthesize overlayView = _overlayView; 

//... 

- (void)viewDidLoad 
{ 
    //... 

    //define your overlayView 
    _overlayView = [[UIView alloc] initWithFrame:CGRectMake(0, 44, 320, 480)]; 
    _overlayView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.8]; 
} 

//hide the searchResultsTableView 
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller 
{ 
    self.searchDisplayController.searchResultsTableView.alpha = 0.0f; 
} 

//when ending the search, hide the overlayView 
- (void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller 
{ 
    [_overlayView removeFromSuperview]; 
} 

//depending on what the user has inputed, add or remove the overlayView to the view of the current viewController 
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString 
{ 

    if ([searchString length]>0) 
    { 
     [self.view addSubview:_overlayView]; 
    } 
    else 
    { 
     [_overlayView removeFromSuperview]; 
    } 

    return NO; 
} 

@end 
+0

Mi piace questa soluzione meglio della risposta accettata; Grazie! Molto più pulito – elsurudo

2

Che dire solo facendo semplice come questo:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString 
{ 
self.searchDisplayController.searchResultsTableView.hidden=YES; 
return YES; 
} 

funziona bene per me ..

+0

Questo funziona solo parzialmente, nel mio caso lo sfondo è oscurato, e non appena inizio a digitare lo sfondo in grigio viene rimosso e rivelando la tabella sottostante – Besi

1

Tutte le risposte esistenti sono troppo complicate. Puoi scappare nascondendo immediatamente la visualizzazione della tabella dei risultati.

-(void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView 
{ 
    tableView.hidden = YES; 
} 
Problemi correlati