My goal is to make my the ImageView rounded and I already created a custom IBDesignable class
Code
import UIKit
#IBDesignable class MyImageView: UIImageView {
#IBInspectable var borderColor: UIColor = UIColor.clear {
didSet {
layer.borderColor = borderColor.cgColor
}
}
#IBInspectable var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
}
Everything works fine already, but why is the image didn't change to rounded?
Result:
Set the clipToBounds property of UIImageView to true.
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
self.clipsToBounds = true
}
}
Related
I am new in iOS Development, I want to make gradient rounded button by using this designable class
#IBDesignable
class GradientButton: UIButton {
let gradientLayer = CAGradientLayer()
#IBInspectable
var topGradientColor: UIColor? {
didSet {
setGradient(topGradientColor: topGradientColor, bottomGradientColor: bottomGradientColor)
}
}
#IBInspectable
var bottomGradientColor: UIColor? {
didSet {
setGradient(topGradientColor: topGradientColor, bottomGradientColor: bottomGradientColor)
}
}
override func layoutSubviews() {
super.layoutSubviews()
updateCornerRadius()
}
#IBInspectable var fullRounded: Bool = false {
didSet {
updateCornerRadius()
}
}
#IBInspectable var cornerRadiusOfButton : CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadiusOfButton
}
}
func updateCornerRadius() {
layer.cornerRadius = fullRounded ? (frame.size.height / 2) : cornerRadiusOfButton
}
#IBInspectable var borderWidth: CGFloat {
set {
layer.borderWidth = newValue
}
get {
return layer.borderWidth
}
}
#IBInspectable var borderColor: UIColor? {
set {
guard let uiColor = newValue else { return }
layer.borderColor = uiColor.cgColor
}
get {
guard let color = layer.borderColor else { return nil }
return UIColor(cgColor: color)
}
}
private func setGradient(topGradientColor: UIColor?, bottomGradientColor: UIColor?) {
if let topGradientColor = topGradientColor, let bottomGradientColor = bottomGradientColor {
gradientLayer.frame = bounds
gradientLayer.colors = [topGradientColor.cgColor, bottomGradientColor.cgColor]
gradientLayer.borderColor = layer.borderColor
gradientLayer.borderWidth = layer.borderWidth
gradientLayer.cornerRadius = layer.cornerRadius
layer.insertSublayer(gradientLayer, at: 0)
} else {
gradientLayer.removeFromSuperlayer()
}
}
}
but here is the result:
as you can see the width of the gradient layer button is incorret.
here is the constraint layout I use:
I want that gradient layer to have the same width as the original button, I suspect that the problem is in this line
gradientLayer.frame = bounds
but unfortunately I don't know how to set the gradient layer width to be the same size as the original button programmatically in #IBDesignable class
could you please help me to solve this issue ? thanks in advance
Override layoutSubviews inside GradientButton and update the gradientLayer frame as,
override func layoutSubviews() {
super.layoutSubviews()
self.gradientLayer.frame = bounds
}
I created lots of IBInspectable. But today, I observed that Xcode having some properties like this:
In the link, I marked rectangle box. I want to create custom IBInspectable like that. I don't know that is possible or not.
Any help would be appreciated.
Follow below steps to create Custom IBDesignable
Step 1:
Step 2:
step 3: add this code in created customTextView file
import UIKit
#IBDesignable
class customTextView: UITextView {
#IBInspectable var cornerRadius: CGFloat = 4.0 {
didSet{
layer.cornerRadius = cornerRadius
}
}
#IBInspectable var borderWidth: CGFloat = 0.0 {
didSet{
layer.borderWidth = borderWidth
}
}
#IBInspectable var borderColor: UIColor = UIColor.clear {
didSet{
layer.borderColor = borderColor.cgColor
}
}
#IBInspectable var shadowOpacity: Float = 0 {
didSet{
layer.shadowOpacity = shadowOpacity
}
}
#IBInspectable var shadowColor: UIColor = UIColor.clear {
didSet{
layer.shadowColor = shadowColor.cgColor
}
}
#IBInspectable var shadowOffSet: CGSize = CGSize.zero {
didSet{
layer.shadowOffset = shadowOffSet
}
}
}
Step 4:
Step 5: Here you get you custom fields
I can view the changes made using IBInspectable on my simulator but not in my storyboard
I tried reinstalling my Xcode but it didn't fix this issue. Here are some screenshots :
So i know my code works fine because it runs in the simulator and this is a new project altogether so I do not have any of the "Storyboard might still be loading the changes" problems.
import UIKit
extension UIView {
#IBInspectable
var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
#IBInspectable
var borderWidth: CGFloat {
get {
return layer.borderWidth
}
set {
layer.borderWidth = newValue
}
}
#IBInspectable
var borderColor: UIColor? {
get {
let color = UIColor(cgColor: layer.borderColor!)
return color
}
set {
layer.borderColor = newValue?.cgColor
}
}
#IBInspectable
var shadowRadius: CGFloat {
get {
return layer.shadowRadius
}
set {
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.shadowOpacity = 0.4
layer.shadowRadius = shadowRadius
}
}
}
Firstly, you need #IBDesignable directive to render the updates in Storyboard whereas #IBInspectable is only to access the property directly in the Storyboard.
Secondly, you have extended the UIView class to show the inspectable properties in the Storyboard but without #IBDesignable.
Now you would think adding #IBDesignable would solve your problem but sadly you can't apply #IBDesignable on an extension like so:
#IBDesignable //won't work on an extension
extension UIView {
//...
}
You can only apply the #IBDesignable directive on a class you have access to, like so:
#IBDesignable
class MyPrettyDesignableView: UIView {
//...
}
Solution:
Bottomline is that you should subclass UIView and apply the #IBDesignable directive on this class.
Basically, your only option is:
#IBDesignable
class MyPrettyDesignableView: UIView {
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
self.layer.cornerRadius = cornerRadius
self.layer.masksToBounds = true
}
}
#IBInspectable var borderWidth: CGFloat = 0 {
didSet {
self.layer.borderWidth = borderWidth
}
}
#IBInspectable var borderColor: UIColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1) {
didSet {
self.layer.borderColor = borderColor.cgColor
}
}
}
Then in the storyboard, go to the view that you want designable in storyboard and change it's custom class to MyPrettyDesignableView.
Change it's custom class to your IBDesignable subclass:
Set the IBInspectable properties:
Have you checked that in Interface Builder (Editor Menu) that you have set Automatically Refresh Views and Refresh All Views?
Update: Try this:
#IBDesignable public class CustomView: UIView {
#IBInspectable var borderColor: UIColor = .white{
didSet {
layer.borderColor = borderColor.cgColor
}
}
#IBInspectable var borderWidth: CGFloat = 2.0 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var cornerRadius: CGFloat = 10.0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
#IBInspectable var shadowRadius: CGFloat {
get {
return layer.shadowRadius
}
set {
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.shadowOpacity = 0.4
layer.shadowRadius = shadowRadius
}
}
override public func layoutSubviews() {
super.layoutSubviews()
clipsToBounds = true
}
}
Please update your code as below. You must have to set layer.maskToBound = false and view.clipToBounds = false
import UIKit
extension UIView {
#IBInspectable
var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
#IBInspectable
var borderWidth: CGFloat {
get {
return layer.borderWidth
}
set {
layer.borderWidth = newValue
}
}
#IBInspectable
var borderColor: UIColor? {
get {
let color = UIColor(cgColor: layer.borderColor!)
return color
}
set {
layer.borderColor = newValue?.cgColor
}
}
#IBInspectable
var shadowRadius: CGFloat {
get {
return layer.shadowRadius
}
set {
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = CGSize(width: 0, height: 2)
layer.shadowOpacity = 0.4
layer.shadowRadius = shadowRadius
layer.maskToBounds = false
}
}
}
Have you tried to check Automatically Refresh Views or Refresh All Views? It works in my Xcode 9.4.1.
Editor -> Automatically Refresh Views
Assuming you have already applied #IBDesignable correctly at the declaration of a class. And assuming you have already applied #IBInspectable at the properties of the classes, then here is the trick that worked for me.
I delete and retype #IBDesignable.
sometimes even after adding #IBDesignable on the class and #IBInspectable on property definition, your Xcode might not show and refresh, so first
make sure you are using them correctly. if it is not refreshing in my case i had to close all instance of Xcode and restart the Xcode, then it will load the new fresh Interface builder files.
I'm trying to style my UIView inside table cell prototype to have it shadow for it and a couple more styling customization but for some reason when I build the project the changes are not applied.
I have the next code for it in separate file CustomView.swift
import UIKit
#IBDesignable
class CustomView: UIView {
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
layer.masksToBounds = cornerRadius > 0
}
}
#IBInspectable var shadowOpacity: Float = 0 {
didSet {
layer.shadowOpacity = shadowOpacity
}
}
#IBInspectable var shadowRadius: CGFloat = 0 {
didSet {
layer.shadowRadius = shadowRadius
}
}
#IBInspectable var shadowOffset: CGSize = CGSize(width: 0.0, height: 0.0) {
didSet {
layer.shadowOffset = shadowOffset
}
}
#IBInspectable var shadowColor: UIColor? = UIColor(red: 157/255, green: 157/255, blue: 157/255, alpha: 1.0) {
didSet {
layer.shadowColor = shadowColor?.cgColor
}
}
}
I see the field inside the "Attribute inspector" of Xcode 9
but after building it the change are not applied basically I don't see the shadow for view.
The most interesting that I'm using the same approach to customize text fields as well as buttons and this code works for UIButton/UITextField but not for UIView
Does someone know why it doesn't work for UIView ?
Any help greatly appreciated.
Thank you.
check your code:
layer.masksToBounds = cornerRadius > 0
Change that to:
layer.masksToBounds = false
And also make sure that your clipsToBounds is set to false either in code like so:
clipsToBounds = false
or in your storyboard like so:
Please Update the function
#IBInspectable
var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
This view's order is like this
-View Controller
-Fake shadow view
-Container view
-Search Bar
In normal state, roundedcorner works correctly, but when I click on it, there is some shadow. When I type something on it just the view becomes rectengular
try this IBDesignable class and give rounded corner from story board
import Foundation
#IBDesignable class customView: UIView {
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
#IBInspectable var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var borderColor: UIColor = UIColor.gray {
didSet {
layer.borderColor = borderColor.cgColor
}
}
#IBInspectable var shadowColor: UIColor = UIColor.gray {
didSet {
layer.shadowColor = shadowColor.cgColor
}
}
#IBInspectable var shadowOpacity: Float = 1.0 {
didSet {
layer.shadowOpacity = shadowOpacity
}
}
#IBInspectable var shadowRadius: CGFloat = 1.0 {
didSet {
layer.shadowRadius = shadowRadius
}
}
#IBInspectable var masksToBounds: Bool = true {
didSet {
layer.masksToBounds = masksToBounds
}
}
#IBInspectable var shadowOffset: CGSize = CGSize(width: 12, height: 12) {
didSet {
layer.shadowOffset = shadowOffset
}
}
}