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

如何在UITextView中实现WhatsApp、Facebook式状态文本背景扩展样式

实现UITextView中文本区域动态背景(类似WhatsApp/Facebook/Instagram状态样式)

我懂你想要的效果——在UITextView里只给实际输入的文本部分加上背景色,而且输入时这个背景区域能跟着文本自动扩展,就像社交平台的状态输入框那样对吧?下面给你两种实用的实现方案,你可以根据需求选择:

方案一:利用NSAttributedString自带的背景属性(快速实现)

这是最简单直接的方式,通过给文本添加backgroundColor属性,UITextView会自动根据文本的布局渲染背景,输入文本时背景也会跟着自动适配扩展。

实现步骤

  1. 监听UITextView的文本变化事件
  2. 每次文本更新时,给全部文本添加背景色属性(保留原有文本的其他格式属性)

代码示例

class StatusTextView: UITextView {
    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        setupBaseConfig()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupBaseConfig()
    }
    
    private func setupBaseConfig() {
        delegate = self
        // 让TextView本身背景透明,只显示文本的背景色
        backgroundColor = .clear
        // 初始设置文本背景
        updateTextBackground()
    }
    
    private func updateTextBackground() {
        let mutableAttributedText = NSMutableAttributedString(attributedString: self.attributedText)
        // 这里用淡灰色作为文本背景,可根据需求替换颜色
        mutableAttributedText.addAttribute(
            .backgroundColor,
            value: UIColor.systemGray5,
            range: NSRange(location: 0, length: mutableAttributedText.length)
        )
        self.attributedText = mutableAttributedText
    }
}

extension StatusTextView: UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        updateTextBackground()
    }
}

方案二:自定义绘制背景(更灵活的样式控制)

如果需要更精细的样式调整(比如圆角、内边距、边框等),可以重写UITextView的绘制方法,手动绘制文本区域的背景。

实现步骤

  1. 获取文本的实际布局范围
  2. 根据文本占用的区域绘制自定义背景
  3. 监听文本变化,触发重绘

代码示例

class CustomStatusTextView: UITextView {
    // 可自定义的样式参数
    private let textBgColor = UIColor.systemGray5
    private let cornerRadius: CGFloat = 8.0
    private let textInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
    
    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        setupBaseConfig()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupBaseConfig()
    }
    
    private func setupBaseConfig() {
        backgroundColor = .clear
        textContainerInset = textInsets
        // 监听文本变化通知
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(textDidChange),
            name: UITextView.textDidChangeNotification,
            object: self
        )
    }
    
    @objc private func textDidChange() {
        // 文本变化时触发重绘
        setNeedsDisplay()
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        guard let layoutManager = layoutManager, let textContainer = textContainer else { return }
        
        // 获取文本实际占用的矩形范围
        let fullTextRange = NSRange(location: 0, length: textStorage.length)
        let textRect = layoutManager.boundingRect(forGlyphRange: fullTextRange, in: textContainer)
        
        // 调整背景矩形,适配内边距和圆角
        let backgroundRect = textRect.inset(by: UIEdgeInsets(
            top: -textInsets.top,
            left: -textInsets.left,
            bottom: -textInsets.bottom,
            right: -textInsets.right
        )).offsetBy(dx: textContainerInset.left, dy: textContainerInset.top)
        
        // 绘制带圆角的背景
        let bgPath = UIBezierPath(roundedRect: backgroundRect, cornerRadius: cornerRadius)
        textBgColor.setFill()
        bgPath.fill()
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

注意事项

  • 两种方案都支持多行文本自动适配,背景会随着文本换行自动扩展
  • 如果使用方案二,还可以额外添加边框、阴影等效果,进一步贴近社交平台的样式
  • 记得将UITextView自身的backgroundColor设为透明,避免和自定义背景冲突

内容的提问来源于stack exchange,提问作者iOS Trainee.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:24:44