Remove a sublayer from TextField - ios

I need two functions, One to add a bottom boarder and one to remove a bottom boarder. How can I remove this boarder I have created?
extension UITextField {
func addBottomBorder(){
let bottomLine = CALayer()
bottomLine.frame = CGRect.init(x: 0, y: self.frame.size.height - 1, width: self.frame.size.width, height: 1)
bottomLine.backgroundColor = UIColor.white.cgColor
self.borderStyle = UITextBorderStyle.none
self.layer.addSublayer(bottomLine)
}
func removeBottomBorder(){
}
}

You can try to remove the layer with .removeFromSuperlayer() so hold a reference to it
extension UITextField {
func addBottomBorder(){
let bottomLine = CALayer()
bottomLine.frame = CGRect.init(x: 0, y: self.frame.size.height - 1, width: self.frame.size.width, height: 1)
bottomLine.backgroundColor = UIColor.red.cgColor
self.layer.addSublayer(bottomLine)
}
func removeBottomBorder() {
self.layer.sublayers?.first?.removeFromSuperlayer()
}
}
for safety that you may add other sublayers
extension UITextField {
func addBottomBorder(){
let bottomLine = UIView()
bottomLine.tag = 23
bottomLine.frame = CGRect.init(x: 0, y: self.frame.size.height - 1, width: self.frame.size.width, height: 1)
bottomLine.backgroundColor = UIColor.red
self.addSubview(bottomLine)
}
func removeBottomBorder() {
self.subviews.forEach {
if $0.tag == 23 {
$0.removeFromSuperview()
}
}
}
}

Related

Placeholder Text Not Appearing In Single Line Text Field

I am trying to create an underlined text field with placeholder text, I got the following extension to help out.
extension UITextField {
func setBottomLine(borderColor: UIColor) {
borderStyle = .none
backgroundColor = .clear
let borderLine = CALayer()
borderLine.frame = CGRect(x: 0, y: frame.height - 2, width: frame.width, height: 2)
layer.addSublayer(borderLine)
}
I call this extension in layout subviews of my view controller, and whenever I assign placeholder text nothing shows up. I am very confused on what the problem is. Thanks!
extension UITextField {
func setUnderLine() {
let border = CALayer()
let width = CGFloat(0.5)
border.borderColor = UIColor.darkGray.cgColor
border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width - 10, height: self.frame.size.height)
border.borderWidth = width
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
mytextField.setUnderLine()
}
Check this out.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var yourTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
yourTextField.textFieldUnderscoreAndPlaceholder()
}
}
extension UITextField {
//MARK: Text underscore with placeholder
func textFieldUnderscoreAndPlaceholder() {
//Underscore
let textFieldUnderscore = CALayer()
textFieldUnderscore.frame = CGRect(x: 0.0, y: frame.height - 1, width: frame.width, height: 1.0)
bounds = bounds.insetBy(dx: 0, dy: -2)
textFieldUnderscore.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 1).cgColor
layer.addSublayer(textFieldUnderscore)
//Placeholder
placeholder = "Type some text here..."
}
}

Multiple shadows under UIView iOS Swift

I am trying to make a UIButton with rounded corners that has 2 colored shadows. Why is the red (and at this point also the blue "shadow" layer covering the button? How to get the shadows below the button canvas). I thought it was helping to insert sublayers instead of just adding them.
I have made a playground illustrating the issue
import UIKit
import PlaygroundSupport
This is the button I'm trying to implement
class PrimaryButton: UIButton {
required init(text: String = "Test 1", hasShadow: Bool = true) {
super.init(frame: .zero)
setTitle(text, for: .normal)
backgroundColor = UIColor.blue
layer.cornerRadius = 48 / 2
layer.masksToBounds = false
if hasShadow {
insertShadow()
}
}
fileprivate func insertShadow() {
let layer2 = CALayer(layer: layer), layer3 = CALayer(layer: layer)
layer2.applySketchShadow(color: UIColor.red, alpha: 0.5, x: 0, y: 15, blur: 35, spread: -10)
layer3.applySketchShadow(color: UIColor.blue, alpha: 0.5, x: 0, y: 10, blur: 21, spread: -9)
layer.insertSublayer(layer2, at: 0)
layer.insertSublayer(layer3, at: 0)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
layer.sublayers?.forEach { (sublayer) in
sublayer.shadowPath = UIBezierPath(rect: bounds).cgPath
}
}
}
This is an extension that helps adding the shadow from Sketch specification:
extension CALayer {
func applySketchShadow(
color: UIColor = .black,
alpha: Float = 0.5,
x: CGFloat = 0,
y: CGFloat = 2,
blur: CGFloat = 4,
spread: CGFloat = 0)
{
shadowColor = color.cgColor
shadowOpacity = alpha
shadowOffset = CGSize(width: x, height: y)
shadowRadius = blur / 2.0
if spread == 0 {
shadowPath = nil
} else {
let dx = -spread
let rect = bounds.insetBy(dx: dx, dy: dx)
shadowPath = UIBezierPath(rect: rect).cgPath
}
masksToBounds = false
}
}
class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white
let button = PrimaryButton()
button.frame = CGRect(x: 150, y: 200, width: 200, height: 48)
view.addSubview(button)
self.view = view
}
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
It seems legit to me. layer1 & layer2 are sublayers of the button layer.
You could add a third layer that will serve as a background. Here is an example based on your code:
class PrimaryButton: UIButton {
let layer1 = CALayer(), layer2 = CALayer(), layer3 = CALayer()
override func layoutSubviews() {
super.layoutSubviews()
layer1.backgroundColor = UIColor.blue.cgColor
layer1.cornerRadius = 48 / 2
[layer1, layer2, layer3].forEach {
$0.masksToBounds = false
$0.frame = layer.bounds
layer.insertSublayer($0, at: 0)
}
layer2.applySketchShadow(color: UIColor.red, alpha: 0.5, x: 0, y: 15, blur: 35, spread: -10)
layer3.applySketchShadow(color: UIColor.blue, alpha: 0.5, x: 0, y: 10, blur: 21, spread: -9)
}
}
Note that I put most of the code inside layoutSubviews because most of your methods use the actual bounds of the button.
Change your insertions to:
layer.insertSublayer(layer2, at: 1)
layer.insertSublayer(layer3, at: 2)
That should do it.
Another way is to add double buttons without change your class.
let button = PrimaryButton()
button.frame = CGRect(x: 150, y: 200, width: 200, height: 48)
button.backgroundColor = UIColor.clear
view.addSubview(button)
self.view = view
let button1 = PrimaryButton()
button1.frame = CGRect(x: 0, y: 0, width: 200, height: 48)
button.addSubview(button1)
button1.layer.sublayers?.forEach{$0.removeFromSuperlayer()}

iOS UITextField Underline Style in swift

I've added this image, I hope you can see it, of a user interface login. Notice the text field is transparent with the exception of the line at the bottom. What code do I put in to get that affect? Can I put the necessary information in the "user defined runtime attributes"?
Create a subclass of UITextField as below, And simply set this class in your storyboard to UITextField
Swift 5 Support With #IBInspectable
import UIKit
class HSUnderLineTextField: UITextField , UITextFieldDelegate {
let border = CALayer()
#IBInspectable open var lineColor : UIColor = UIColor.black {
didSet{
border.borderColor = lineColor.cgColor
}
}
#IBInspectable open var selectedLineColor : UIColor = UIColor.black {
didSet{
}
}
#IBInspectable open var lineHeight : CGFloat = CGFloat(1.0) {
didSet{
border.frame = CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.size.width, height: self.frame.size.height)
}
}
required init?(coder aDecoder: (NSCoder?)) {
super.init(coder: aDecoder!)
self.delegate=self;
border.borderColor = lineColor.cgColor
self.attributedPlaceholder = NSAttributedString(string: self.placeholder ?? "",
attributes: [NSAttributedString.Key.foregroundColor: UIColor.white])
border.frame = CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.size.width, height: self.frame.size.height)
border.borderWidth = lineHeight
self.layer.addSublayer(border)
self.layer.masksToBounds = true
}
override func draw(_ rect: CGRect) {
border.frame = CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.size.width, height: self.frame.size.height)
}
override func awakeFromNib() {
super.awakeFromNib()
border.frame = CGRect(x: 0, y: self.frame.size.height - lineHeight, width: self.frame.size.width, height: self.frame.size.height)
self.delegate = self
}
func textFieldDidBeginEditing(_ textField: UITextField) {
border.borderColor = selectedLineColor.cgColor
}
func textFieldDidEndEditing(_ textField: UITextField) {
border.borderColor = lineColor.cgColor
}
}
Set lineColor and selectedLineColor from the storyboard and run your project.

Adding Padding to UITextField [duplicate]

I want to leave a bit of space at the beginning of a UITextField, just like here:
Add lefthand margin to UITextField
But I don't know how to do that with Swift.
This is what I am using right now:
Swift 4.2, 5
class TextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
override open func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override open func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
override open func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: padding)
}
}
Swift 4
class TextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
override open func textRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override open func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override open func editingRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
}
Swift 3:
class TextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
override func textRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
}
I never set a other padding but you can tweak. This class doesn't take care of the rightView and leftView on the textfield. If you want that to be handle correctly you can use something like (example in objc and I only needed the rightView:
- (CGRect)textRectForBounds:(CGRect)bounds {
CGRect paddedRect = UIEdgeInsetsInsetRect(bounds, self.insets);
if (self.rightViewMode == UITextFieldViewModeAlways || self.rightViewMode == UITextFieldViewModeUnlessEditing) {
return [self adjustRectWithWidthRightView:paddedRect];
}
return paddedRect;
}
- (CGRect)placeholderRectForBounds:(CGRect)bounds {
CGRect paddedRect = UIEdgeInsetsInsetRect(bounds, self.insets);
if (self.rightViewMode == UITextFieldViewModeAlways || self.rightViewMode == UITextFieldViewModeUnlessEditing) {
return [self adjustRectWithWidthRightView:paddedRect];
}
return paddedRect;
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
CGRect paddedRect = UIEdgeInsetsInsetRect(bounds, self.insets);
if (self.rightViewMode == UITextFieldViewModeAlways || self.rightViewMode == UITextFieldViewModeWhileEditing) {
return [self adjustRectWithWidthRightView:paddedRect];
}
return paddedRect;
}
- (CGRect)adjustRectWithWidthRightView:(CGRect)bounds {
CGRect paddedRect = bounds;
paddedRect.size.width -= CGRectGetWidth(self.rightView.frame);
return paddedRect;
}
This is a great case for an extension. By using an extension, there is no need to subclass UITextField and the new functionality will be made available to any UITextField in your app:
extension UITextField {
func setLeftPaddingPoints(_ amount:CGFloat){
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height))
self.leftView = paddingView
self.leftViewMode = .always
}
func setRightPaddingPoints(_ amount:CGFloat) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height))
self.rightView = paddingView
self.rightViewMode = .always
}
}
When I need to set the padding of a text field anywhere in my application, I simply do the following:
textField.setLeftPaddingPoints(10)
textField.setRightPaddingPoints(10)
Using Swift extensions, the functionality is added to the UITextField directly without subclassing.
X, Y , Z are your desired values
textField.layer.sublayerTransform = CATransform3DMakeTranslation(x, y, z)
Such margin can be achieved by setting leftView / rightView to UITextField.
Updated For Swift 4
// Create a padding view for padding on left
textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 15, height: textField.frame.height))
textField.leftViewMode = .always
// Create a padding view for padding on right
textField.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 15, height: textField.frame.height))
textField.rightViewMode = .always
I just added/placed an UIView to left and right side of the textfield. So now the typing will start after the view.
Thanks
Hope this helped...
Swift 4, Xcode 9
I like Pheepster's answer, but how about we do it all from the extension, without requiring VC code or any subclassing:
import UIKit
#IBDesignable
extension UITextField {
#IBInspectable var paddingLeftCustom: CGFloat {
get {
return leftView!.frame.size.width
}
set {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
leftView = paddingView
leftViewMode = .always
}
}
#IBInspectable var paddingRightCustom: CGFloat {
get {
return rightView!.frame.size.width
}
set {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
rightView = paddingView
rightViewMode = .always
}
}
}
Use my extension Swift 5 tested:
extension UITextField {
enum PaddingSpace {
case left(CGFloat)
case right(CGFloat)
case equalSpacing(CGFloat)
}
func addPadding(padding: PaddingSpace) {
self.leftViewMode = .always
self.layer.masksToBounds = true
switch padding {
case .left(let spacing):
let leftPaddingView = UIView(frame: CGRect(x: 0, y: 0, width: spacing, height: self.frame.height))
self.leftView = leftPaddingView
self.leftViewMode = .always
case .right(let spacing):
let rightPaddingView = UIView(frame: CGRect(x: 0, y: 0, width: spacing, height: self.frame.height))
self.rightView = rightPaddingView
self.rightViewMode = .always
case .equalSpacing(let spacing):
let equalPaddingView = UIView(frame: CGRect(x: 0, y: 0, width: spacing, height: self.frame.height))
// left
self.leftView = equalPaddingView
self.leftViewMode = .always
// right
self.rightView = equalPaddingView
self.rightViewMode = .always
}
}
}
How to use
// equal padding
yourTextField.addPadding(padding: .equalSpacing(10))
// padding right
yourTextField.addPadding(padding: .right(10))
// padding left
yourTextField.addPadding(padding: .left(10))
in Swift 4.2 and Xcode 10
Initially my text field is like this.
After adding padding in left side my text field is...
//Code for left padding
textFieldName.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: textFieldName.frame.height))
textFieldName.leftViewMode = .always
Like this we can create right side also.(textFieldName.rightViewMode = .always)
If you want SharedInstance type code(Write once use every ware) see the below code.
//This is my shared class
import UIKit
class SharedClass: NSObject {
static let sharedInstance = SharedClass()
//This is my padding function.
func textFieldLeftPadding(textFieldName: UITextField) {
// Create a padding view
textFieldName.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 3, height: textFieldName.frame.height))
textFieldName.leftViewMode = .always//For left side padding
textFieldName.rightViewMode = .always//For right side padding
}
private override init() {
}
}
Now call this function like this.
//This single line is enough
SharedClass.sharedInstance.textFieldLeftPadding(textFieldName:yourTF)
Simple swift 3 solution - add code to viewDidLoad:
let indentView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 20))
textField.leftView = indentView
textField.leftViewMode = .always
No need for ridiculously long code
Here is Haagenti's answer updated to Swift 4.2:
class PaddedTextField: UITextField {
func getPadding(plusExtraFor clearButtonMode: ViewMode) -> UIEdgeInsets {
var padding = UIEdgeInsets(top: 11, left: 16, bottom: 11, right: 16)
// Add additional padding on the right side when showing the clear button
if self.clearButtonMode == .always || self.clearButtonMode == clearButtonMode {
padding.right = 28
}
return padding
}
override open func textRect(forBounds bounds: CGRect) -> CGRect {
let padding = getPadding(plusExtraFor: .unlessEditing)
return bounds.inset(by: padding)
}
override open func placeholderRect(forBounds bounds: CGRect) -> CGRect {
let padding = getPadding(plusExtraFor: .unlessEditing)
return bounds.inset(by: padding)
}
override open func editingRect(forBounds bounds: CGRect) -> CGRect {
let padding = getPadding(plusExtraFor: .whileEditing)
return bounds.inset(by: padding)
}
}
Reference: Upgrading To Swift 4.2.
Edit: Account for clear button.
To create padding view for UITextField in Swift 5
func txtPaddingVw(txt:UITextField) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 5))
txt.leftViewMode = .always
txt.leftView = paddingView
}
This one line of code saved me:
For Xamarin.iOS:
textField.Layer.SublayerTransform = CATransform3D.MakeTranslation(5, 0, 0);
For Swift:
textField.layer.sublayerTransform = CATransform3DMakeTranslation(5, 0, 0);
Subclassing UITextField is the way to go. Open a playground and add the following code:
class MyTextField : UITextField {
var leftTextMargin : CGFloat = 0.0
override func textRectForBounds(bounds: CGRect) -> CGRect {
var newBounds = bounds
newBounds.origin.x += leftTextMargin
return newBounds
}
override func editingRectForBounds(bounds: CGRect) -> CGRect {
var newBounds = bounds
newBounds.origin.x += leftTextMargin
return newBounds
}
}
let tf = MyTextField(frame: CGRect(x: 0, y: 0, width: 100, height: 44))
tf.text = "HELLO"
tf.leftTextMargin = 25
tf.setNeedsLayout()
tf.layoutIfNeeded()
Easy way: to do this by extending UITextField
extension UITextField {
func setPadding(left: CGFloat? = nil, right: CGFloat? = nil){
if let left = left {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: left, height: self.frame.size.height))
self.leftView = paddingView
self.leftViewMode = .always
}
if let right = right {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: right, height: self.frame.size.height))
self.rightView = paddingView
self.rightViewMode = .always
}
}
}
Then you can set padding to any edge this way:
textField.setPadding(left: 5, right: 5)
In most cases you can regard this as a technicality but all the examples don't get the difference between frame and bounds right. When referencing the view's height in a subview, use bounds – otherwise you may run into trouble once some transform is applied to the parent.
See the updated code below (based on Pheepster's answer).
extension UITextField {
func setLeftPadding(_ amount: CGFloat = 10) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.bounds.size.height))
self.leftView = paddingView
self.leftViewMode = .always
}
func setRightPadding(_ amount: CGFloat = 10) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.bounds.size.height))
self.rightView = paddingView
self.rightViewMode = .always
}
}
Create UIView with required padding space and add it to textfield.leftView member and set textfield.leftViewMode member to UITextFieldViewMode.Always
// For example if you have textfield named title
#IBOutlet weak var title: UITextField!
// Create UIView
let paddingView : UIView = UIView(frame: CGRectMake(0, 0, 5, 20))
//Change your required space instaed of 5.
title.leftView = paddingView
title.leftViewMode = UITextFieldViewMode.Always
I prefer to use IBDesignable class and IBInspectable properties to allow me to set the padding via Xcode storyboards and keep it reusable. I've also updated the code to work in Swift 4.
import Foundation
import UIKit
#IBDesignable
class PaddableTextField: UITextField {
var padding = UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
#IBInspectable var left: CGFloat = 0 {
didSet {
adjustPadding()
}
}
#IBInspectable var right: CGFloat = 0 {
didSet {
adjustPadding()
}
}
#IBInspectable var top: CGFloat = 0 {
didSet {
adjustPadding()
}
}
#IBInspectable var bottom: CGFloat = 0 {
didSet {
adjustPadding()
}
}
func adjustPadding() {
padding = UIEdgeInsets(top: top, left: left, bottom: bottom, right: right)
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
}
override func textRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: UIEdgeInsets(top: top, left: left, bottom: bottom, right: right))
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: UIEdgeInsets(top: top, left: left, bottom: bottom, right: right))
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return bounds.inset(by: UIEdgeInsets(top: top, left: left, bottom: bottom, right: right))
}
}
Put this code in your viewDidLoad():
textField.delegate = self
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: self.textField.frame.height))
textField.leftView = paddingView
textField.leftViewMode = UITextFieldViewMode.always
It works for me :)
ScareCrow's answer in Swift 3
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5);
override func textRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override func placeholderRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
override func editingRect(forBounds bounds: CGRect) -> CGRect {
return UIEdgeInsetsInsetRect(bounds, padding)
}
In Swift 3.
You may use custom UITextField with indent that is set in its constructor. Don't need for extra declaration in a controller.
class CustomTextField : UITextField {
private let indentView = UIView(frame: CGRect(x: 0, y:0, width: 10, height: 10))
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.leftView = indentView
self.leftViewMode = .always
}
}
* Extending UITextField in Swift 5 *
import UIKit
#IBDesignable
extension UITextField {
#IBInspectable var paddingLeftCustom: CGFloat {
get {
return leftView!.frame.size.width
}
set {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
leftView = paddingView
leftViewMode = .always
}
}
#IBInspectable var paddingRightCustom: CGFloat {
get {
return rightView!.frame.size.width
}
set {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: newValue, height: frame.size.height))
rightView = paddingView
rightViewMode = .always
}
}
}
//MARK:- Use this class for different type of Roles
import UIKit
class HelperExtensionViewController: UIViewController {
}
//MARK:- Extension
extension UIImageView
{
func setImageCornerRadius()
{
self.layer.cornerRadius = self.frame.size.height/2
self.clipsToBounds = true
}
func setImageCornerRadiusInPoints(getValue:CGFloat)
{
self.layer.cornerRadius = getValue
self.clipsToBounds = true
}
}
extension UIButton
{
func setButtonCornerRadiusOnly()
{
self.layer.cornerRadius = self.frame.size.height/2
self.clipsToBounds = true
}
func setBtnCornerRadiusInPoints(getValue:CGFloat)
{
self.layer.cornerRadius = getValue
self.clipsToBounds = true
}
}
extension UITextField
{
func setTextFieldCornerRadiusWithBorder()
{
self.layer.cornerRadius = self.frame.size.height/2
self.layer.borderColor = UIColor.darkGray.cgColor
self.backgroundColor = UIColor.clear
self.layer.borderWidth = 0.5
self.clipsToBounds = true
}
func setLeftPaddingPoints(_ amount:CGFloat){
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height))
self.leftView = paddingView
self.leftViewMode = .always
}
func setRightPaddingPoints(_ amount:CGFloat) {
let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: amount, height: self.frame.size.height))
self.rightView = paddingView
self.rightViewMode = .always
}
}
extension UIView
{
func setCornerRadius()
{
self.layer.cornerRadius = self.frame.size.height/2
self.clipsToBounds = true
}
// OUTPUT 1
func setViewCornerRadiusWithBorder()
{
self.layer.cornerRadius = self.frame.size.height/2
self.layer.borderColor = UIColor.init(red: 95.0/255.0, green: 229.0/255.0, blue: 206.0/255.0, alpha: 1.0).cgColor
self.backgroundColor = UIColor.clear
self.layer.borderWidth = 1.0
self.clipsToBounds = true
}
func layoutSubviews(myView:UIView)
{
let shadowPath = UIBezierPath(rect: myView.bounds)
myView.layer.masksToBounds = false
myView.layer.shadowColor = UIColor.lightGray.cgColor
myView.layer.shadowOffset = CGSize(width: -1.0, height: 2.0)
myView.layer.shadowOpacity = 0.5
myView.layer.shadowPath = shadowPath.cgPath
}
func layoutSubviews2(myView:UIView)
{
let shadowPath = UIBezierPath(rect: myView.bounds)
myView.clipsToBounds = true
myView.layer.masksToBounds = false
myView.layer.shadowColor = UIColor.black.cgColor
myView.layer.shadowOffset = CGSize(width: 0.0, height: 1.0)
myView.layer.shadowOpacity = 0.2
myView.layer.shadowPath = shadowPath.cgPath
}
func setViewCornerRadiusInPoints(getValue:CGFloat)
{
self.layer.cornerRadius = getValue
self.clipsToBounds = true
}
func dropShadow(scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = UIColor.black.cgColor
layer.shadowOpacity = 0.5
layer.shadowOffset = CGSize(width: -1, height: 1)
layer.shadowRadius = 1
layer.shadowPath = UIBezierPath(rect: bounds).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
// OUTPUT 2
func dropShadow(color: UIColor, opacity: Float = 0.5, offSet: CGSize, radius: CGFloat = 1, scale: Bool = true) {
layer.masksToBounds = false
layer.shadowColor = color.cgColor
layer.shadowOpacity = opacity
layer.shadowOffset = offSet
layer.shadowRadius = radius
layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
layer.shouldRasterize = true
layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
func setGradientBackground(myview:UIView) {
let colorTop = UIColor(red: 100.0/255.0, green: 227.0/255.0, blue: 237.0/255.0, alpha: 1.0).cgColor
let colorBottom = UIColor(red: 141.0/255.0, green: 109.0/255.0, blue: 164.0/255.0, alpha: 1.0).cgColor
let gradientLayer = CAGradientLayer()
gradientLayer.colors = [colorTop, colorBottom]
gradientLayer.locations = [1.0, 1.0]
gradientLayer.frame = myview.bounds
myview.layer.insertSublayer(gradientLayer, at:0)
}
}
To Extend original answer for leftView and Swift5+
class TextField: UITextField {
let padding = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
override open func textRect(forBounds bounds: CGRect) -> CGRect {
let paddedRect = bounds.inset(by: self.padding)
if (self.leftViewMode == .always || self.leftViewMode == .unlessEditing) {
return self.adjustRectOriginForLeftView(bounds: paddedRect)
}
return paddedRect
}
override open func placeholderRect(forBounds bounds: CGRect) -> CGRect {
let paddedRect = bounds.inset(by: self.padding)
if (self.leftViewMode == .always || self.leftViewMode == .unlessEditing) {
return self.adjustRectOriginForLeftView(bounds: paddedRect)
}
return paddedRect;
}
override open func editingRect(forBounds bounds: CGRect) -> CGRect {
let paddedRect = bounds.inset(by: self.padding);
if (self.leftViewMode == .always || self.leftViewMode == .unlessEditing) {
return self.adjustRectOriginForLeftView(bounds: paddedRect)
}
return paddedRect;
}
func adjustRectOriginForLeftView(bounds : CGRect) -> CGRect{
var paddedRect = bounds;
paddedRect.origin.x += self.leftView!.frame.width
return paddedRect
}
}
Create space at the beginning of a UITextField.
in Swift 5+ and Xcode 12.
textFieldName.setLeftPaddingPoints(CGFloat(10))
textFieldName.setRightPaddingPoints(CGFloat(10)

Custom progress view

I want to do a custom progress view for my iOS app, with 2 dots. Here is my code:
import UIKit
#IBDesignable
class StepProgressView: UIView {
#IBInspectable var progress: Float = 0
var progressColor = UIColor.blackColor()
var bgColor = UIColor.whiteColor()
override func layoutSubviews() {
self.backgroundColor = UIColor.clearColor()
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
let height = frame.height-8
let circle1 = UIView(frame: CGRect(x: frame.width*(1/3), y: 0, width: frame.height, height: frame.height))
circle1.backgroundColor = bgColor
circle1.layer.cornerRadius = frame.height/2
addSubview(circle1)
let circle2 = UIView(frame: CGRect(x: frame.width*(2/3), y: 0, width: frame.height, height: frame.height))
circle2.backgroundColor = bgColor
circle2.layer.cornerRadius = frame.height/2
addSubview(circle2)
let bgView = UIView(frame: CGRect(x: height/2, y: 4, width: frame.width-height/2, height: height))
bgView.backgroundColor = bgColor
bgView.layer.cornerRadius = height/2
addSubview(bgView)
let progressView = UIView(frame: CGRect(x: 0, y: 4, width: frame.width*CGFloat(progress), height: height))
progressView.backgroundColor = progressColor
progressView.layer.cornerRadius = height/2
addSubview(progressView)
}
}
The result:
However, as you can see, the circles aren't "filled" when the progression pass over one of them, and I don't know how to do that. I could create another view but I don't know how to handle the corner radius.
Can you help me ?
Thanks

Resources