如何在Swift中将UiSearchBar搜索图标设置在右侧

8
我正在学习Swift。
作为常规的SearchBar,默认情况下它会出现如下图(1)所示。 enter image description here 但根据我们的设计要求,我需要将其更改为以下图(2)所示。

enter image description here

我尝试使用以下代码,结果如图(3)所示。

enter image description here

当我尝试以下代码时,右侧视图被隐藏了,我无法看到文本框的右侧视图

搜索图标完全不可见

let searchField = (searchBar.valueForKey("_searchField") as! UITextField)
searchField.layer.cornerRadius = 15;


    let searchIcon = searchField.leftView!
    if (searchIcon is UIImageView) {
        print("yes")
    }

    searchField.rightView = searchIcon
  searchField.leftViewMode = .Never
searchField.rightViewMode = .Always

有人能帮我获取需求吗?如果您能提供Objective C的话,我也可以理解。

5个回答

21

在ViewController中,搜索栏文本字段的leftview是实际的搜索图标,因此将其设置为nil,并创建一个带有自定义图标的图像视图并将其设置为搜索文本字段的右视图。

Objective C

@interface FirstViewController ()
{
    UISearchBar  *searchBar;
}
@end

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    searchBar = [[UISearchBar alloc] init];
    searchBar.frame = CGRectMake(15, 100, 350,50);

    [self.view addSubview:searchBar];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    UITextField *searchTextField = [((UITextField *)[searchBar.subviews objectAtIndex:0]).subviews lastObject];
    searchTextField.layer.cornerRadius = 15.0f;
    searchTextField.textAlignment = NSTextAlignmentLeft;

    UIImage *image = [UIImage imageNamed:@"search"];
    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

    searchTextField.leftView = nil;

    searchTextField.placeholder = @"Search";

    searchTextField.rightView = imageView;
    searchTextField.rightViewMode = UITextFieldViewModeAlways;
}

Swift

    private var searchBar: UISearchBar!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        searchBar = UISearchBar()
        searchBar.frame = CGRect(x: 15, y: 100, width: 350, height: 50)
        self.view.addSubview(searchBar)

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        let searchTextField:UITextField = searchBar.subviews[0].subviews.last as! UITextField
        searchTextField.layer.cornerRadius = 15
        searchTextField.textAlignment = NSTextAlignment.left
        let image:UIImage = UIImage(named: "search")!
        let imageView:UIImageView = UIImageView.init(image: image)
        searchTextField.leftView = nil
        searchTextField.placeholder = "Search"
        searchTextField.rightView = imageView
        searchTextField.rightViewMode = UITextFieldViewMode.always
    }

输入图像描述


1
我们必须在viewDidLayoutSubviews()之后设置searchTextField,但我不知道为什么。似乎searchTextField会覆盖在viewDidLayoutSubviews()之前设置的配置。 - Jerome
将以下代码添加到viewDidLayoutSubviews()中对我很有帮助,谢谢! - Threadripper

4
我建议您查看苹果文档中的layoutIfNeeded()layoutSubviews()。阅读后,您将更好地理解它们。当您编写searchBar.layoutIfNeeded()实例方法时,效果神奇。另一种解决方案是调用searchBar.layoutSubviews(),但是根据苹果文档的说法:

不应直接调用此方法。如果要强制进行布局更新,请在下一次绘图更新之前调用setNeedsLayout()方法。如果要立即更新视图的布局,请调用layoutIfNeeded()方法。

根据@Jeyamahesan的回答。当您像下面这样修改代码时,无需将代码分别放在viewDidLoad()和ViewDidAppear()中。

示例:

import UIKit

class MainController: UIViewController {

    private var searchBar: UISearchBar!

    override func viewDidLoad() {
        super.viewDidLoad()

        searchBar = UISearchBar()
        searchBar.frame = CGRect(x: 15, y: 100, width: 350, height: 50)
        searchBar.layoutIfNeeded()
        self.view.addSubview(searchBar)

        let searchTextField:UITextField = searchBar.subviews[0].subviews.last as! UITextField
        searchTextField.layer.cornerRadius = 15
        searchTextField.textAlignment = NSTextAlignment.left
        let image:UIImage = UIImage(named: "Search")!
        let imageView:UIImageView = UIImageView.init(image: image)
        searchTextField.leftView = nil
        searchTextField.placeholder = "Search"
        searchTextField.rightView = imageView
        searchTextField.rightViewMode = UITextFieldViewMode.always
    }
}

我解决问题的方法:

MainView.swift

import UIKit

class MainView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    private func setupUI() {
        backgroundColor = UIColor.lightGray
        setupSubViews()
        setupAutoLayout()
    }

    // MARK: Initialize UI Elements
    private let searchBar: UISearchBar = {
        let searchBar = UISearchBar()
        searchBar.isTranslucent = false
        searchBar.barTintColor = ColorPalette.LuminousDay.white
        searchBar.layoutIfNeeded()
        return searchBar
    }()

    private let searchImageView: UIImageView = {
        let image = UIImage(named: "Search")
        let imageView = UIImageView(image: image)
        imageView.contentMode = .scaleAspectFit
        return imageView
    }()

    private lazy var searchBarTextField: UITextField = { [unowned self] in
        let textField = self.searchBar.value(forKey: "searchBarTextField") as! UITextField
        textField.font = FontBook.SourceSansPro.Weight.semiBold.setFont(size: 24)
        textField.textColor = ColorPalette.LuminousDay.charm
        textField.tintColor = ColorPalette.LuminousDay.charm
        textField.clearButtonMode = .never
        textField.leftViewMode = .never
        textField.leftView = nil
        textField.rightViewMode = .always
        textField.rightView = self.searchImageView
        return textField
    }()

    private func setupSubViews() {
        addSubview(searchBar)
        searchBar.addSubview(searchBarTextField)
        searchBarTextField.addSubview(searchImageView)
    }

    private func setupAutoLayout() {
        searchBar.anchor(top: safeAreaLayoutGuide.topAnchor, bottom: nil,
                         leading: safeAreaLayoutGuide.leadingAnchor, trailing: safeAreaLayoutGuide.trailingAnchor,
                         centerX: nil, centerY: nil,
                         centerXconstant: nil, centerYconstant: nil,
                         size: CGSize.zero, padding: UIEdgeInsets(top: 50, left: 0, bottom: 0, right: 0))

        searchImageView.setSize(size: CGSize(width: 16, height: 16))
    }
}

MainController.swift

import UIKit

class MainController: UIViewController {

    override func loadView() {
        view = MainView()
    }

    override func viewDidLoad() {
        super.viewDidLoad()

    }
}

1
以下是使用故事板在Swift 5和iOS 13或更高版本中完整的搜索视图自定义。
    @IBOutlet weak var searchview: UISearchBar!

    override func viewDidLoad() {
            super.viewDidLoad()
    
        //make background vertical  line
        searchview.backgroundImage = UIImage()
        
        if #available(iOS 13.0, *) {
                let searchTextField:UITextField = searchview.searchTextField
                searchTextField.textAlignment = .left
                searchTextField.layer.cornerRadius = 20
                searchTextField.layer.masksToBounds = true
                searchTextField.rightView = nil

                //your custom icon here
                let image:UIImage = UIImage(named: "Search")!
                let imageV:UIImageView = UIImageView.init(image: image)
                searchTextField.rightView = nil
                searchTextField.placeholder = "Search"
                searchTextField.leftView = imageV
                //dafault search icon
                let imageV = searchTextField.leftView as! UIImageView
                imageV.image = imageV.image?.withRenderingMode(UIImage.RenderingMode.alwaysTemplate)
                imageV.tintColor = UIColor.lightGray
                
            }
    
 }

1
尝试这个,并在 viewDidLayoutSubviews() 中调用它。
func SearchText(to searchBar: UISearchBar, placeHolderText: String) {
        searchBar.barTintColor = UIColor.clear
        searchBar.backgroundColor = UIColor.clear
        searchBar.isTranslucent = true
        searchBar.setBackgroundImage(UIImage(), for: .any, barMetrics: .default)
        
        let searchTextField:UITextField = searchBar.value(forKey: "searchField") as? UITextField ?? UITextField()
        searchTextField.layer.cornerRadius = 15
        searchTextField.textAlignment = NSTextAlignment.left
        let image:UIImage = UIImage(named: "search")!
        let imageView:UIImageView = UIImageView.init(image: image)
        searchTextField.leftView = nil
         searchTextField.font = UIFont.textFieldText
        searchTextField.attributedPlaceholder = NSAttributedString(string: placeHolderText,attributes: [NSAttributedString.Key.foregroundColor: UIColor.yourCOlur])
        searchTextField.rightView = imageView
        searchTextField.backgroundColor = UIColor.yourCOlur
        searchTextField.rightViewMode = UITextField.ViewMode.always
    }

0

Switf 5

参考Jeyamahesan的回答。

我发现viewDidLayoutSubviews比viewDidAppear更好。如果你在viewDidAppear中调用setupSearchTextField(),你会看到searchTextField上的闪烁变化。

因为viewDidLayoutSubviews在第一次调用时会被调用两次,并且以后会被多次调用。所以我添加了一个isFirst变量。

R.string.localizable.product_name() -> 这是一个很好的资源框架,你可以在这里找到更多详细信息。 https://github.com/mac-cain13/R.swift

private var isFirst = true
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    guard isFirst else {
    return
    }
    isFirst = false
    setupSearchTextField()
}

private func setupSearchTextField() {
    let searchTextField = searchBar.searchTextField
    searchTextField.backgroundColor = .white
    searchTextField.layer.borderColor = UIColor(hex: "707070").cgColor
    searchTextField.layer.borderWidth = 1
    searchTextField.placeholder = R.string.localizable.product_name()
    let imageView = UIImageView(image: R.image.searchIcon())
    searchTextField.rightView = imageView
    searchTextField.rightViewMode = UITextField.ViewMode.always
    //delegate
    searchBar.delegate = self
}

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