overlaying text on image using swift

后端 未结 2 1621
小鲜肉
小鲜肉 2021-02-10 00:08

I am trying to overlay some text on an image using Swift and am looking at this code here: (src: How do I add text to an image in iOS Swift)

This places the text right i

相关标签:
2条回答
  • 2021-02-10 00:29

    Details

    xCode 9.1, Swift 4

    Solution

    extension UIView

    extension UIView {
    
        func copyObject<T: UIView> () -> T? {
            let archivedData = NSKeyedArchiver.archivedData(withRootObject: self)
            return NSKeyedUnarchiver.unarchiveObject(with: archivedData) as? T
        }
    }
    

    extension UIImage

     extension UIImage {
    
        typealias EditSubviewClosure<T: UIView> = (_ parentSize: CGSize, _ viewToAdd: T)->()
    
        func with<T: UIView>(view: T, editSubviewClosure: EditSubviewClosure<T>) -> UIImage {
    
            if let copiedView = view.copyObject() as? T {
                UIGraphicsBeginImageContext(size)
    
                let basicSize = CGRect(origin: .zero, size: size)
                draw(in: basicSize)
                editSubviewClosure(size, copiedView)
                copiedView.draw(basicSize)
    
                let newImage = UIGraphicsGetImageFromCurrentImageContext()
                UIGraphicsEndImageContext()
                return newImage!
            }
            return self
    
        }
    }
    

    extension UIImageView

     extension UIImageView {
    
        enum ImageAddingMode {
            case changeOriginalImage
            case addSubview
            case addCopiedSubview
        }
    
        func drawOnCurrentImage<T: UIView>(view: T, mode: ImageAddingMode, editSubviewClosure: @escaping UIImage.EditSubviewClosure<T>) {
    
            guard let image = image else {
                return
            }
    
            let addSubView: (T) -> () = { view in
                editSubviewClosure(self.frame.size, view)
                self.addSubview(view)
            }
    
            switch mode {
                case .changeOriginalImage:
                    self.image = image.with(view: view, editSubviewClosure: editSubviewClosure)
    
                case .addSubview:
                    addSubView(view)
    
                case .addCopiedSubview:
                    if let copiedView = view.copyObject() as? T {
                        addSubView(copiedView)
                    }
            }
        }
    }
    

    Usage

    Sample 1

    func sample1(label: UILabel) {
        imageView.contentMode = .scaleAspectFit
        imageView.image = UIImage(named: "wall")?.with(view: label) { (parentSize, viewToAdd) in
            print("parentSize: \(parentSize)")
            viewToAdd.font = UIFont.systemFont(ofSize: 40)
            viewToAdd.textColor = .yellow
            viewToAdd.bounds = CGRect(x: 40, y: 40, width: 200, height: 40)
        }
    }
    

    Sample 2

    func sample2(label: UILabel) {
        imageView.image = UIImage(named: "wall")
        imageView.contentMode = .scaleAspectFit
        imageView.drawOnCurrentImage(view: label, mode: .changeOriginalImage) { (parentSize, viewToAdd) in
            print("parentSize: \(parentSize)")
            viewToAdd.font = UIFont.systemFont(ofSize: 40)
            viewToAdd.textColor = .yellow
            viewToAdd.textAlignment = .right
            let width: CGFloat = 200
            let height: CGFloat = 30
            let indent: CGFloat = 40
            viewToAdd.bounds = CGRect(x: parentSize.width - width - indent, y: parentSize.height - height - indent, width: width, height: height)
        }
    }
    

    Sample 3

    func sample3(label: UILabel) {
        imageView.image = UIImage(named: "wall")
        imageView.contentMode = .scaleAspectFill
        imageView.drawOnCurrentImage(view: label, mode: .addSubview) { (parentSize, viewToAdd) in
            print("parentSize: \(parentSize)")
            viewToAdd.font = UIFont.systemFont(ofSize: 16)
            viewToAdd.textColor = .yellow
            viewToAdd.frame = CGRect(x: 40, y: 40, width: 200, height: 20)
        }
    }
    

    Sample 4

    func sample4(label: UILabel) {
        imageView.image = UIImage(named: "wall")
        imageView.contentMode = .scaleAspectFill
        imageView.drawOnCurrentImage(view: label, mode: .addCopiedSubview) { (parentSize, viewToAdd) in
            print("parentSize: \(parentSize)")
            viewToAdd.font = UIFont.systemFont(ofSize: 16)
            viewToAdd.textColor = .yellow
            viewToAdd.frame = CGRect(x: 40, y: 40, width: 200, height: 20)
        }
    }
    

    Full sample

    Do not forget to add the solution code here

    import UIKit
    
    class ViewController: UIViewController {
    
        let imageView = UIImageView(frame: CGRect(x: 50, y: 50, width: 300, height: 300))
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            let label = UILabel(frame: CGRect(x: 20, y: 20, width: 80, height: 30))
            label.text = "Blablabla"
            label.font = UIFont.systemFont(ofSize: 20)
            label.textColor = .black
            view.addSubview(label)
    
            sample1(label: label)
            //sample2(label: label)
            //sample3(label: label)
            //sample4(label: label)
    
            imageView.clipsToBounds = true
            view.addSubview(imageView)
        }
    
        func sample1(label: UILabel) {
            imageView.contentMode = .scaleAspectFit
            imageView.image = UIImage(named: "wall")?.with(view: label) { (parentSize, viewToAdd) in
                print("parentSize: \(parentSize)")
                viewToAdd.font = UIFont.systemFont(ofSize: 40)
                viewToAdd.textColor = .yellow
                viewToAdd.bounds = CGRect(x: 40, y: 40, width: 200, height: 20)
            }
        }
    
        func sample2(label: UILabel) {
            imageView.image = UIImage(named: "wall")
            imageView.contentMode = .scaleAspectFit
            imageView.drawOnCurrentImage(view: label, mode: .changeOriginalImage) { (parentSize, viewToAdd) in
                print("parentSize: \(parentSize)")
                viewToAdd.font = UIFont.systemFont(ofSize: 40)
                viewToAdd.textColor = .yellow
                viewToAdd.textAlignment = .right
                let width: CGFloat = 200
                let height: CGFloat = 30
                let indent: CGFloat = 40
                viewToAdd.bounds = CGRect(x: parentSize.width - width - indent, y: parentSize.height - height - indent, width: width, height: height)
            }
        }
    
        func sample3(label: UILabel) {
            imageView.image = UIImage(named: "wall")
            imageView.contentMode = .scaleAspectFill
            imageView.drawOnCurrentImage(view: label, mode: .addSubview) { (parentSize, viewToAdd) in
                print("parentSize: \(parentSize)")
                viewToAdd.font = UIFont.systemFont(ofSize: 16)
                viewToAdd.textColor = .yellow
                viewToAdd.frame = CGRect(x: 40, y: 40, width: 200, height: 20)
            }
        }
    
        func sample4(label: UILabel) {
            imageView.image = UIImage(named: "wall")
            imageView.contentMode = .scaleAspectFill
            imageView.drawOnCurrentImage(view: label, mode: .addCopiedSubview) { (parentSize, viewToAdd) in
                print("parentSize: \(parentSize)")
                viewToAdd.font = UIFont.systemFont(ofSize: 16)
                viewToAdd.textColor = .yellow
                viewToAdd.frame = CGRect(x: 40, y: 40, width: 200, height: 20)
            }
        }
    }
    
    0 讨论(0)
  • 2021-02-10 00:34

    Great answer Vasily!

    but in my situation I needed to add these fixes.

    TEXT IS VERY SMALL

    I ran a situation where the text was super small, maybe because the UIImage size was too small for the selected font of 14, so I fixed this by giving a huge font of 120.

    TEXT IS NOT DISPLAYED AT THE GIVEN CGPOINT

    In the same context of a big UIImage size, the position given to the extension was misplacing the text, the fix: added these 2 lets with the ratio of height and width computed and then multiplied for x,y points.

    let widthRatio = size.width/UIScreen.main.bounds.width
    let heightRatio = size.height/UIScreen.main.bounds.height
    

    Hope that helps anybody!

    0 讨论(0)
提交回复
热议问题