Friday, December 14, 2018

Displaying text and images together on UILabel in Swift 3

I'm developing a pet project called MyCalculator. I need to display the current operations the user is entering. I display the numbers and Math operators on a label. I inserted an image of  the square root of x operator in the label when the user touches the operator button.


The code snippet below show how to insert text and inline image in a UILabel.



    private var operatorImages: [Int:UIImage] = [
        103:UIImage(named: "squareRootX")!,
        116:UIImage(named: "cubeRootX")!,
        206:UIImage(named: "yRootX")!,
    ]
    private var operatorSymbolsCache : [Int:NSTextAttachment] = [:]
    
    private func getOperatorSymbol(_ tag: Int) -> NSTextAttachment {
        var result = operatorSymbolsCache[tag]
        if result == nil {
            result = NSTextAttachment()
            result?.image = operatorImages[tag]!
            result?.bounds = CGRect(x: 0.0, y: 0.0, width: Double(operatorImages[tag]!.size.width), height: Double(operatorImages[tag]!.size.height))
            operatorSymbolsCache[tag] = result
        }
        return result!
    }

    ...

    var myText = NSMutableAttributedString()
    myText.append(NSAttributedString(string: operand))
    myText.append(NSAttributedString(attachment: getOperatorSymbol(currentOperations[i].1.tag)))

    currentOperationsLabel.attributedText = myText
 
       
 

The problem is the operator image is not vertically center like in the image below.


I fixed it by updating the line:



result?.bounds = CGRect(x: 0.0, y: 0, width: Double(operatorImages[tag]!.size.width), height: Double(operatorImages[tag]!.size.height))
 
       
 

to:



result?.bounds = CGRect(x: 0.0, y: Double((displaySubSection.font.capHeight - operatorImages[tag]!.size.height) / 2), width: Double(operatorImages[tag]!.size.width), height: Double(operatorImages[tag]!.size.height))
 
       

I changed the y parameter. The graph below show what capHeight property is.


The properties capHeight, size.height, and size.width are in point. If the image dimension is 30x30 pixels, the size.height property would be 15 (points) and size.width property would be 15 (points) when the app is running on high resolution devices such as iPhone 5s and iPhone 6 because one point contains 2 pixels. To get the property's value in pixels, multiply it by the scale property of the UIImage class.



References
https://developer.apple.com/documentation/uikit/uiimage/1624105-size
https://stackoverflow.com/questions/26105803/center-nstextattachment-image-next-to-single-line-uilabel





No comments:

Post a Comment