swift 如何在右侧设置 UiSearchBar 搜索图标

How to set UiSearchBar Search icon on the right side in swift

我正在研究 Swift。

作为常规 SearchBar 默认情况下,它的外观如下图 (1) 所示。

但根据我们的设计要求,我需要将其更改为如下图(2)。

我尝试使用下面的代码,我得到了如下图 (3)

**当我尝试以下代码时,右视图被隐藏,我无法看到文本字段右视图

搜索图标完全不可见**

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 上也提供

在ViewController中,搜索栏文本框的左视图是实际的搜索图标,因此将其设置为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
    }

我建议你查看 Apple 文档 layoutIfNeeded() layoutSubviews() 。阅读它们后,您将有更好的理解。当您编写 searchBar.layoutIfNeeded() 实例方法时,奇迹就会发生。另一个解决方案是 searchBar.layoutSubviews() 但 Apple 文档说:

You should not call this method directly. If you want to force a layout update, call the setNeedsLayout() method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded() method.

根据@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()

    }
}

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
}

试试这个,然后调用 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
    }

这是 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
                
            }
    
 }