Как изменить текст кнопки «Отмена» по умолчанию, который отображается в UISearchBar + iPhone - PullRequest
26 голосов
/ 29 марта 2010

Я занимаюсь разработкой приложения, в котором я хотел изменить текст строки поиска в панели поиска. Я хотел изменить текст кнопки «Отмена», которая появляется рядом с панелью поиска. Перед вводом любой строки в строке поиска мы получим строку поиска в качестве строки по умолчанию. Я хотел изменить текст этой строки, и когда мы нажимаем на эту панель поиска, мы получаем кнопку отмены рядом с панелью поиска, и я хотел изменить текст этой кнопки отмены.

Ответы [ 14 ]

50 голосов
/ 24 января 2013

Используйте внешний прокси:

id barButtonAppearanceInSearchBar = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil];

[barButtonAppearanceInSearchBar setBackgroundImage:grayBackgroundImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[barButtonAppearanceInSearchBar setTitleTextAttributes:@{
                                      NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-CondensedBold" size:20],
                                 NSForegroundColorAttributeName : [UIColor blackColor]
     } forState:UIControlStateNormal];
[barButtonAppearanceInSearchBar setTitle:@"X"];
35 голосов
/ 30 июня 2010

Вам также необходимо иметь "searchBar setShowsCancelButton" перед процедурой.

- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller
{
    [theSearchBar setShowsCancelButton:YES animated:NO];
    for (UIView *subView in theSearchBar.subviews){
        if([subView isKindOfClass:[UIButton class]]){
            [(UIButton*)subView setTitle:@"Done" forState:UIControlStateNormal];
        }
    }
}

Примечание также: используйте UIButton, чтобы избежать проблем с Apple!

23 голосов
/ 23 сентября 2013

Решение для iOS 7. Все кредиты для этого идут на Мр. Джеспер Нильсен - он написал код.

-(void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller {
    UIButton *cancelButton;
    UIView *topView = theSearchBar.subviews[0];
    for (UIView *subView in topView.subviews) {
        if ([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
            cancelButton = (UIButton*)subView;
        }
    }
    if (cancelButton) {
        [cancelButton setTitle:@"YourTitle" forState:UIControlStateNormal];
    }

}
4 голосов
/ 03 октября 2014

В iOS 7, если вы используете UISearchBar, просто напишите этот код в searchBarTextDidBeginEditing: метод

searchBar.showsCancelButton = YES;UIView* view=searchBar.subviews[0];
for (UIView *subView in view.subviews) {
      if ([subView isKindOfClass:[UIButton class]]) {
          UIButton *cancelButton = (UIButton*)subView;

          [cancelButton setTitle:@"إلغاء" forState:UIControlStateNormal];
       }
}
4 голосов
/ 29 марта 2010

Если под "Строкой поиска" вы подразумеваете заполнитель, то это должно сделать это:

[searchBar setPlaceholder:@"Whatever you want"];

Что касается изменения текста кнопки отмены, это может быть немного сложнее. Apple не использует для этого стандартный UIBarButtonItem или даже нестандартный UIButton. Вместо этого они используют UINavigationButton для кнопки отмены в строке поиска. Поскольку это не документированный публичный класс, попытка изменить его может очень хорошо отклонить ваше приложение из App Store. Если вы действительно хотите рискнуть отклонением, тогда вы можете искать в подпредставлениях searchBar:

for(UIView *view in [searchBar subviews]) {
    if([view isKindOfClass:[NSClassFromString(@"UINavigationButton") class]]) {
        [(UIBarItem *)view setTitle:@"Whatever you want"];
    }
}

Обратите внимание, что кнопка отмены загружается лениво, поэтому вам придется делать это изменение, когда строка поиска активирована пользователем.

3 голосов
/ 11 сентября 2013

Я хотел бы исправить технику UIAppearance, так как код yar1vn не будет работать с Xcode 5. В следующем у вас будет код, который отлично работает как для iOS 6, так и для iOS 7.

Во-первых, вы должны понимать, что кнопка отмены является частной кнопкой UINavigationButton: UIButton. Следовательно, это не UIBarButtonItem. После некоторой проверки кажется, что UINavigationButton ответит на эти селекторы UIAppearance:

// inherited from UINavigationButton
@selector(setTintColor:)
@selector(setBackgroundImage:forState:style:barMetrics:)
@selector(setBackgroundImage:forState:barMetrics:)
@selector(setTitleTextAttributes:forState:)
@selector(setBackgroundVerticalPositionAdjustment:forBarMetrics:)
@selector(setTitlePositionAdjustment:forBarMetrics:)
@selector(setBackButtonBackgroundImage:forState:barMetrics:)
@selector(setBackButtonTitlePositionAdjustment:forBarMetrics:)
@selector(setBackButtonBackgroundVerticalPositionAdjustment:forBarMetrics:)

// inherited from UIButton
@selector(setTitle:forState:)

По совпадению, эти селекторы совпадают с селекторами UIBarButtonItem. Смысл в том, чтобы использовать два отдельных UIAppearance для обработки частного класса UINavigationButton.

/* dual appearance technique by Cœur to customize a UINavigationButton */
Class barClass = [UISearchBar self];

UIBarButtonItem<UIAppearance> *barButtonItemAppearanceInBar = [UIBarButtonItem appearanceWhenContainedIn:barClass, nil];
[barButtonItemAppearanceInBar setTintColor:...];
[barButtonItemAppearanceInBar setBackgroundImage:... forState:... style:... barMetrics:...];
[barButtonItemAppearanceInBar setBackgroundImage:... forState:... barMetrics:...];
[barButtonItemAppearanceInBar setTitleTextAttributes:... forState:...];
[barButtonItemAppearanceInBar setBackgroundVerticalPositionAdjustment:... forBarMetrics:...];
[barButtonItemAppearanceInBar setTitlePositionAdjustment:... forBarMetrics:...];
[barButtonItemAppearanceInBar setBackButtonBackgroundImage:... forState:... barMetrics:...];
[barButtonItemAppearanceInBar setBackButtonTitlePositionAdjustment:... forBarMetrics:...];
[barButtonItemAppearanceInBar setBackButtonBackgroundVerticalPositionAdjustment:... forBarMetrics:...];

UIButton<UIAppearance> *buttonAppearanceInBar = [UIButton appearanceWhenContainedIn:barClass, nil];
[buttonAppearanceInBar setTitle:... forState:...];

Теперь этот метод работает для кнопки «Отмена», но также работает для кнопки «Назад», если вы измените barClass на [UINavigationBar self].

2 голосов
/ 28 марта 2015

Это решение работает для меня - iOs7 и iOs8:

@interface ... : ...
@property (strong, nonatomic) IBOutlet UISearchBar *search; 
@end

и

- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
[searchBar setShowsCancelButton:YES animated:YES];

NSArray *searchBarSubViews = [[self.search.subviews objectAtIndex:0] subviews];
UIButton *cancelButton;
for (UIView *subView in searchBarSubViews) {
    if ([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
        cancelButton = (UIButton*)subView;
        break;
    }
}
if (cancelButton) {

    [cancelButton setTitle:@"New cancel" forState:UIControlStateNormal];

}
 //insert this two lines below if you have a button appearance like this "Ne...cel" 

[searchBar setShowsCancelButton:NO animated:YES];
[searchBar setShowsCancelButton:YES animated:YES]; 
}
1 голос
/ 25 мая 2016

Если вы просто хотите локализовать заголовок по умолчанию "Отмена" для кнопки отмены, я предпочитаю изменить значение ключа CFBundleDevelopmentRegion с en на локализованный регион в Info.plist файл в проекте.

Вот мое изменение,

<key>CFBundleDevelopmentRegion</key>
<string>zh_CN</string>

после этого заголовок по умолчанию «Отмена» будет отображаться как «取消» на китайском языке. Это изменение также повлияет на все значения области по умолчанию, например, будут локализованы заголовки действий операций монтажа в UITextField / UITextView, «Выбрать» -> «选择», «Вставить» -> «粘贴» ...

Кстати, файл Info.plist может быть прекрасно локализован.

Наслаждайтесь!

1 голос
/ 18 ноября 2014

Рабочий код Джеремитриппа в Swift

Я не смог найти тот же код в Swift, поэтому я "перевел" его сам:

func searchDisplayControllerWillBeginSearch(controller: UISearchDisplayController) {
    self.searchDisplayController?.searchBar.showsCancelButton = true
    var cancelButton: UIButton
    var topView: UIView = self.searchDisplayController?.searchBar.subviews[0] as UIView
    for subView in topView.subviews {
        if subView.isKindOfClass(NSClassFromString("UINavigationButton")) {
        cancelButton = subView as UIButton
        cancelButton.setTitle("My Custom Title", forState: UIControlState.Normal)
        }
    }
}
1 голос
/ 21 января 2014

В iOS 7, если вы установили displaysSearchBarInNavigationBar = YES на UISearchDisplayController, замена заголовка кнопки отмены через рекурсию подпредставления или прокси внешнего вида не будет работать .

Вместо этого используйте собственную кнопку бара в viewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.searchDisplayController.displaysSearchBarInNavigationBar = YES;
    UIBarButtonItem *barItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"A Custom Title", nil)
                                                                style:UIBarButtonItemStyleBordered
                                                               target:self
                                                               action:@selector(cancelButtonTapped:)];

    // NB: Order is important here.
    //     Only do this *after* setting displaysSearchBarInNavigationBar to YES
    //     as that's when UISearchDisplayController creates it's navigationItem
    self.searchDisplayController.navigationItem.rightBarButtonItem = barItem;
}
...