改变iOS 7中UISearchBar的字体大小和字体样式

25

我该如何在iOS 7中改变UISearchBar的字体大小和字体样式?

UITextField *textField = [[searchBar subviews] objectAtIndex:1];
[textField setFont:[UIFont fontWithName:@"Helvetica" size:20]];

iOS 6上可以工作,但在iOS 7上崩溃了


1
什么是错误?不要深入标准UI组件的私有子视图结构。那些东西会改变并使您的代码出错。使用提供的API来完成这些操作。 - rmaddy
请查看此链接:https://dev59.com/52Ik5IYBdhLWcg3wr_9o 我认为你尝试实现的是相同的功能。 - o15a3d4l11s2
@rmaddy是正确的,我在我的答案中给出了安全方法的详细解释。 - Bhavin
9个回答

67

试一下这个,对于 iOS 5.0 及以上版本可以正常工作:(iOS 7同样适用)

- (void)viewDidLoad
{

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setFont:[UIFont fontWithName:@"Helvetica" size:20]];

}

适用于 iOS 8

- (void)viewDidLoad
    {

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:@{
            NSFontAttributeName: [UIFont fontWithName:@"Helvetica" size:20],
      }];

    }

3
我对此有一个小问题。我已经实现了相同的功能,并且它正在工作。但是,如果我导航到某个视图控制器并返回到同一屏幕,则字体会更改为默认设置。有任何想法吗? - Ganesh
1
在iOS 8上也是一样的情况。第一次使用时可以正常工作。但是当我导航到另一个屏幕并返回时,字体又回到了系统默认值。 - Mike
UISearchBar没有从textfield继承。 - jeet.chanchawat
@jeet.chanchawat - 那并不重要。外观是为UISearchBar的子视图中的UITextFields定义的,而其中确实存在一个。 - Adam Kaplan
'appearanceWhenContainedIn:'已被弃用:自iOS 9.0起首次弃用-请改用+appearanceWhenContainedInInstancesOfClasses: [[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setDefaultTextAttributes:@{ NSFontAttributeName: [UIFont fontWithName:@"Helvetica" size:20] }]; - Sathe_Nagaraja
显示剩余2条评论

34

对我来说,被接受的答案在iOS 7.1上无效。我不得不将其更改为以下内容:

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setDefaultTextAttributes:@{
            NSFontAttributeName: [UIFont fontWithName:@"Avenir-Heavy" size:20.],
}];

3
这种方法克服了Ganesh在评论中提到的问题(在iOS 8.0上尝试),即仅使用setFont而不使用setDefaultTextAttribute时,文本仅在第一个视图上更改,并且在从屏幕导航回来后不会更改。 - Mike
这个答案更好。 - Harshit Gupta
是的,这是唯一一种在 iOS 8.1 上每次都能正常工作的方法。 - Mike Gledhill

6

iOS 10 Swift 3:

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSFontAttributeName:UIFont(name: "Avenir-Heavy", size: 22)!]

2

appearanceWhenContainedIn:在iOS9中已经被弃用,请使用以下方式:

[[UITextField appearanceWhenContainedInInstancesOfClasses:@[[UISearchBar class]]] setDefaultTextAttributes:@{ NSFontAttributeName: [UIFont fontWithName:@"FontName" size:14]}];

1

对于那些寻找工作的Swift版本的人,我已经适应了这个答案。Swift目前不支持Objc可变参数方法,因此不能直接使用上述方法。我们可以通过创建一个不使用可变参数并调用所需内容的Objective-C类别来解决这个问题:

// UIAppearance+Swift.h
@interface UIView (UIViewAppearance_Swift)
// appearanceWhenContainedIn: is not available in Swift. This fixes that.
+ (instancetype)my_appearanceWhenContainedIn:(Class<UIAppearanceContainer>)containerClass;
@end

// UIAppearance+Swift.m
@implementation UIView (UIViewAppearance_Swift)
+ (instancetype)my_appearanceWhenContainedIn:(Class<UIAppearanceContainer>)containerClass {
    return [self appearanceWhenContainedIn:containerClass, nil];
}
@end

请确保在桥接头文件中导入#import "UIAppearance+Swift.h"

然后只需调用:

UITextField.my_appearanceWhenContainedIn(UISearchBar.self).font = UIFont.systemFontOfSize(14.0)

1

对于Swift 4,您需要引用NSAttributedStringKey枚举:

UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self])
        .defaultTextAttributes = [NSAttributedStringKey.font.rawValue: UIFont(...)]

在iOS11(Swift 4)中可以加快工作。特别是.rawValue是我所缺少的。 - Rishi
类型“NSAttributedStringKey”(又名“NSString”)没有成员“font”。 - Erick Maynard

1

正如rmaddy所说,你不应该依赖于标准UI组件的私有子视图结构。这些会发生变化并导致代码崩溃。相反,你应该使用提供的API来完成这些操作。

我认为更加安全的方法是:

[[UITextField appearanceWhenContainedIn:[UISearchBar class], nil] setFont:[UIFont systemFontOfSize:14]];

或者您也可以使用此示例代码:
for(UIView *subView in searchBar.subviews) {
    if ([subView isKindOfClass:[UITextField class]]) {
        UITextField *searchField = (UITextField *)subView;
        searchField.font = [UIFont systemFontOfSize:14];
    }
}

上面的代码也更安全(至少与问题中提到的那个相比),因为它没有使用subviewsindex

这里的第二种方法似乎不太安全。您仍然依赖于子视图结构,因为您假设UISearchBar具有UITextField作为直接子视图。仅仅因为避免使用索引并不意味着避免私有子视图结构。 - rickerbh
@rickerbh:是的,没错。实际上,我也认为 OP 应该使用我在答案中提到的第一种方法。 - Bhavin

1
在Swift 5中,@Piotr Tomasik的代码仍然可以使用,只需稍作修改即可。
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedString.Key.font:UIFont(name: "poppins", size: 13)!]

0
  • SWIFT
  • iOS 8

对我来说,使用递归函数查找实际文本字段的方法很有效。

extension UIView {

func recursive_applyTheme_Search(
    #dynamicTextStyle: NSString,
    bgColor: UIColor,
    cursorColor: UIColor,
    textColor: UIColor,
    placeholderTextColor: UIColor,
    borderColor: UIColor,
    borderWidth: CGFloat,
    cornerRadius: CGFloat) {

    for subview in self.subviews
    {
        if subview is UITextField {

            (subview as! UITextField).applyThemeForSearchBar(
                dynamicTextStyle: dynamicTextStyle,
                bgColor: bgColor,
                cursorColor: cursorColor,
                textColor: textColor,
                placeholderTextColor: placeholderTextColor,
                borderColor: borderColor,
                borderWidth: borderWidth,
                cornerRadius: cornerRadius)
        }
        else { subview.recursive_applyTheme_Search(
                dynamicTextStyle: dynamicTextStyle,
                bgColor: bgColor,
                cursorColor: cursorColor,
                textColor: textColor,
                placeholderTextColor: placeholderTextColor,
                borderColor: borderColor,
                borderWidth: borderWidth,
                cornerRadius: cornerRadius) }
    }

}
}

此外,大多数WWDC视频建议字体应符合动态类型,使用let font = UIFont.preferredFontForTextStyle(UIFontTextStyleBody) - Andrei Popa

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