如何更改UISearchBar + iPhone中显示的取消按钮的默认文本

时间:2010-03-29 06:36:25

标签: ios iphone uisearchbar

我正在开发一个应用程序,我想在SearchBar中更改搜索字符串的文本。我想更改SearchBar旁边显示的取消按钮的文本。在搜索栏中输入任何字符串之前,我们将获取搜索字符串作为默认字符串。我想更改该字符串的文本,当我们点击该搜索栏时,我们会在搜索栏旁边找到一个取消按钮,我想更改该取消按钮的文本。

15 个答案:

答案 0 :(得分:50)

使用外观代理:

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"];

答案 1 :(得分:35)

您还需要在程序之前使用“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问题!

答案 2 :(得分:23)

iOS 7的解决方案。所有学分转到Mr. Jesper Nielsen - 他编写了代码。

-(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];
    }

}

答案 3 :(得分:4)

如果通过“搜索字符串”表示占位符,那么应该这样做:

[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"];
    }
}

请注意,取消按钮是懒惰加载的,因此当用户激活搜索栏时,您必须进行此修改。

答案 4 :(得分:4)

在iOS 7中,如果您使用的是UISearchBar,只需在searchBarTextDidBeginEditing:method

中编写此代码
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];
       }
}

答案 5 :(得分:3)

我想修复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],它也适用于“后退”按钮。

答案 6 :(得分:2)

此解决方案适用于我 - 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]; 
}

答案 7 :(得分:1)

在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;
}

答案 8 :(得分:1)

Jeremytripp在Swift工作的代码

我无法在Swift中找到相同的代码,所以我&#34;翻译了#34;我自己:

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)
        }
    }
}

答案 9 :(得分:1)

如果您只想本地化取消按钮的默认“取消”标题,我更喜欢将 CFBundleDevelopmentRegion 键的值从en更改为Info中的本地化区域项目中的.plist文件。

这是我的更改,

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

之后,默认的“取消”标题将显示为中文“取消”。此更改还将影响所有默认区域值,例如,UITextField / UITextView上的粘贴板操作的操作标题将被本地化,“选择” - &gt; “选择”,“粘贴” - &gt; “粘贴” ...

顺便说一句,Info.plist文件可以完美地进行本地化。

享受!

答案 10 :(得分:0)

我没有引用非公共UINavigationButton类,而是执行了以下操作。我希望它能通过App Store审核!

for (id subview in searchBar.subviews) {
    if ([subview respondsToSelector:@selector(setTitle:)]) {
        [subview setTitle:@"Map"];
    }
}

答案 11 :(得分:0)

如果您在更改iOS7中的“取消”按钮时仍然遇到问题,目前这对我有用:

-(void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller{
    self.searchDisplayController.searchBar.showsCancelButton = YES;
    UIButton *cancelButton;
    UIView *topView = self.searchDisplayController.searchBar.subviews[0];
    for (UIView *subView in topView.subviews) {
        if ([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]) {
            cancelButton = (UIButton*)subView;
        }
    }
    if (cancelButton) {
      //Set the new title of the cancel button
        [cancelButton setTitle:@"Hi" forState:UIControlStateNormal];
    }
}

答案 12 :(得分:0)

如果SearchBar在navigationBar中,代码将与通常的答案不同;您需要搜索NavigationBar的子视图。

-(void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller{
UINavigationBar * navigationBar =  self.navigationController.navigationBar;

for (UIView *subView in navigationBar.subviews){
    if([subView isKindOfClass:NSClassFromString(@"UINavigationButton")]){
        [(UIButton*)subView setTitle:@"İptal" forState:UIControlStateNormal];
    }
}}

并且这项工作在iOS7 +中,如果你仍然无法设置标题,你应该学习查看调试 - 这就是我解决这个问题的方法。

这个简短的教程非常清楚地概述了View-Debugging的关键点:

http://www.raywenderlich.com/98356/view-debugging-in-xcode-6

答案 13 :(得分:0)

    if #available(iOS 13.0, *) {
        controller.searchBar.setValue("Done", forKey:"cancelButtonText")
    } else {
        controller.searchBar.setValue("Done", forKey:"_cancelButtonText")
    }

?‍♂️

实际上controller.searchBar.setValue("Done", forKey:"cancelButtonText")适用于所有iOS版本

答案 14 :(得分:-1)

在Swift 2.1中运行短代码(已测试iOS7-9)

@IBOutlet weak var searchBar: UISearchBar!
func enableSearchBarCancelButton(enable: Bool, title: String? = nil) {
    searchBar?.showsCancelButton = enable
    if enable {
        if let _cancelButton = searchBar?.valueForKey("_cancelButton"),
            let cancelButton = _cancelButton as? UIButton {
                cancelButton.enabled = enable //comment out if you want this button disabled when keyboard is not visible
                if title != nil {
                    cancelButton.setTitle(title, forState: UIControlState.Normal)
                }
        }
    }
}