UISearchBar透明背景视图

21
在UISearchBar中默认会呈现一个背景视图。怎样隐藏这个背景视图?我只需要 UISearchBar 中的搜索文本框部分。
12个回答

61
[[searchBar.subviews objectAtIndex:0] removeFromSuperview];

4
当我使用以下代码行时,这个方法对我有用: searchBar.backgroundColor = [UIColor clearColor]; - Josh Brown
我正在使用Xcode 4.01和iOS 4.3。这对我不起作用。还尝试使用上面建议的clearColor,但没有进展。 - quano
我验证了4.2和4.3之间没有变化 - 如果没有其他东西消失,那么您可能没有正确设置IB连接。 - Brandon
10
看起来这个方法可行,但前提条件是搜索栏的样式设置为“黑色半透明”。 - Timothy Groote
4
对我来说没问题(在iOS 6.1模拟器,Xcode 5.0.2上测试通过),无需进行任何修改,但要小心!在iOS 7上,它会移除搜索栏本身,因此在使用此方法之前应检查iOS版本。 - FreeNickname
显示剩余2条评论

24

这里有一个适用于iOS 5和的解决方案。我已经检查过,不需要更改任何其他属性(比如将背景颜色设置为[UIColor clearColor])就可以让它起作用。

for (UIView * v in searchBar.subviews) {
    if ([v isKindOfClass:NSClassFromString(@"UISearchBarTextField")]) {
        v.superview.alpha = 0;
        UIView *containerView = [[UIView alloc] initWithFrame:searchBar.frame];
        [containerView addSubview:v];
        [self.view addSubview:containerView];
    }
}

1
我试过其他5个(设置图像等等...)都不起作用,但这个在iOS 6上立即起作用了! - fellowworldcitizen
有一个更少 hackie 的解决方案,请检查 @Coeur 的回答。 - Levi

18

自iOS 5开始,我建议采用以下方式,避免与未记录的子视图混淆。如果您是对UISearchBarController进行子类化而不是对UISearchBar本身进行子类化,请使用self.searchBar替换self

// transparency for UISearchBar
self.translucent = YES;
self.backgroundImage = [UIImage new];
self.scopeBarBackgroundImage = [UIImage new];

还有一个额外的好处:

// transparency for UIToolbar
self.translucent = YES;
[self setBackgroundImage:[UIImage new] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
[self setShadowImage:[UIImage new] forToolbarPosition:UIToolbarPositionAny];

// transparency for UINavigationBar
self.translucent = YES;
[self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
self.shadowImage = [UIImage new];

// transparency for UITabBar
self.backgroundImage = [UIImage new];
self.shadowImage = [UIImage new];

非常棒的回答。非常感谢您更新这篇旧文章。幸运的是,我在我的代码中保存了链接,并来到这里,因为我正在解决iOS7的兼容性问题。 - Kevin Zych

11

更新:自iOS 5.0起,如果有可用的背景图像,现在可以执行以下操作:

searchBar.backgroundImage = someUIImage;

(仅在iOS 6上进行了测试,因此可能在5上存在错误!将进行检查。)

Brandon的答案不再有效(或者对我来说不是这样),所以我四处看了看并注意到:

(gdb) po [searchBar subviews]
<__NSArrayM 0x665ab80>(
<UISegmentedControl: 0x63aad80; frame = (0 0; 225 44); opaque = NO; layer = <CALayer: 0x6368420>>,
<UISearchBarBackground: 0x6347280; frame = (0 0; 225 44); layer = <CALayer: 0x638a230>>,
<UISearchBarTextField: 0x6331110; frame = (0 0; 0 0); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x63a20f0>>
)

第三项是自定义文本字段,很可能是我想要的,但是奇怪的是,将子视图0和1从父视图中移除却没有解决问题。最终,我使用了以下方法,它确实有效

UITextField *sbTextField = (UITextField *)[searchBar.subviews lastObject];
[sbTextField removeFromSuperview];
[self.view addSubview:sbTextField];
sbTextField.frame = searchBar.frame;
[searchBar removeFromSuperview];

为了使其更加健壮,最好检查该类是否是文本字段的子类等。但除非出现问题,否则我只会保持简单。

编辑:根据tipycalFlow的建议将objectAtIndex:2更改为lastObject


1
+1,太棒了!虽然在索引2处删除子视图不总是有效,因为数组大小显然不是固定的。更好的方法是UITextField *sbTextField = (UITextField *)[searchBar.subviews lastObject]; - tipycalFlow
Daniel:我们正在使用这个应用程序在应用商店中。 - Kalle
有一个更少“hackie”的解决方案,请查看@Coeur的答案。 - Levi
设置 backgroundImage 不是hacky的,而且@Coeur的答案在iOS 7下对我也不起作用。即使将 translucent 设置为 NO,状态栏的色调始终会变得暗淡无光。 - devios1

10

对于寻找答案的未来访问者。我发现以下方法在iOS 5+上非常有效,并且我更喜欢它,因为它不涉及 messing with the layout of the UISearchBar itself。

UISearchBar * search = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
[search setBackgroundColor:[UIColor clearColor]];
[search setPlaceholder:@"Search"];

for (UIView * v in [search subviews]) {
    if (![v isKindOfClass:[UITextField class]]) {
        v.alpha = 0;
    }
}

[header addSubview:search];
[search release];

2

我尝试使用蒙版层来使搜索栏中文本字段周围的所有内容透明(从而显示下方视图的内容)。虽然这种方法有效,但在发布应用时我会感到紧张,因为您必须确切地匹配蒙版的形状与UISearchBar中的文本字段的形状。如果Apple更改文本字段的形状,则您的蒙版将不适合,您将看到您不想要的搜索栏渐变部分和/或您不想要的文本字段部分将被遮盖。话虽如此,以下是我的做法:

//first make sure you include core animation so that the compiler will know about your view's layer
#import <QuartzCore/QuartzCore.h>

//now make a mask.  this is basically just a solid colored shape.  When you apply the mask, anywhere where the color is solid will become transparent in your view.  i used the excellent Opacity (http://likethought.com/opacity/) to generate this code, but you can do it any way you'd like

@interface SearchMaskLayer : CALayer {
}
@end

@implementation SearchMaskLayer

- (void)drawInContext:(CGContextRef)context
{


    CGRect imageBounds = CGRectMake(0, 0, 310, 34);
    CGRect bounds = imageBounds;

    CGFloat alignStroke;
    CGFloat resolution;
    CGMutablePathRef path;
    CGPoint point;
    CGPoint controlPoint1;
    CGPoint controlPoint2;
    UIColor *color;
    resolution = 0.5 * (bounds.size.width / imageBounds.size.width + bounds.size.height / imageBounds.size.height);

    CGContextSaveGState(context);
    CGContextTranslateCTM(context, bounds.origin.x, bounds.origin.y);
    CGContextScaleCTM(context, (bounds.size.width / imageBounds.size.width), (bounds.size.height / imageBounds.size.height));

    // Layer 1

    alignStroke = 0.0;
    path = CGPathCreateMutable();
    point = CGPointMake(295.0, 32.0);
    point.x = (round(resolution * point.x + alignStroke) - alignStroke) / resolution;
    point.y = (round(resolution * point.y + alignStroke) - alignStroke) / resolution;
    CGPathMoveToPoint(path, NULL, point.x, point.y);
    point = CGPointMake(310.0, 17.0);
    point.x = (round(resolution * point.x + alignStroke) - alignStroke) / resolution;
    point.y = (round(resolution * point.y + alignStroke) - alignStroke) / resolution;
    controlPoint1 = CGPointMake(303.229, 32.0);
    controlPoint1.x = (round(resolution * controlPoint1.x + alignStroke) - alignStroke) / resolution;
    controlPoint1.y = (round(resolution * controlPoint1.y + alignStroke) - alignStroke) / resolution;
    controlPoint2 = CGPointMake(310.0, 25.229);
    controlPoint2.x = (round(resolution * controlPoint2.x + alignStroke) - alignStroke) / resolution;
    controlPoint2.y = (round(resolution * controlPoint2.y + alignStroke) - alignStroke) / resolution;
    CGPathAddCurveToPoint(path, NULL, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, point.x, point.y);
    point = CGPointMake(310.0, 17.0);
    point.x = (round(resolution * point.x + alignStroke) - alignStroke) / resolution;
    point.y = (round(resolution * point.y + alignStroke) - alignStroke) / resolution;
    CGPathAddLineToPoint(path, NULL, point.x, point.y);
    point = CGPointMake(295.0, 2.0);
    point.x = (round(resolution * point.x + alignStroke) - alignStroke) / resolution;
    point.y = (round(resolution * point.y + alignStroke) - alignStroke) / resolution;
    controlPoint1 = CGPointMake(310.0, 8.771);
    controlPoint1.x = (round(resolution * controlPoint1.x + alignStroke) - alignStroke) / resolution;
    controlPoint1.y = (round(resolution * controlPoint1.y + alignStroke) - alignStroke) / resolution;
    controlPoint2 = CGPointMake(303.229, 2.0);
    controlPoint2.x = (round(resolution * controlPoint2.x + alignStroke) - alignStroke) / resolution;
    controlPoint2.y = (round(resolution * controlPoint2.y + alignStroke) - alignStroke) / resolution;
    CGPathAddCurveToPoint(path, NULL, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, point.x, point.y);
    point = CGPointMake(15.0, 2.0);
    point.x = (round(resolution * point.x + alignStroke) - alignStroke) / resolution;
    point.y = (round(resolution * point.y + alignStroke) - alignStroke) / resolution;
    CGPathAddLineToPoint(path, NULL, point.x, point.y);
    point = CGPointMake(0.0, 17.0);
    point.x = (round(resolution * point.x + alignStroke) - alignStroke) / resolution;
    point.y = (round(resolution * point.y + alignStroke) - alignStroke) / resolution;
    controlPoint1 = CGPointMake(6.771, 2.0);
    controlPoint1.x = (round(resolution * controlPoint1.x + alignStroke) - alignStroke) / resolution;
    controlPoint1.y = (round(resolution * controlPoint1.y + alignStroke) - alignStroke) / resolution;
    controlPoint2 = CGPointMake(0.0, 8.771);
    controlPoint2.x = (round(resolution * controlPoint2.x + alignStroke) - alignStroke) / resolution;
    controlPoint2.y = (round(resolution * controlPoint2.y + alignStroke) - alignStroke) / resolution;
    CGPathAddCurveToPoint(path, NULL, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, point.x, point.y);
    point = CGPointMake(0.0, 17.0);
    point.x = (round(resolution * point.x + alignStroke) - alignStroke) / resolution;
    point.y = (round(resolution * point.y + alignStroke) - alignStroke) / resolution;
    CGPathAddLineToPoint(path, NULL, point.x, point.y);
    point = CGPointMake(15.0, 32.0);
    point.x = (round(resolution * point.x + alignStroke) - alignStroke) / resolution;
    point.y = (round(resolution * point.y + alignStroke) - alignStroke) / resolution;
    controlPoint1 = CGPointMake(0.0, 25.229);
    controlPoint1.x = (round(resolution * controlPoint1.x + alignStroke) - alignStroke) / resolution;
    controlPoint1.y = (round(resolution * controlPoint1.y + alignStroke) - alignStroke) / resolution;
    controlPoint2 = CGPointMake(6.771, 32.0);
    controlPoint2.x = (round(resolution * controlPoint2.x + alignStroke) - alignStroke) / resolution;
    controlPoint2.y = (round(resolution * controlPoint2.y + alignStroke) - alignStroke) / resolution;
    CGPathAddCurveToPoint(path, NULL, controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, point.x, point.y);
    point = CGPointMake(295.0, 32.0);
    point.x = (round(resolution * point.x + alignStroke) - alignStroke) / resolution;
    point.y = (round(resolution * point.y + alignStroke) - alignStroke) / resolution;
    CGPathAddLineToPoint(path, NULL, point.x, point.y);
    CGPathCloseSubpath(path);
    color = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
    [color setFill];
    CGContextAddPath(context, path);
    CGContextFillPath(context);
    CGPathRelease(path);
}

在您的某个方法中,稍后应用该掩码

- (void)viewDidLoad {
    [super viewDidLoad];
    SearchMaskLayer *maskLayer = [[SearchMaskLayer alloc] init];
    [maskLayer setFrame:CGRectMake(0, 0, 310, 34)];
    [maskLayer setPosition:CGPointMake(162,21)];
    [maskLayer setNeedsDisplay];    
    [self.searchBar.layer setNeedsDisplay];
    [self.searchBar.layer setMask:maskLayer];
    [maskLayer release];
}

我故意调整了图层的位置,只是为了看看它会是什么样子,但你可以计算出适合自己需要的尺寸和位置。


1
如果遇到编译错误,请确保已包含QuartzCore框架:https://dev59.com/3nA85IYBdhLWcg3wCfDm - Ying
天啊,这个可行!它有点粗糙,所以Kalperin,如果你有更新的版本,请分享:)与此同时,我会尝试看看能否挖掘一下,使其符合我的需求。 - Ying
不幸的是,以某种方式附加这些遮罩会防止 UISearchBar 在视图大小发生变化时自动调整大小,例如从纵向到横向。对我来说不可行,但非常酷炫! - Ying
@Ying,我没有更新。我仍然不想发布任何像这样的东西(无论您的自动调整大小问题如何),但图层蒙版仍然是一个有用的工具。 - kalperin

2

这里是关于此问题的博客文章

我采用了与Weaverfish类似的方法。不过,我将设置子视图alpha属性的过程封装在了一个独立的类中。

您可以按照以下方式对UISearchBar进行子类化:

在UITransparentBackgroundSearchBar.h文件中:

#import <UIKit/UIKit.h>
@interface UITransparentBackgroundSearchBar : UISearchBar
@end

在UITransparentBackgroundSearchBar.m文件中:

#import "UITransparentBackgroundSearchBar.h"
@implementation UITransparentBackgroundSearchBar

-(void)didAddSubview:(UIView *)subview {
    if (![subview isKindOfClass:[UITextField class]]) {
        subview.alpha = 0;
    }
}

@end

在你的故事板中,将搜索栏类设置为UITransparentBackgroundSearchBar,就完成了。
现在,我是iOS开发的新手,所以我不能说这是万无一失的。它似乎可以工作,并且如果我需要在另一个视图中使用相同的透明背景,它避免了代码重复。

2

公共方法无法隐藏UISearchBar的背景(将透明颜色分配为不起作用)。

如果您想要精确控制文本字段的样式,应使用UITextField。


如果你仍然支持iOS 4.x,那真的非常重要。 - slatvick

1

通过将1px * 1px的透明图像设置为backgroundImage属性,可以轻松制作。 在iOS 5、6上进行了测试。

searchBar.backgroundImage = [UIImage imageNamed:@"transparentImage.png"];

1
这个可以工作,但我发现你也必须将 searchBar.scopeBarBackgroundImage 设置为相同的透明图像。 - Lucien
我喜欢这个解决方案,因为它没有涉及任何黑客技巧。这比其他黑客技巧更加稳定。 - Jake

1

除了Kalle的答案外,其他答案都对我没用,但需要进行一些小的改进。

UITextField *sbTextField = (UITextField *)[self.mSearchBar.subviews lastObject];
[sbTextField removeFromSuperview];
[self.view addSubview:sbTextField];
CGRect sbFrame = self.mSearchBar.frame;
// Set the default height of a textfield
sbFrame.size.height = 31;   

/* 8 is the top padding for textfield inside searchbar
 * You may need to add a variable to 8 according to your requirement.
 */
sbFrame.origin.y = 8+ self.mSearchBar.superview.frame.origin.y;
sbTextField.frame = sbFrame;

[sbTextField setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin];  //to support different orientations.
[self.mSearchBar removeFromSuperview];

+1 给 Kalle。 (点赞)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接