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

Swift5中如何搭配MDCOutlinedTextField使用Material Chips组件

实现MDCOutlinedTextField内嵌Material Chips的Swift方案

核心思路为自定义继承自MDCOutlinedTextField的控件,将MDCChipView组件放入输入框内部容器中,同时调整输入文本的缩进距离避免和Chips重叠,具体实现步骤如下:


步骤1:集成依赖

首先确认你已集成Material Components iOS库,使用CocoaPods的话在Podfile中添加以下配置:

pod 'MaterialComponents/TextFields'
pod 'MaterialComponents/Chips'

执行pod install完成集成后,在需要使用的文件中导入对应模块:

import MaterialComponents.MDCOutlinedTextField
import MaterialComponents.MDCChipView

步骤2:自定义带Chips的文本框控件

class ChipsOutlinedTextField: MDCOutlinedTextField {
    // 承载多个Chip的堆栈容器
    private let chipsStackView: UIStackView = {
        let stack = UIStackView()
        stack.axis = .horizontal
        stack.spacing = 8
        stack.alignment = .center
        stack.translatesAutoresizingMaskIntoConstraints = false
        return stack
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupContainer()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupContainer()
    }
    
    private func setupContainer() {
        addSubview(chipsStackView)
        // 配置Chip容器约束:居左对齐、上下居中、固定高度适配Chip尺寸
        NSLayoutConstraint.activate([
            chipsStackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12),
            chipsStackView.centerYAnchor.constraint(equalTo: centerYAnchor),
            chipsStackView.heightAnchor.constraint(equalToConstant: 32)
        ])
    }
    
    // 重写方法调整非编辑状态下文本的起始位置,给Chip留出显示空间
    override func textRect(forBounds bounds: CGRect) -> CGRect {
        var originRect = super.textRect(forBounds: bounds)
        originRect.origin.x += chipsStackView.frame.width + 8
        return originRect
    }
    
    // 重写方法调整编辑状态下文本的起始位置
    override func editingRect(forBounds bounds: CGRect) -> CGRect {
        var originRect = super.editingRect(forBounds: bounds)
        originRect.origin.x += chipsStackView.frame.width + 8
        return originRect
    }
    
    // 对外暴露添加Chip的方法
    func addChip(title: String) {
        let chip = MDCChipView()
        chip.titleLabel.text = title
        chip.setBackgroundColor(.systemGray5, for: .normal)
        chip.setTitleColor(.label, for: .normal)
        chip.sizeToFit()
        // 绑定点击Chip删除的事件
        chip.addTarget(self, action: #selector(removeChip(_:)), for: .touchUpInside)
        chipsStackView.addArrangedSubview(chip)
        // 刷新布局更新文本缩进
        setNeedsLayout()
        layoutIfNeeded()
    }
    
    @objc private func removeChip(_ sender: MDCChipView) {
        sender.removeFromSuperview()
        setNeedsLayout()
    }
}

步骤3:调用示例

// 初始化自定义文本框
let contactTextField = ChipsOutlinedTextField(frame: CGRect(x: 20, y: 100, width: view.frame.width - 40, height: 56))
contactTextField.label.text = "收件人"
contactTextField.placeholder = "输入姓名或邮箱"
// 添加测试Chip
contactTextField.addChip(title: "张三")
contactTextField.addChip(title: "李四")
view.addSubview(contactTextField)

可选优化点

  • 若Chips数量过多需要换行,可将stackView替换为支持流式布局的UICollectionView,实现多行排列效果
  • 可根据设计需求自定义Chip的样式,包括背景色、圆角、删除图标、选中高亮效果等
  • 若需要输入完成后自动生成Chip,可在UITextFieldDelegate的textFieldShouldReturn(_:)方法中读取当前输入文本,调用addChip方法后清空输入内容即可

内容的提问来源于stack exchange,提问作者Poom Wutthidech

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 10:54:04