27

我正在开发一个应用程序,我想在其中更改 SearchBar 中搜索字符串的文本。我想更改出现在 SearchBar 旁边的 Cancel Button Also 的文本。在搜索栏中输入任何字符串之前,我们会将搜索字符串作为默认字符串。我想更改该字符串的文本,当我们单击该搜索栏时,我们会在搜索栏旁边看到一个取消按钮,我想更改该取消按钮的文本。

4

15 回答 15

51

使用外观代理:

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"];
于 2013-01-24T19:35:01.167 回答
36

您还需要在程序之前设置“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 出现问题!

于 2010-06-30T05:36:11.917 回答
23

iOS 7 解决方案。所有功劳归于 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];
    }

}
于 2013-09-22T20:35:06.490 回答
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"];
    }
}

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

于 2010-03-29T07:18:43.150 回答
4

在 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];
       }
}
于 2014-10-03T09:07:31.407 回答
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:...];

现在,这种技术适用于 Cancel 按钮,但如果您将 barClass 更改为 ,它也适用于 Back 按钮[UINavigationBar self]

于 2013-09-11T15:46:52.240 回答
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]; 
}
于 2015-03-28T00:53:48.000 回答
1

在 iOS 7 上,如果您设置displaysSearchBarInNavigationBar = YES了 on 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;
}
于 2014-01-20T23:18:08.467 回答
1

Jeremytripp 在 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)
        }
    }
}
于 2014-11-18T13:20:22.273 回答
1

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

这是我的改变,

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

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

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

享受!

于 2016-05-25T03:39:51.133 回答
0

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

for (id subview in searchBar.subviews) {
    if ([subview respondsToSelector:@selector(setTitle:)]) {
        [subview setTitle:@"Map"];
    }
}
于 2012-08-05T02:48:19.610 回答
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];
    }
}
于 2014-07-10T00:45:09.437 回答
0

如果 SearchBar 在导航栏中,则代码将与通常的答案不同;您需要改为搜索 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

于 2016-02-11T21:10:32.803 回答
0
    if #available(iOS 13.0, *) {
        controller.searchBar.setValue("Done", forKey:"cancelButtonText")
    } else {
        controller.searchBar.setValue("Done", forKey:"_cancelButtonText")
    }

‍♂️</p>

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

于 2020-01-28T22:18:11.277 回答
-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)
                }
        }
    }
}
于 2016-01-19T10:08:41.683 回答