iOS swift 在 uilabel 上显示带文字的图像

问题描述 投票:0回答:2

在我的应用程序中,我需要像这样在 UILabel 中显示文本内容和图像

但我只能显示文本和图像,例如 UILabel 中的这个文本字符串是从图像底部开始的。但我需要从顶部开始文本。

我正在使用以下代码,请帮助我以正确的格式显示带有文本的图像。

let topDesc = responseDict?["description_top"]?.string ?? ""
                    
                    // Create Attachment
                    let imageAttachment = NSTextAttachment()
                    imageAttachment.image = UIImage(named:"no-image")
                    // Set bound to reposition
                    let imageOffsetY: CGFloat = 0
                    imageAttachment.bounds = CGRect(x: 0, y: imageOffsetY, width: 130, height: 92)
                    // Create string with attachment
                    let attachmentString = NSAttributedString(attachment: imageAttachment)
                    // Initialize mutable string
                    let completeText = NSMutableAttributedString(string: "")
                    // Add image to mutable string
                    completeText.append(attachmentString)
                    // Add your text to mutable string
                    let textAfterIcon = NSAttributedString(string: topDesc)
                    completeText.append(textAfterIcon)
                    self.topContentLbl.textAlignment = .center
                    self.topContentLbl.attributedText = completeText
ios swift uiimageview uilabel overlay
2个回答
1
投票

您可以使用

UITextView
.exclusionPaths
来做到这一点。

在这里,黄色背景的文本视图是 353 点宽,我定义了一个 116x80 的矩形

UIBezierPath

textView.textContainer.exclusionPaths = [UIBezierPath(rect: CGRect(x: 0.0, y: 0.0, width: 116.0, height: 80.0))]

通过在文本视图上设置

.isScrollEnabled = false
,它会根据文本调整自己的高度。

现在,我们需要做的就是在它上面添加圆角矩形视图和图像视图。

要获得 exact 布局 - 使用单个文本字符串 - 会有点困难。

如上图所示,文本围绕排除路径流动,但您发布的图片看起来更像这样:

为此,我在字符串中添加了两个换行符:

advice and guidance to you.\n\nOur Personal stylist will work

但是,除非您编写副本以匹配可用空间,否则它可能看起来像这样:

或者这个:

如果您需要图像中显示的段落分隔符,您最好的选择可能是嵌入一个特殊字符(或者,例如,双换行符)并在运行时拆分字符串以填充两个标签根据需要布置。

这是一个简单的例子,展示了如何使用

.exclusionPaths

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .systemBackground
        
        let textView = UITextView()
        
        textView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(textView)
        
        let g = view.safeAreaLayoutGuide
        
        NSLayoutConstraint.activate([
            
            textView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            textView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            textView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            
        ])
        
        textView.isUserInteractionEnabled = false
        textView.isScrollEnabled = false
        
        let font: UIFont = .systemFont(ofSize: 13.0, weight: .regular)
        
        let paragraphStyle = NSMutableParagraphStyle()
        // let's add a little extra line height
        paragraphStyle.lineSpacing = 2.0
        
        let attributes: [NSAttributedString.Key: Any] = [
            .font: font,
            .foregroundColor: UIColor.blue,
            .paragraphStyle: paragraphStyle
        ]
        
        let str: String = "Online styling consultation service is a service where a professional stylist provides fashion advice and guidance to you over video calls, email, or Whatsapp. Our Personal stylist will work with you to understand your personal style, body shape, and wardrobe goals, and will provide recommendations for clothing, accessories, and outfits that will suit your needs."

        let attStr = NSAttributedString(string: str, attributes: attributes)
        
        textView.attributedText = attStr
        
        textView.textContainer.exclusionPaths = [UIBezierPath(rect: CGRect(x: 0.0, y: 0.0, width: 116.0, height: 80.0))]
        
        // so we can see the frames
        textView.backgroundColor = .yellow
        
    }
    
}

1
投票

这是另一种方法,声明您的对象并设置约束:

class YourViewController: UIViewController {

let yourImageView: UIImageView = {
    let iv = UIImageView()
    iv.image = UIImage(named: "9")
    iv.contentMode = .scaleAspectFill
    iv.layer.cornerRadius = 10
    iv.translatesAutoresizingMaskIntoConstraints = false
    iv.clipsToBounds = true
    
    return iv
}()

let bottomTextView: UITextView = {
    let tv = UITextView()
    tv.backgroundColor = .white
    tv.textColor = .black
    tv.font = .systemFont(ofSize: 16, weight: .regular)
    tv.translatesAutoresizingMaskIntoConstraints = false
    
    return tv
}()

let rightmLabel: UILabel = {
    let label = UILabel()
    label.textColor = .black
    label.font = .systemFont(ofSize: 15, weight: .regular)
    label.numberOfLines = 0
    label.translatesAutoresizingMaskIntoConstraints = false
    
    return label
}()

let titleLabel: UILabel = {
    let label = UILabel()
    label.text = "Online Styling Consultation"
    label.textColor = .black
    label.font = .systemFont(ofSize: 16, weight: .bold)
    label.numberOfLines = 0
    label.translatesAutoresizingMaskIntoConstraints = false

    return label
}()

let bgView: UIView = {
    let v = UIView()
    v.backgroundColor = #colorLiteral(red: 0.9690894485, green: 0.8088869452, blue: 0.9875240922, alpha: 1)
    v.layer.cornerRadius = 10
    v.clipsToBounds = true
    v.translatesAutoresizingMaskIntoConstraints = false
    
    return v
}()

let myString = "Monthly price reflects net monthly payment, after application of AT&T trade‑in credit applied over 36 months with purchase of an iPhone 14 Pro, iPhone 14 Pro Max, iPhone 14, or iPhone 14 Plus and trade‑in of eligible smartphone. Receive credit with purchase of an iPhone 14 Pro or iPhone 14 Pro Max of either $1000, $700, or $350 (based upon the model and condition of your trade‑in smartphone). Receive credit with purchase of an iPhone 14 or iPhone 14 Plus of either $700 or $350 (based upon the model and condition of your trade‑in smartphone). "

override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .white
    
    // split string in two different string
    let words = myString.components(separatedBy: " ")
    let halfLength = words.count / 6 // split string
    let firstHalf = words[0..<halfLength].joined(separator: " ")
    let secondHalf = words[halfLength..<words.count].joined(separator: " ")

    print(firstHalf)
    print(secondHalf)
    
    rightmLabel.text = firstHalf
    bottomTextView.text = secondHalf
    
    view.addSubview(bgView)
    bgView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
    bgView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true
    bgView.heightAnchor.constraint(equalToConstant: 90).isActive = true
    bgView.widthAnchor.constraint(equalToConstant: 90).isActive = true
    
    view.addSubview(yourImageView)
    yourImageView.topAnchor.constraint(equalTo: bgView.topAnchor, constant: 20).isActive = true
    yourImageView.leadingAnchor.constraint(equalTo: bgView.leadingAnchor, constant: 20).isActive = true
    yourImageView.heightAnchor.constraint(equalToConstant: 100).isActive = true
    yourImageView.widthAnchor.constraint(equalToConstant: 100).isActive = true
    
    view.addSubview(bottomTextView)
    bottomTextView.topAnchor.constraint(equalTo: yourImageView.bottomAnchor, constant: 10).isActive = true
    bottomTextView.leadingAnchor.constraint(equalTo: yourImageView.leadingAnchor).isActive = true
    bottomTextView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -10).isActive = true
    bottomTextView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
    
    // create your right label in a stackView
    let stackView = UIStackView(arrangedSubviews: [titleLabel, rightmLabel])
    stackView.distribution = .fillProportionally
    stackView.axis = .vertical
    stackView.spacing = 2
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    view.addSubview(stackView)
    stackView.topAnchor.constraint(equalTo: yourImageView.topAnchor, constant: 0).isActive = true
    stackView.leadingAnchor.constraint(equalTo: yourImageView.trailingAnchor, constant: 20).isActive = true
    stackView.trailingAnchor.constraint(equalTo: bottomTextView.trailingAnchor).isActive = true
    stackView.bottomAnchor.constraint(equalTo: yourImageView.bottomAnchor).isActive = true     
  }
}

这是结果:

© www.soinside.com 2019 - 2024. All rights reserved.