UISearchBar clearButton zwingt die Tastatur zu erscheinen
-
11-09-2019 - |
Frage
Ich habe eine UISearchBar, die für eine Tabellenansicht als Live-Filter wirkt. Wenn die Tastatur über endEditing des Feldes verwiesen :, die Abfragetext und die graue Kreis „clear“ -Taste bleiben. Von hier aus, wenn ich die graue Schaltfläche „Löschen“ tippen erscheint die Tastatur als der Text gelöscht wird.
Wie verhindere ich das? Wenn die Tastatur nicht geöffnet ist mag ich, dass, um den Text zu löschen, ohne die Tastatur wieder zu öffnen.
Es gibt ein Protokoll Methode, die aufgerufen wird, wenn ich die Löschtaste tippen. Aber zu senden UISearchBar eine ResignFirstResponder Nachricht hat keine Auswirkungen auf die Tastatur.
Lösung
Dies ist eine alte Frage, und ich kam gerade über das gleiche Problem und schaffte es die folgende Art und Weise zu lösen:
Wenn die searchBar:textDidChange:
Methode des UISearchBarDelegate wegen der Benutzer aufgerufen wird, die ‚klar‘ Taste tippen, hat die SearchBar nicht das erste Responder noch werden, so dass wir, um das auszunutzen zu erkennen, wenn der Benutzer in der Tat sollte die Suche löschen und nicht den Fokus auf die SearchBar zu bringen und / oder etwas anderes tun.
Spur davon zu halten, brauchen wir eine BOOL
Ivar in unseren Viewcontroller zu erklären, dass auch die SearchBar Delegierten sind (sie es shouldBeginEditing
nennen) und setzen Sie sie mit einem Anfangswert von YES
(unsere Viewcontroller Klasse angenommen heißt SearchViewController):
@interface SearchViewController : UIViewController <UISearchBarDelegate> {
// all of our ivar declarations go here...
BOOL shouldBeginEditing;
....
}
...
@end
@implementation SearchViewController
...
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
...
shouldBeginEditing = YES;
}
}
...
@end
Später, in der UISearchBarDelegate, setzen wir die searchBar:textDidChange:
und searchBarShouldBeginEditing:
Methoden:
- (void)searchBar:(UISearchBar *)bar textDidChange:(NSString *)searchText {
NSLog(@"searchBar:textDidChange: isFirstResponder: %i", [self.searchBar isFirstResponder]);
if(![searchBar isFirstResponder]) {
// user tapped the 'clear' button
shouldBeginEditing = NO;
// do whatever I want to happen when the user clears the search...
}
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)bar {
// reset the shouldBeginEditing BOOL ivar to YES, but first take its value and use it to return it from the method call
BOOL boolToReturn = shouldBeginEditing;
shouldBeginEditing = YES;
return boolToReturn;
}
Im Grunde genommen, das ist es.
Best
Andere Tipps
Ich habe festgestellt, dass ResignFirstResponder funktioniert nicht, wenn textDidChange von einem Kontakt zu der „Löschtaste“ genannt wird. Allerdings performSelection: withObject: afterDelay:
Verwendung scheint eine wirksame Abhilfe zu sein:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if ([searchText length] == 0) {
[self performSelector:@selector(hideKeyboardWithSearchBar:) withObject:searchBar afterDelay:0];
}
}
- (void)hideKeyboardWithSearchBar:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
}
fand ich eine ziemlich sichere Art und Weise zu wissen, ob die Löschtaste gedrückt wurde, und die Zeiten, zu ignorieren, wenn der Benutzer nur das letzte Zeichen des UISearchBar löschen. Hier ist sie:
- (BOOL)searchBar:(UISearchBar *)searchBar shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
_isRemovingTextWithBackspace = ([searchBar.text stringByReplacingCharactersInRange:range withString:text].length == 0);
return YES;
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if (searchText.length == 0 && !_isRemovingTextWithBackspace)
{
NSLog(@"Has clicked on clear !");
}
}
Ganz einfach und unkompliziert, ist es nicht :)? Das einzige, was zu beachten ist, dass, wenn der Benutzer die Löschtaste klickt, wenn die UITextField UISearchBar Bearbeiten Sie zwei Pings haben, während Sie ein nur erhalten, wenn der Benutzer darauf klickt, wenn er nicht bearbeitet wird.
Edit: Ich kann es nicht testen, aber hier ist die schnelle Version, wie pro Rotum:
var isRemovingTextWithBackspace = false
func searchBar(searchBar: UISearchBar, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool
{
self.isRemovingTextWithBackspace = (NSString(string: searchBar.text!).stringByReplacingCharactersInRange(range, withString: text).characters.count == 0)
return true
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String)
{
if searchText.characters.count == 0 && !isRemovingTextWithBackspace
{
NSLog("Has clicked on clear !")
}
}
@ Rotum von update (Swift2):
var isRemovingTextWithBackspace = false
func searchBar(searchBar: UISearchBar, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
self.isRemovingTextWithBackspace = (NSString(string: searchBar.text!).stringByReplacingCharactersInRange(range, withString: text).characters.count == 0)
return true
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.characters.count == 0 && !isRemovingTextWithBackspace {
NSLog("Has clicked on clear!")
}
}
habe ich eine Kombination von Antwort des @ Boliva und auch @ radiospiel zu einer anderen SO Frage beantworten :
@interface SearchViewController : UIViewController <UISearchBarDelegate> {
// all of our ivar declarations go here...
BOOL shouldBeginEditing;
....
}
...
@end
@implementation SearchViewController
...
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
...
shouldBeginEditing = YES;
}
}
...
- (void) searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
// TODO - dynamically update the search results here, if we choose to do that.
if (![searchBar isFirstResponder]) {
// The user clicked the [X] button while the keyboard was hidden
shouldBeginEditing = NO;
}
else if ([searchText length] == 0) {
// The user clicked the [X] button or otherwise cleared the text.
[theSearchBar performSelector: @selector(resignFirstResponder)
withObject: nil
afterDelay: 0.1];
}
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)bar {
// reset the shouldBeginEditing BOOL ivar to YES, but first take its value and use it to return it from the method call
BOOL boolToReturn = shouldBeginEditing;
shouldBeginEditing = YES;
return boolToReturn;
}
@end
Beste Lösung aus meiner Erfahrung ist nur ein UIButton
zu setzen (mit klarem Hintergrund und ohne Text) über dem System Löschtaste und als ein IBAction
verbinden
Mit automatischem Layout sein gerade mehr als einfach
- (IBAction)searchCancelButtonPressed:(id)sender {
[self.searchBar resignFirstResponder];
self.searchBar.text = @"";
// some of my stuff
self.model.fastSearchText = nil;
[self.model fetchData];
[self reloadTableViewAnimated:NO];
}
Durch Betätigen der Schaltfläche „Löschen“ in eine UISearchBar die Tastatur automatisch öffnet, auch wenn Sie searchBar.resignFirstResponder()
im textDidChange
UISearchBarDelegate Methode aufrufen.
Um die Tastatur tatsächlich zu verbergen, wenn Sie auf das „x“ drücken Sie die UISearchBar zu löschen, verwenden Sie den folgenden Code ein. Auf diese Weise, auch wenn textDidChange
aufgerufen wird, während etwas in der UISearchBar eingeben, nur die Tastatur ausblenden, wenn Sie in ihm den gesamten Text löschen, Wetter verwenden Sie die Schaltfläche Löschen oder Sie klicken auf das „x“:
extension ViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchBar.text!.count == 0 {
DispatchQueue.main.async {
searchBar.resignFirstResponder()
}
} else {
// Code to make a request here.
}
}
}
In Ihrer endEditing Methode, warum Sie nicht die UISearchBar löschen und da? Da das sein muss, wo man auch Ersthelfer zurücktreten, es macht Sinn.
Von den Suchleiste Delegaten Anrufe aufgefordert, einen Wechsel von einem alten Wert zu einem neuen zu akzeptieren - man konnte erkennen, dass der neue Wert war gleich Null, zusammen mit dem alten Wert ist nicht zu null, und ein Indikator dafür, dass die Benutzer hatte getippt nichts, da die Tastatur bis zuletzt - dann in diesem Fall zurücktreten Ersthelfer für die Suchleiste. Nicht sicher, ob die Tastatur vorübergehend obwohl angezeigt.
Ich habe eine sehr ähnliche Situation und versuche, dass ich selbst.
Das Berühren der Löschtaste führt searchText
leer zu sein. Ein anderer Weg, dies zu erreichen, ist für leeren Text in - (void)searchBar:(UISearchBar *)bar textDidChange:(NSString *)searchText
zu überprüfen:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
if([searchText length] == 0)
{
[self dismissSearch];
}
else
{
self.searchResultsTable.hidden = YES;
[self handleSearchForString:searchText];
}
}
- (void)dismissSearch
{
[self.searchBar performSelector: @selector(resignFirstResponder)
withObject: nil
afterDelay: 0.1];
self.searchResultsTable.hidden = YES;
}
Für die von Ihnen die UISearchController
in mit iOS 8 und oben, Sie wollen einfach die UISearchController
Unterklasse. Für Vollständigkeit, können Sie auch die Abbrechen , um zu verbergen, wie ich, da von der UISearchBar
den Text Clearing eine auf der Suche ist verworfen. Ich habe diesen Code unten hinzugefügt, wenn Sie es verwenden möchten.
Der Vorteil davon ist, dass Sie in der Lage sein werden dies für jede Klasse und jede Ansicht zu verwenden, anstatt eine Unterklasse von UIViewController
erfordern. Ich werde sogar zählen, wie ich meine UISearchController
am unteren Rand dieser Lösung initialisieren.
FJSearchBar
Diese Klasse muss nur außer Kraft gesetzt werden, wenn Sie die Löschtaste verstecken wollen wie ich. searchController.searchBar.showsCancelButton = NO
Kennzeichnung scheint nicht in Arbeit iOS 8 . Ich habe nicht getestet iOS 9 .
FJSearchBar.h
leer, aber der Vollständigkeit halber hier gestellt.
@import UIKit;
@interface FJSearchBar : UISearchBar
@end
FJSearchBar.m
#import "FJSearchBar.h"
@implementation FJSearchBar
- (void)setShowsCancelButton:(BOOL)showsCancelButton {
// do nothing
}
- (void)setShowsCancelButton:(BOOL)showsCancelButton animated:(BOOL)animated {
// do nothing
}
@end
FJSearchController
Hier ist, wo Sie die wirklichen Änderungen vornehmen möchten. Ich spaltete die UISearchBarDelegate
in eine eigene Kategorie, denn meiner Meinung nach, die Kategorien der Klassen sauberer und leichter zu pflegen. Wenn Sie die Delegierten in der Hauptklasse Schnittstelle / Implementierung halten wollen, sind Sie mehr als willkommen, dies zu tun.
FJSearchController.h
@import UIKit;
@interface FJSearchController : UISearchController
@end
@interface FJSearchController (UISearchBarDelegate) <UISearchBarDelegate>
@end
FJSearchController.m
#import "FJSearchController.h"
#import "FJSearchBar.h"
@implementation FJSearchController {
@private
FJSearchBar *_searchBar;
BOOL _clearedOutside;
}
- (UISearchBar *)searchBar {
if (_searchBar == nil) {
// if you're not hiding the cancel button, simply uncomment the line below and delete the FJSearchBar alloc/init
// _searchBar = [[UISearchBar alloc] init];
_searchBar = [[FJSearchBar alloc] init];
_searchBar.delegate = self;
}
return _searchBar;
}
@end
@implementation FJSearchController (UISearchBarDelegate)
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
// if we cleared from outside then we should not allow any new editing
BOOL shouldAllowEditing = !_clearedOutside;
_clearedOutside = NO;
return shouldAllowEditing;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
// hide the keyboard since the user will no longer add any more input
[searchBar resignFirstResponder];
}
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
if (![searchBar isFirstResponder]) {
// the user cleared the search while not in typing mode, so we should deactivate searching
self.active = NO;
_clearedOutside = YES;
return;
}
// update the search results
[self.searchResultsUpdater updateSearchResultsForSearchController:self];
}
@end
Einige Teile zu beachten:
- Ich habe anstelle von Eigenschaften der Suchleiste und die
BOOL
als private Variablen setzen, weil- Sie sind leichter als private Eigenschaften.
- Sie brauchen nicht von der Außenwelt gesehen oder geändert werden.
- Wir prüfen, ob die
searchBar
der Ersthelfer ist. Wenn es nicht ist, dann tatsächlich deaktivieren wir die Suchsteuerung, da der Text leer ist und wir nicht mehr suchen. Wenn Sie wirklich Sie sicher sein wollen, können Sie auch, dasssearchText.length == 0
gewährleisten. -
searchBar:textDidChange:
vorsearchBarShouldBeginEditing:
aufgerufen, weshalb wir es in dieser Reihenfolge behandelt. - aktualisiere ich die Suchergebnisse der Text ändert jedes Mal, aber Sie können die
[self.searchResultsUpdater updateSearchResultsForSearchController:self];
searchBarSearchButtonClicked:
wenn Sie nur die nach dem Benutzer durchgeführten Suche wollen verschieben möchten drückt die Suchen Taste.
Eine Swift-Version von @boliva ‚s Antwort.
class MySearchContentController: UISearchBarDelegate {
private var searchBarShouldBeginEditing = true
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchBarShouldBeginEditing = searchBar.isFirstResponder
}
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
defer {
searchBarShouldBeginEditing = true
}
return searchBarShouldBeginEditing
}
}
Ich habe jetzt in diesen mehrmals ausgeführt werden. Ich schätze die Antworten, die Menschen gegeben haben.
Schließlich würde Ich mag Apple sehen uns nur erlauben (Entwickler) zu erkennen, wenn die Löschtaste gedrückt wurde.
Es ist offensichtlich, dass das Drücken es, weil jeder Text in dem Suchfeld gelöscht wird erkannt wird.
Ich vermute, dass es ist einfach nicht sehr hoch im Augenblick auf ihrer Prioritätenliste ... Aber ich mag wirklich jemand bei Apple würde UISearchBar eine wenig Liebe geben!