Created
June 25, 2018 18:08
-
-
Save deepakraj27/02b13b6cca08f5da25bc8a7bf1f0c722 to your computer and use it in GitHub Desktop.
An easy, helpful UIImageView category that generates letter initials as a placeholder for user images, with a custom background color and double border with custom stroke width Completely supports SWIFT 4 and SWIFT 3, written excusively for you.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// UIImageView+Letters.swift | |
// UIImageViewLettersDemo | |
// | |
// Created by Deepakraj Murugesan on 23/02/18. | |
// Copyright © 2018 Deepak. All rights reserved. | |
// | |
import Foundation | |
import UIKit | |
extension UIImageView { | |
/// Sets the image property of the view based on initial text, a specified background color, custom text attributes, and a circular clipping | |
/// | |
/// - Parameters: | |
/// - string: The string used to generate the initials. This should be a user's full name if available. | |
/// - color: This optional paramter sets the background of the image. By default, a random color will be generated. | |
/// - circular: This boolean will determine if the image view will be clipped to a circular shape. | |
/// - textAttributes: This dictionary allows you to specify font, text color, shadow properties, etc. | |
open func setImage(string: String?, | |
color: UIColor? = nil, | |
circular: Bool = false, | |
stroke: Bool = false, | |
textAttributes: [NSAttributedStringKey: Any]? = nil) { | |
let image = imageSnap(text: string != nil ? string?.initials : "", | |
color: color ?? .random, | |
circular: circular, | |
stroke: stroke, | |
textAttributes:textAttributes) | |
if let newImage = image { | |
self.image = newImage | |
} | |
} | |
private func imageSnap(text: String?, | |
color: UIColor, | |
circular: Bool, | |
stroke: Bool, | |
textAttributes: [NSAttributedStringKey: Any]?) -> UIImage? { | |
let scale = Float(UIScreen.main.scale) | |
var size = bounds.size | |
if contentMode == .scaleToFill || contentMode == .scaleAspectFill || contentMode == .scaleAspectFit || contentMode == .redraw { | |
size.width = CGFloat(floorf((Float(size.width) * scale) / scale)) | |
size.height = CGFloat(floorf((Float(size.height) * scale) / scale)) | |
} | |
UIGraphicsBeginImageContextWithOptions(size, false, CGFloat(scale)) | |
let context = UIGraphicsGetCurrentContext() | |
if circular { | |
let path = CGPath(ellipseIn: bounds, transform: nil) | |
context?.addPath(path) | |
context?.clip() | |
} | |
// Fill | |
context?.setFillColor(color.cgColor) | |
context?.fill(CGRect(x: 0, y: 0, width: size.width, height: size.height)) | |
let attributes = textAttributes ?? [NSAttributedStringKey.foregroundColor: UIColor.white, | |
NSAttributedStringKey.font: UIFont.systemFont(ofSize: 55.0)] | |
//stroke color | |
if stroke { | |
//outer circle | |
context?.setStrokeColor((attributes[NSAttributedStringKey.foregroundColor] as! UIColor).cgColor) | |
context?.setLineWidth(4) | |
var rectangle : CGRect = CGRect(x: 0, y: 0, width: size.width, height: size.height) | |
context?.addEllipse(in: rectangle) | |
context?.drawPath(using: .fillStroke) | |
//inner circle | |
context?.setLineWidth(1) | |
rectangle = CGRect(x: 4, y: 4, width: size.width - 8, height: size.height - 8) | |
context?.addEllipse(in: rectangle) | |
context?.drawPath(using: .fillStroke) | |
} | |
// Text | |
if let text = text { | |
let textSize = text.size(withAttributes: attributes) | |
let bounds = self.bounds | |
let rect = CGRect(x: bounds.size.width/2 - textSize.width/2, y: bounds.size.height/2 - textSize.height/2, width: textSize.width, height: textSize.height) | |
text.draw(in: rect, withAttributes: attributes) | |
} | |
let image = UIGraphicsGetImageFromCurrentImageContext() | |
UIGraphicsEndImageContext() | |
return image | |
} | |
} | |
// MARK: UIColor Helper | |
extension UIColor { | |
/// Returns random generated color. | |
open static var random: UIColor { | |
srandom(arc4random()) | |
var red: Double = 0 | |
while (red < 0.1 || red > 0.84) { | |
red = drand48() | |
} | |
var green: Double = 0 | |
while (green < 0.1 || green > 0.84) { | |
green = drand48() | |
} | |
var blue: Double = 0 | |
while (blue < 0.1 || blue > 0.84) { | |
blue = drand48() | |
} | |
return .init(red: CGFloat(red), green: CGFloat(green), blue: CGFloat(blue), alpha: 1.0) | |
} | |
open static func colorHash(name: String?) -> UIColor { | |
guard let name = name else { | |
return .red | |
} | |
var nameValue = 0 | |
for character in name { | |
let characterString = String(character) | |
let scalars = characterString.unicodeScalars | |
nameValue += Int(scalars[scalars.startIndex].value) | |
} | |
var r = Float((nameValue * 123) % 51) / 51 | |
var g = Float((nameValue * 321) % 73) / 73 | |
var b = Float((nameValue * 213) % 91) / 91 | |
let defaultValue: Float = 0.84 | |
r = min(max(r, 0.1), defaultValue) | |
g = min(max(g, 0.1), defaultValue) | |
b = min(max(b, 0.1), defaultValue) | |
return .init(red: CGFloat(r), green: CGFloat(g), blue: CGFloat(b), alpha: 1.0) | |
} | |
} | |
// MARK: String Helper | |
// Example = Ex | |
// For Example = FE | |
// for example = fe | |
// "" = DP | |
extension String { | |
public var initials: String { | |
let words = components(separatedBy: .whitespacesAndNewlines) | |
//to identify letters | |
let letters = CharacterSet.letters | |
var firstChar : String = "" | |
var secondChar : String = "" | |
var firstCharFoundIndex : Int = -1 | |
var firstCharFound : Bool = false | |
var secondCharFound : Bool = false | |
for (index, item) in words.enumerated() { | |
if item.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { | |
continue | |
} | |
//browse through the rest of the word | |
for (_, char) in item.unicodeScalars.enumerated() { | |
//check if its a aplha | |
if letters.contains(char) { | |
if !firstCharFound { | |
firstChar = String(char) | |
firstCharFound = true | |
firstCharFoundIndex = index | |
} else if !secondCharFound { | |
secondChar = String(char) | |
if firstCharFoundIndex != index { | |
secondCharFound = true | |
} | |
break | |
} else { | |
break | |
} | |
} | |
} | |
} | |
if firstChar.isEmpty && secondChar.isEmpty { | |
firstChar = "D" | |
secondChar = "P" | |
} | |
return firstChar + secondChar | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
how i can add bottom shadow to image?