ios 在 UISearchBar 中设置取消按钮的样式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1200149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Styling the cancel button in a UISearchBar
提问by Chu Yeow
I have a UISearchBar that has a cancel button (it's displayed using -(void)setShowsCancelButton:animated
). I've changed the tintColor
of the search bar like this in an attempt to get a grayish searchbar:
我有一个带有取消按钮的 UISearchBar(它使用 显示-(void)setShowsCancelButton:animated
)。我已经tintColor
像这样更改了搜索栏,试图获得一个灰色的搜索栏:
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 40)];
searchBar.tintColor = [UIColor colorWithWhite:0.8 alpha:1.0];
This is what it looks like now - notice how the cancel button is also gray: http://twitpic.com/c0hte
这就是现在的样子 - 注意取消按钮也是灰色的:http: //twitpic.com/c0hte
Is there a way to set the color of the cancel button separately so it looks more like this: http://twitpic.com/c0i6q
有没有办法单独设置取消按钮的颜色,使其看起来更像这样:http: //twitpic.com/c0i6q
采纳答案by Amagrammer
What you want to do is pretty tough. There is no built-in hook to get at the cancel button.
你想做的事情很艰难。没有内置的钩子可以到达取消按钮。
However, there are a couple of options if you are willing to jimmy open the hood.
但是,如果您愿意打开引擎盖,有几种选择。
First off, UISearchBar is a UIView, and the Cancel button is also a view, which is added into the search bar as a subview, just as you would expect.
首先,UISearchBar 是一个 UIView,而 Cancel 按钮也是一个视图,正如您所期望的那样,它作为子视图添加到搜索栏中。
I have experimented a little, and can tell you that when the button is onscreen it has a size of 48,30.
我进行了一些实验,可以告诉您,当按钮在屏幕上时,它的大小为 48,30。
So in viewWillAppear, you can do something like this:
因此,在 viewWillAppear 中,您可以执行以下操作:
Find the cancel button view in [searchBar subviews] by looking for one with size 48,30. (There only seems to be one -- this could change...) You could be doubly careful and look for one that is in approximately the correct position (differs in landscape and portrait).
Add a subview to the cancel button.
The subview should be a UIControl (so that you can set enabled = NO, in order to make sure touch events get to the actual cancel button)
It needs to have the right color and rounded corners; you will need to fudge the size for reasons I don't yet understand (55,30 seems to work)
This will work if searchBar.showsCancelButton is always YES; if you want it to disappear when not editing the search string, you will need to find a hook to add the overlay each time the cancel button appears.
As you can see, this is some ugly tinkering. Do it with eyes wide open.
在 [searchBar subviews] 中查找大小为 48,30 的取消按钮视图。(似乎只有一个——这可能会改变......)你可以加倍小心,寻找一个位置大致正确的(横向和纵向不同)。
向取消按钮添加子视图。
子视图应该是一个 UIControl(这样你就可以设置 enabled = NO,以确保触摸事件到达实际的取消按钮)
它需要有正确的颜色和圆角;由于我还不明白的原因,您需要捏造大小(55,30 似乎有效)
如果 searchBar.showsCancelButton 始终为 YES,这将起作用;如果您希望它在不编辑搜索字符串时消失,则每次出现取消按钮时都需要找到一个钩子来添加叠加层。
如您所见,这是一些丑陋的修补。睁大眼睛做这件事。
回答by lemnar
You can use UIAppearance
to style the cancel button without iterating subviews of the UISearchBar
, but the UIButton
header does not currently have any methods annotated with UI_APPEARANCE_SELECTOR
.
您可以使用UIAppearance
样式不反复的子视图的取消按钮UISearchBar
,但在UIButton
头目前没有与任何注释的方法UI_APPEARANCE_SELECTOR
。
EDIT: Drill down the subviews till you get that cancel button
编辑:向下钻取子视图,直到您获得取消按钮
But this usually returns nil until
searchBar.setShowsCancelButton(true, animated: true)
is called.
但这通常返回 nil 直到
searchBar.setShowsCancelButton(true, animated: true)
被调用。
extension UISearchBar {
var cancelButton : UIButton? {
if let view = self.subviews.first {
for subView in view.subviews {
if let cancelButton = subView as? UIButton {
return cancelButton
}
}
}
return nil
}
}
回答by Neru-J
Change the title of 'Cancel' button:
更改“取消”按钮的标题:
[[UIButton appearanceWhenContainedIn:[UISearchBar class], nil] setTitle:@"newTitle" forState:UIControlStateNormal];
Swift equivalent:
Swift 等效项:
let cancelButton = UIButton.appearance(whenContainedInInstancesOf: [UISearchBar.self])
cancelButton?.setTitle("cancel".localized, for: .normal)
回答by Yiming Tang
In iOS 5.0+, you can use the appearnce
proxy.
在 iOS 5.0+ 中,您可以使用appearnce
代理。
Before the search bar is showed.:
在显示搜索栏之前。:
UIBarButtonItem *searchBarButton = [UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil];
[searchBarButton setBackgroundImage:myCancelButtonImageNormal forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[searchBarButton setBackgroundImage:myCancelButtonImageHighlighted forState:UIControlStateHighlighted barMetrics:UIBarMetricsDefault];
[searchBarButton setTitleTextAttributes:barButtonTitleTextAttributesNormal forState:UIControlStateNormal];
[searchBarButton setTitleTextAttributes:barButtonTitleTextAttributesHighlighted forState:UIControlStateHighlighted];
If you use [UIButton appearanceWhenContainedIn:[UISearchBar class], nil]
, it will affect other buttons (e.g. clear button). So, you'd better not use UIButton
's appearnce. Try UIBarButtonItem
.
如果使用[UIButton appearanceWhenContainedIn:[UISearchBar class], nil]
,它会影响其他按钮(例如清除按钮)。所以,你最好不要使用UIButton
的出现。试试UIBarButtonItem
。
回答by Sara
Though this might not be exactly relevant to the original question, the solution is still applicable in the larger sense of trying to customize the Cancel button in the UISearchBar. Thought this will help others who are stuck in such a scenario.
尽管这可能与原始问题不完全相关,但该解决方案在尝试自定义 UISearchBar 中的取消按钮的更大意义上仍然适用。认为这将帮助陷入这种情况的其他人。
My situation was to change the cancel button's title, but with a twist, wherein I did not want to show the cancel button by default but only wanted it to show up, when the user enters the search mode (by clicking inside the search text field). At this instant, I wanted the cancel button to carry the caption "Done" ("Cancel" was giving a different meaning to my screen, hence the customization).
我的情况是更改取消按钮的标题,但有一点变化,其中我不想在默认情况下显示取消按钮,而只想在用户进入搜索模式时(通过在搜索文本字段内单击)显示它)。此时,我希望取消按钮带有标题“完成”(“取消”对我的屏幕赋予不同的含义,因此自定义)。
Nevertheless, here's what I did (a combination of caelavel's and Arenim's solutions):
尽管如此,这就是我所做的(caelavel 和 Arenim 解决方案的组合):
Subclassed UISearchBar as MyUISearchBar with these two methods:
使用以下两种方法将 UISearchBar 子类化为 MyUISearchBar:
-(void) setCloseButtonTitle: (NSString *) title forState: (UIControlState)state
{
[self setTitle: title forState: state forView:self];
}
-(void) setTitle: (NSString *) title forState: (UIControlState)state forView: (UIView *)view
{
UIButton *cancelButton = nil;
for(UIView *subView in view.subviews){
if([subView isKindOfClass:UIButton.class])
{
cancelButton = (UIButton*)subView;
}
else
{
[self setTitle:title forState:state forView:subView];
}
}
if (cancelButton)
[cancelButton setTitle:title forState:state];
}
And in the viewcontroller which uses this Searchbar, the following piece of code takes care of showing the cancel button and customizing its title:
在使用此搜索栏的视图控制器中,以下代码负责显示取消按钮并自定义其标题:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
MyUISearchBar *sBar = (MyUISearchBar *)searchBar;
[sBar setShowsCancelButton:YES];
[sBar setCloseButtonTitle:@"Done" forState:UIControlStateNormal];
}
Strangely enough, I did not have to do anything to hide the cancel button, as it is hidden by default, when the search mode is exited.
奇怪的是,当退出搜索模式时,我没有做任何事情来隐藏取消按钮,因为默认情况下它是隐藏的。
回答by Andrew Homeyer
You can find the cancel button by looping through the subviews of the search bar and checking for the class type (instead of the size):
您可以通过循环搜索栏的子视图并检查类类型(而不是大小)来找到取消按钮:
UIButton *cancelButton = nil;
for(UIView *subView in yourSearchBar.subviews){
if([subView isKindOfClass:UIButton.class]){
cancelButton = (UIButton*)subView;
}
}
And then change the tint color:
然后更改色调颜色:
[cancelButton setTintColor:[UIColor colorWithRed:145.0/255.0 green:159.0/255.0 blue:179.0/255.0 alpha:1.0]];
回答by dpart
If you want to configure your cancel button on UISearchBar
you should get the UIButton
object from your UISearchBar
object. Example below
如果你想配置你的取消按钮,UISearchBar
你应该UIButton
从你的UISearchBar
对象中获取对象。下面的例子
UISearchBar *s_bar = [[UISearchBar alloc] initWithFrame:CGRectMake(50,20,300,30)];
s_bar.delegate = self;
s_bar.barStyle = UIBarStyleDefault;
s_bar.showsCancelButton = YES;
UIButton *cancelButton;
for (id button in s_bar.subviews)
{
if ([button isKindOfClass:[UIButton class]])
{
cancelButton=(UIButton*)button;
break;
}
}
回答by Mr. Ming
Custom UISearchBar and override method -addSubview:
自定义 UISearchBar 和覆盖方法 -addSubview:
- (void) addSubview:(UIView *)view {
[super addSubview:view];
if ([view isKindOfClass:UIButton.class]) {
UIButton *cancelButton = (UIButton *)view;
[cancelButton setBackgroundImage:[UIImage imageNamed:@"xxxx.png"] forState:UIControlStateNormal];
[cancelButton setBackgroundImage:[UIImage imageNamed:@"yyyy.png"] forState:UIControlStateHighlighted];
}
}
回答by C?ur
I'll give a detailed answered regarding the UIAppearance technique. First, you need to understand that the cancel button is a private UINavigationButton:UIButton. After some inspection, it appears that UINavigationButton will respond to those UIAppearance selectors:
我将详细回答有关 UIAppearance 技术的问题。首先,您需要了解取消按钮是一个私有的 UINavigationButton:UIButton。经过一些检查,似乎 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:)
Coincidentally, those selectors match those of a UIBarButtonItem. Meaning the trick is to use two separate UIAppearance to handle the private class UINavigationButton.
巧合的是,这些选择器与 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:...];
// only for a backButton in an UINavigationBar, not for a cancelButton in an UISearchBar
//[barButtonItemAppearanceInBar setBackButtonBackgroundImage:... forState:... barMetrics:...];
//[barButtonItemAppearanceInBar setBackButtonTitlePositionAdjustment:... forBarMetrics:...];
//[barButtonItemAppearanceInBar setBackButtonBackgroundVerticalPositionAdjustment:... forBarMetrics:...];
UIButton<UIAppearance> *buttonAppearanceInBar = [UIButton appearanceWhenContainedIn:barClass, nil];
// warning: doesn't work for iOS7+
[buttonAppearanceInBar setTitle:... forState:...];
This will let you customize your Cancel button as much as you want.
这将使您可以根据需要自定义“取消”按钮。
回答by Elliott Davies
Swift 2.1.1:
斯威夫特 2.1.1:
There's no simple way to hook in and style the search bar, you need to grab the subview manually from the search bar and then apply your changes.
没有简单的方法来挂钩和设置搜索栏的样式,您需要从搜索栏中手动抓取子视图,然后应用您的更改。
var cancelButton: UIButton
let topView: UIView = self.customSearchController.customSearchBar.subviews[0] as UIView
for subView in topView.subviews {
if subView.isKindOfClass(NSClassFromString("UINavigationButton")!) {
cancelButton = subView as! UIButton
cancelButton.enabled = true
cancelButton.setTitle("TestTitle", forState: UIControlState.Normal) // Change to set the title
cancelButton.setBackgroundImage(UIImage(named: "ImageName"), forState: .Normal) // Change this to set a custom cancel button image, set the title to "" to remove 'Cancel' text
}
}