Domanda

Qualcuno sa come annullare (dimettersi dal primo risponditore) da una UISearchBar quando si tocca sotto la casella di testo di ricerca e sopra la tastiera?Qualcuno può aiutarmi a pubblicare del codice per gestire questa cosa?

Grazie

È stato utile?

Soluzione

Un'idea alternativa che ho ricevuto da iphonedevbook , progetto di esempio di codice 04, è stato quello di utilizzare un grosso pulsante trasparente che sta dietro tutti gli altri controlli, che non fa altro che dimettersi tutti di primo intervento, se sfruttato. Cioè se l'utente tocca ovunque dove non c'è un controllo più importante - che è il comportamento intuitivo -. la barra di ricerca e la tastiera scompare

Altri suggerimenti

Aggiungi un gesto rubinetto in vista padre (del UISearchBar)

[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:searchBar action:@selector(resignFirstResponder)]];

Ho compiuto questo utilizzando un UITapGestureRecognizer:

UIGestureRecognizer* cancelGesture;

- (void) backgroundTouched:(id)sender {
    [self.view endEditing:YES];
}

#pragma mark - UISearchBarDelegate

-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    cancelGesture = [UITapGestureRecognizer new];
    [cancelGesture addTarget:self action:@selector(backgroundTouched:)];
    [self.view addGestureRecognizer:cancelGesture];
}

-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    if (cancelGesture) {
        [self.view removeGestureRecognizer:cancelGesture];
        [cancelGesture release];
        cancelGesture = nil;
    }
}

Il codice è una nuda, ma si può vedere l'intento. Quando il SearchBar inizia a modificare, si allega un riconoscitore rubinetto gesto alla visualizzazione del controller della vista, e rimuoverlo quando si ferma la modifica.

Ci sono un paio di avvertimenti che si può lavorare in giro: questa operazione farà in modo, se si fa clic su qualcosa oltre la tastiera o campo di testo della barra di ricerca, le trappole Riconoscimento del click - quindi se si utilizza il chiaro, annullano, ambito o risultati tasto che non risponderanno correttamente.

Nel mio scenario particolare, ho avuto un UITableView che copriva l'area esposta della vista in modo ho attaccato il sistema di riconoscimento gesto ad essa, invece di vista principale vista controllori, isolando l'area a cui il gesto avrebbe risposto.

Alla fine ho utilizzato un approccio ibrido tra Hauke ​​e Beau Scott.Ci sono stati due problemi che ho riscontrato utilizzando le loro soluzioni:

1) Se c'è qualcos'altro sullo schermo, toccandolo non verrà chiamato il resignFirstResponder.Ad esempio, se l'utente tocca un pulsante anziché lo spazio attorno al pulsante, il pulsante mangerà l'evento.La soluzione di Beau Scott, tuttavia, affronta questo problema.

2) Toccando la barra di ricerca stessa si otterrà la chiamata di resignFirstResponder.Chiaramente non vuoi che la tastiera scompaia quando tocchi UISearchBar.Una piccola modifica descritta di seguito risolve questo problema.

Ho finito per impostare la mia vista come segue.La vista principale ha due figli: UISearchBar e una sottovista che contiene il resto dei miei elementi dell'interfaccia utente.La visualizzazione secondaria occupa l'intero schermo sotto UISearchBar.Quindi ho utilizzato il codice esatto di Beau Scott per aggiungere e rimuovere il riconoscimento dei gesti, ma invece di aggiungerlo a self.view l'ho aggiunto alla sottoview:

IBOutlet UIView *gestureRecognizer;

...

-(void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    cancelGesture = [UITapGestureRecognizer new];
    [cancelGesture addTarget:self action:@selector(backgroundTouch:)];
    [gestureRecognizer addGestureRecognizer:cancelGesture];
}

-(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    if (cancelGesture) {
        [gestureRecognizer removeGestureRecognizer:cancelGesture];
        [cancelGesture release];
        cancelGesture = nil;
    }
}

Innanzitutto, hai bisogno di un riferimento alla barra di ricerca.Supponiamo che l'oggetto controller abbia un riferimento all'oggetto UISearchBar *theSearchBar e che lo assegni quando crei l'oggetto UISearchBar.

Successivamente, è necessario rilevare che la vista che lo contiene è stata toccata.La vista che viene toccata "sa", ma è necessario fornire tali informazioni al controller.Purtroppo Apple non ha fornito un modo semplice per farlo, ma non è nemmeno così difficile.

La mia soluzione è sostituire l'UIView standard che un oggetto UIViewController normalmente crea con un UIControl e quindi fare in modo che UIViewController risponda agli eventi touch.

MainController.m

- (void) loadView {
    UIControl *control = [[UIControl alloc] initWithFrame: <desired frame>];
[control addTarget: self action: @selector(touchUpInside) 
             forControlEvents: UIControlEventTouchUpInside];
       // or touch down events, or whatever you like
    self.view = control;
    [control release];
}

- (void) viewDidLoad {
    [super viewDidLoad];
    theSearchBar = [[UISearchBar alloc] initWithFrame: <desired frame>];

    // insert code to finish customizing the search bar

    [self.view addSubview: theSearchBar];
}

- (void) touchUpInside {
    if [theSearchBar isFirstResponder] {
        // grab any data you need from the search bar
        [theSearchBar resignFirstResponder];
    }
}

MainController.h

@interface MainController : UIViewController
{
    UISearchBar *theSearchBar;
}

Una precisazione:

Esiste un solo oggetto, chiamiamo la classe MainController, che è una sottoclasse di UIViewController.Tutti i metodi sopra elencati sono implementati in MainController.theSearchBar è dichiarato come UISearchBar* nel file .h.

Stai definendo la vista e il controller utilizzando Interface Builder?Se è così, ti suggerisco di imparare a NON usarlo: una volta che ti addentri nel tipo di trucchi di cui stiamo discutendo qui, diventa più un ostacolo che un aiuto: io non lo uso affatto, mai.

La risposta di @Gia Dang è il più semplice, ma non sottoclasse il UIView, solo il UIViewController, quindi il mio invito è un po ' diverso. Inoltre, dal momento che non so l'overhead per chiamare in realtà resignFirstResponder, preferisco controllare prima. E 'più codice, ma dal momento che tutto questo è fatto sul thread principale (che può rallentare l'interfaccia utente), preferisco controllare prima.

@implementation MyController : UIViewController {
@private
    UISearchController *_uiSearchController;
}

- (void)viewDidLoad {
    // add tap on view to resign the responder if we're in the middle of typing in the search
    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboardIfNeeded)];
    [self.view addGestureRecognizer:tapGestureRecognizer];
}

- (void)closeKeyboardIfNeeded {
    if (![_uiSearchController.searchBar isFirstResponder]) {
        return;
    }
    [_uiSearchController.searchBar resignFirstResponder];
}

@end

Per quanto riguarda le altre risposte, fare attenzione sugli oggetti continuamente ricreando. C'è sempre un calo di prestazioni, sia che si tratti della creazione stessa o la raccolta dei rifiuti attraverso la ARC , e queste cose rallenta il thread principale. A seconda di quello che stai facendo anche sul thread principale, può avere un notevole impatto sulle prestazioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top