我正在开发一个应用程序,我想在其中更改 SearchBar 中搜索字符串的文本。我想更改出现在 SearchBar 旁边的 Cancel Button Also 的文本。在搜索栏中输入任何字符串之前,我们会将搜索字符串作为默认字符串。我想更改该字符串的文本,当我们单击该搜索栏时,我们会在搜索栏旁边看到一个取消按钮,我想更改该取消按钮的文本。
15 回答
使用外观代理:
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"];
您还需要在程序之前设置“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 出现问题!
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];
}
}
如果“搜索字符串”是指占位符,那么应该这样做:
[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"];
}
}
请注意,取消按钮是延迟加载的,因此您必须在用户激活搜索栏时进行此修改。
在 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];
}
}
我想修复 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]
。
这个解决方案对我有用 - 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];
}
在 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;
}
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)
}
}
}
如果您只想本地化取消按钮的默认“取消”标题,我更喜欢将CFBundleDevelopmentRegion键的值从 en 更改为项目中 Info.plist 文件中的本地化区域。
这是我的改变,
<key>CFBundleDevelopmentRegion</key>
<string>zh_CN</string>
之后,默认的“取消”标题将显示为中文“取消”。此更改还将影响所有默认区域值,例如 UITextField/UITextView 上的粘贴板操作的动作标题将被本地化,“选择”->“选择”,“粘贴”->“粘贴”...
顺便说一句,Info.plist 文件可以完美地本地化。
享受!
我没有引用非公共 UINavigationButton 类,而是执行了以下操作。我希望它能通过 App Store 审查!
for (id subview in searchBar.subviews) {
if ([subview respondsToSelector:@selector(setTitle:)]) {
[subview setTitle:@"Map"];
}
}
如果您在更改 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];
}
}
如果 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
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版本
在 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)
}
}
}
}