Swift:在视图中水平和垂直居中放置NSAttributedString

时间:2019-01-30 10:26:39

标签: swift constraints

你好,

我有一个CardButton类:UIButton。在此CardButton的draw方法中,我想在其内部添加NSAttributed String并将其居中(垂直和水平),该字符串基本上只是一个表情符号。结果看起来像这样:

enter image description here

但是,NSAttributedString只能在容器内水平尺寸的中心对齐。

我的解决方案:

  1. 在CardButton内创建一个containerView
  2. 中心容器在其容器(即CardButton)中垂直和水平查看
  3. 在containerView内添加NSAttributedString并调整containerView的大小以适合字符串的字体。

所以结果看起来像这样:

enter image description here

我为发生这种情况所做的尝试如下:

class CardButton: UIButton {

override func draw(){
//succesfully drawing the CardButton

let stringToDraw = attributedString(symbol, fontSize: symbolFontSize) //custom method to create attributed string

let containerView = UIView()
containerView.backgroundColor = //green
addSubview(containerView)

containerView.translatesAutoresizingMaskIntoConstraints = false
let centerXConstraint = containerView.centerXAnchor.constraint(equalTo: (self.centerXAnchor)).isActive = true
let centerYConstraint = containerView.centerYAnchor.constraint(equalTo: (self.centerYAnchor)).isActive = true

stringToDraw.draw(in: containerView.bounds)
containerView.sizeToFit()

}
}
长话短说,我非常失败。我首先尝试将containerView添加到cardButton,使背景变为绿色,将其宽度和高度固定,以确保将其正确地添加为子视图。它做了。但是,一旦我尝试对其进行主动约束,它就会完全消失。

有什么想法要解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

实现任何特定的UI设计目标总是有不止一种方法,但是以下过程相对简单,并且已进行了调整,以适应问题中提出和理解的要求。

UIButton.setImage方法允许将图像分配给UIButton,而无需显式创建容器。

UIGraphicsImageRenderer方法允许通过各种组件(包括NSAttributedText和大量自定义形状)制作图像。

利用这两个工具为您的项目提供基础的过程将是:

  1. 渲染具有适当成分和尺寸的图像
  2. 将渲染的图像分配给按钮

可以为此功能创建一个类,但此处未对此进行探讨。

此外,您的问题提到在应用约束时内容会消失。当图像尺寸对于容器来说太大时,可以看到这种效果,约束条件是将内容物置于看不见的位置,并且可能还有其他条件。

Rounded rectangles and Emoji with NSAttributedString

以下代码产生以上图像:

func drawRectangleWithEmoji() -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: 512, height: 512))

    let img = renderer.image { (ctx) in
        // Create the outer square:
        var rectangle = CGRect(x: 0, y: 0, width: 512, height: 512).insetBy(dx: 7.5, dy: 7.5)
        var roundedRect = UIBezierPath(roundedRect: rectangle, cornerRadius: 50).cgPath
        // MARK: .cgPath creates a CG representation of the path

        ctx.cgContext.setFillColor(UIColor.white.cgColor)
        ctx.cgContext.setStrokeColor(UIColor.blue.cgColor)
        ctx.cgContext.setLineWidth(15)

        ctx.cgContext.addPath(roundedRect)
        ctx.cgContext.drawPath(using: .fillStroke)

        // Create the inner square:
        rectangle = CGRect(x: 0, y: 0, width: 512, height: 512).insetBy(dx: 180, dy: 180)
        roundedRect = UIBezierPath(roundedRect: rectangle, cornerRadius: 10).cgPath

        ctx.cgContext.setFillColor(UIColor.green.cgColor)
        ctx.cgContext.setStrokeColor(UIColor.green.cgColor)
        ctx.cgContext.setLineWidth(15)

        ctx.cgContext.addPath(roundedRect)
        ctx.cgContext.drawPath(using: .fillStroke)

        // Add emoji:
        var fontSize: CGFloat = 144
        var attrs: [NSAttributedString.Key: Any] = [
            .font: UIFont.systemFont(ofSize: fontSize)//,
            //.backgroundColor: UIColor.gray  //uncomment to see emoji background bounds
        ]

        var string = "❤️"
        var attributedString = NSAttributedString(string: string, attributes: attrs)
        let strWidth = attributedString.size().width
        let strHeight = attributedString.size().height
        attributedString.draw(at: CGPoint(x: 256 - strWidth / 2, y: 256 - strHeight / 2))

        // Add NSAttributedString:
        fontSize = 56
        attrs = [
            .font: UIFont.systemFont(ofSize: fontSize),
            .foregroundColor: UIColor.brown
        ]

        string = "NSAttributedString"
        attributedString = NSAttributedString(string: string, attributes: attrs)
        let textWidth = attributedString.size().width
        let textHeight = attributedString.size().height
        attributedString.draw(at: CGPoint(x: 256 - textWidth / 2, y: 384 - textHeight / 2))

    }

    return img
}

激活NSLayoutContraints,然后可以为按钮设置新图像:

    override func viewDidLoad() {
       super.viewDidLoad()
       view = UIView()
       view.backgroundColor = .white

       let buttonsView = UIView()
       buttonsView.translatesAutoresizingMaskIntoConstraints = false
       // buttonsView.backgroundColor = UIColor.gray
       view.addSubview(buttonsView)

       NSLayoutConstraint.activate([
           buttonsView.widthAnchor.constraint(equalToConstant: CGFloat(buttonWidth)),
           buttonsView.heightAnchor.constraint(equalToConstant: CGFloat(buttonWidth)),
           buttonsView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
           buttonsView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
           ])

       let cardButton = UIButton(type: .custom)
       cardButton.contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
       cardButton.setImage(drawRectangleWithEmoji(), for: .normal)

       let frame = CGRect(x: 0, y: 0, width: buttonWidth, height: buttonWidth)
       cardButton.frame = frame

       buttonsView.addSubview(cardButton)

   }

您的评论以及对所提供代码的建设性审查将不胜感激。

相关问题