You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调整UISearchBar中清除按钮的位置?

调整UISearchBar清除按钮位置的解决方案

问题背景

需要调整UISearchBar右侧清除按钮(带X的按钮)的位置,目前已通过value(forKey: "searchField")获取内部UITextField完成了搜索栏的样式自定义,但仅能获取清除按钮的矩形区域,无法调整其位置。当前自定义代码如下:

if let searchTextField = value(forKey: "searchField") as? UITextField {
    
    searchTextField.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        searchTextField.heightAnchor.constraint(equalToConstant: CGFloat(height)),
        searchTextField.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0),
        searchTextField.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0),
        searchTextField.centerYAnchor.constraint(equalTo: centerYAnchor, constant: 0)
    ])

    searchTextField.clipsToBounds = true
    searchTextField.font = UIFont.regularDMSans(of: 17)
    searchTextField.textColor = .textLight
    searchTextField.layer.cornerRadius = 20
    searchTextField.layer.borderWidth = 2.0
    searchTextField.layer.borderColor = UIColor.createEventDivider.cgColor
    
    if !shouldShowSearchIcon {
        setImage(UIImage(), for: .search, state: .normal)
    }

    let offset = UIOffset(horizontal: 13, vertical: 0)
    setPositionAdjustment(offset, for: .search)
}

可行解决方案

方法一:子类化UITextField重写位置计算方法

系统清除按钮的位置由clearButtonRect(forBounds:)方法决定,通过子类化UITextField并重写该方法,可直接调整按钮偏移:

  1. 创建自定义UITextField子类:
class CustomSearchTextField: UITextField {
    // 自定义水平偏移量:负数左移,正数右移
    var clearButtonHorizontalOffset: CGFloat = -10
    // 可选:自定义垂直偏移量
    var clearButtonVerticalOffset: CGFloat = 0
    
    override func clearButtonRect(forBounds bounds: CGRect) -> CGRect {
        let defaultRect = super.clearButtonRect(forBounds: bounds)
        return CGRect(
            x: defaultRect.origin.x + clearButtonHorizontalOffset,
            y: defaultRect.origin.y + clearButtonVerticalOffset,
            width: defaultRect.width,
            height: defaultRect.height
        )
    }
}
  1. 在自定义UISearchBar中替换内部TextField:
class CustomSearchBar: UISearchBar {
    var shouldShowSearchIcon: Bool = true
    var height: CGFloat = 40
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupCustomSearchField()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupCustomSearchField()
    }
    
    private func setupCustomSearchField() {
        // 替换系统默认TextField为自定义子类
        let customTextField = CustomSearchTextField()
        customTextField.clearButtonHorizontalOffset = -15 // 按需调整偏移值
        setValue(customTextField, forKey: "searchField")
        
        guard let searchTextField = value(forKey: "searchField") as? CustomSearchTextField else { return }
        
        // 原有样式配置
        searchTextField.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            searchTextField.heightAnchor.constraint(equalToConstant: height),
            searchTextField.leadingAnchor.constraint(equalTo: leadingAnchor),
            searchTextField.trailingAnchor.constraint(equalTo: trailingAnchor),
            searchTextField.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])

        searchTextField.clipsToBounds = true
        searchTextField.font = UIFont.regularDMSans(of: 17)
        searchTextField.textColor = .textLight
        searchTextField.layer.cornerRadius = 20
        searchTextField.layer.borderWidth = 2.0
        searchTextField.layer.borderColor = UIColor.createEventDivider.cgColor
        
        if !shouldShowSearchIcon {
            setImage(UIImage(), for: .search, state: .normal)
        }

        let offset = UIOffset(horizontal: 13, vertical: 0)
        setPositionAdjustment(offset, for: .search)
    }
}

方法二:替换为自定义清除按钮

若不想子类化,可直接隐藏系统清除按钮,自定义按钮并通过rightView添加,完全控制位置和样式:

if let searchTextField = value(forKey: "searchField") as? UITextField {
    // 隐藏系统默认清除按钮
    searchTextField.clearButtonMode = .never
    
    // 创建自定义清除按钮
    let clearButton = UIButton(type: .custom)
    clearButton.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal)
    clearButton.tintColor = .gray
    clearButton.frame = CGRect(x: 0, y: 0, width: 24, height: 24)
    clearButton.addTarget(self, action: #selector(clearSearchText), for: .touchUpInside)
    
    // 调整按钮位置:通过contentEdgeInsets控制偏移
    clearButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 10)
    searchTextField.rightView = clearButton
    searchTextField.rightViewMode = .whileEditing
}

// 清除文本的响应方法
@objc private func clearSearchText() {
    (value(forKey: "searchField") as? UITextField)?.text = ""
}

内容的提问来源于stack exchange,提问作者İsmail Ege Oğuz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 19:51:53