This question already has answers here:
Rounded Corners only on Top of a UIView
(11 answers)
Closed 1 year ago.
I have UIView which I need to draw a border only partial part view, this is how my design look alike, how do i make it ?
expected
Try this
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var droppedView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
droppedView.clipsToBounds = true
droppedView.layer.cornerRadius = 24 // 얼만큼 둥글게 할 것인지
droppedView.layer.maskedCorners = [.layerMinXMinYCorner,
.layerMaxXMinYCorner]
droppedView.backgroundColor = .systemGray6
}
}
#IBOutlet weak var shadowVw: UIView!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
shadowVw.layer.cornerRadius = 24
shadowVw.layer.maskedCorners = [.layerMinXMinYCorner,.layerMaxXMinYCorner]
shadowVw.backgroundColor = .systemGray6
shadowVw.layer.shadowColor = UIColor.lightGray.cgColor
shadowVw.layer.shadowOpacity = 0.7
shadowVw.layer.shadowOffset = CGSize(width: 0.0, height: -5.0)
shadowVw.layer.shadowRadius = 5
}
Related
How can I change the color only of extra letters when typing in UITextField in Swift and return the color back when deleting?
I was able only to change color of all letters, when exceeding the limit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var inputLimitField: UITextField!
#IBOutlet weak var characterCountLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
characterCountLabel.text = "10/10"
inputLimitField.delegate = self
}
func checkRemainingChars() {
let allowedChars = 10
let charsInTextView = -(inputLimitField.text?.count ?? 0)
let remainingChars = allowedChars + charsInTextView
characterCountLabel.textColor = .black
inputLimitField.textColor = .black
inputLimitField.layer.borderColor = UIColor.systemGray3.cgColor
if remainingChars < 0 {
characterCountLabel.textColor = .red
inputLimitField.textColor = .red
inputLimitField.layer.borderColor = UIColor.red.cgColor
inputLimitField.layer.cornerRadius = 6.0
inputLimitField.layer.borderWidth = 1.0
}
characterCountLabel.text = ("\(String(remainingChars))/10")
}
func textFieldDidChangeSelection(_ textField: UITextField) {
checkRemainingChars()
}
}
this is what I expected to get
enter image description here
and this is what I really get enter image description here
p.s. also I can't put a letter counter in the corner through TF's border, because there is a mistake when I import Material Components: No such module 'MaterialComponents'
I have created a simple custom UIView:
final class TestView: UIView {
var testColor: UIColor = .white {
didSet {
backgroundColor = testColor
}
}
}
Then I wrote this in my view controller:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var testView: TestView!
#IBOutlet weak var testView2: TestView!
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
TestView.appearance().testColor = .red
}
}
}
By doing this, I get an error:
Could you help me understanding what's wrong here and how to implement the UIAppearance proxy for any custom UIView?
Thank you for your help
You need to make the property #objc and dynamic:
final class TestView: UIView {
#objc dynamic var testColor: UIColor? = .white {
didSet {
backgroundColor = testColor
}
}
}
Worth noting: the UIAppearance proxy does NOT affect views which are already part of the view hierarchy.
So, in your example, adding #objc dynamic to your property will get rid of the crash, but you will not see any change to the two #IBOutlet views.
If you call it as part of viewDidLoad() (instead of DispatchQueue.main.asyncAfter):
override func viewDidLoad() {
super.viewDidLoad()
TestView.appearance().testColor = .red
}
The two #IBOutlet views will get the red background.
Or, if you add a new view to the hierarchy, it will get the red background:
class AppearanceTestViewController: UIViewController {
#IBOutlet weak var testView: TestView!
#IBOutlet weak var testView2: TestView!
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) {
TestView.appearance().testColor = .red
self.addAnotherTestView()
}
}
func addAnotherTestView() -> Void {
let v = TestView()
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
NSLayoutConstraint.activate([
v.widthAnchor.constraint(equalToConstant: 240.0),
v.heightAnchor.constraint(equalTo: v.widthAnchor),
v.centerXAnchor.constraint(equalTo: view.centerXAnchor),
v.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
// this newly added view WILL have a red background
}
}
I am trying to get my button to render a shadow in swift 4.2
I've followed other examples to no avail. What am I missing?
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var btnHi: UIButton! // Standard button tweeked in view controller
#IBOutlet weak var btnNext: NextButton! // My custom button via class
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
btnHi.layer.cornerRadius = btnHi.frame.height / 2
btnHi.layer.borderWidth = 3.0
btnHi.layer.borderColor = UIColor.darkGray.cgColor
btnHi.layer.shadowColor = UIColor.black.cgColor
btnHi.layer.shadowOffset = CGSize(width: 0.0, height: 6.0)
btnHi.layer.shadowRadius = 8
btnHi.layer.opacity = 0.5
// btnHi.clipsToBounds = true
// btnHi.layer.masksToBounds = false
}
#IBAction func btnNext(_ sender: Any) {
btnNext.setupShakeButton()
}
}
should see a drop shadow for the button instead I get no shadow.
You are missing shadowOpacity which is zero by default. You should probably not use opacity because that makes the whole button semitransparent.
btnHi.layer.shadowColor = UIColor.black.cgColor
btnHi.layer.shadowOffset = CGSize(width: 0.0, height: 6.0)
btnHi.layer.shadowRadius = 8
btnHi.layer.shadowOpacity = 0.5
Also note that clipping has to be turned off:
btnHi.layer.masksToBounds = false
I have a green view, which is pinned to the edges of the top view. On top is a blue view, which is also a child of the top view and which is aligned using the following code...
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var blueView: UIView!
#IBOutlet weak var greenView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
blueView.translatesAutoresizingMaskIntoConstraints = false
blueView.widthAnchor.constraint(equalTo: greenView.widthAnchor).isActive = true
blueView.leftAnchor.constraint(equalTo: greenView.leftAnchor).isActive = true
blueView.heightAnchor.constraint(equalTo: greenView.heightAnchor).isActive = true
let top = blueView.topAnchor.constraint(equalTo: greenView.topAnchor)
top.priority = 800
top.isActive = true
view.layoutIfNeeded()
UIView.animate(withDuration: 5) {
let bottom = self.blueView.topAnchor.constraint(equalTo: self.greenView.bottomAnchor)
bottom.priority = 1000
bottom.isActive = true
self.view.layoutIfNeeded()
}
}
}
If I comment out the animation code, this is how it looks...
With the animation block, the blue view finishes in the correct place, but it starts at the top of the screen instead of aligned to the top of the green view.
Why is the animation block causing the blue view to start further up the screen?
OK - the Blue view is not starting at the top of the Green view because you are starting your animation before the initial layout has finished.
You could move the animation block into a function triggered after a delay, or into viewDidAppear:
import UIKit
class AnimViewController: UIViewController {
#IBOutlet weak var blueView: UIView!
#IBOutlet weak var greenView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
blueView.translatesAutoresizingMaskIntoConstraints = false
blueView.widthAnchor.constraint(equalTo: greenView.widthAnchor).isActive = true
blueView.leftAnchor.constraint(equalTo: greenView.leftAnchor).isActive = true
blueView.heightAnchor.constraint(equalTo: greenView.heightAnchor).isActive = true
let top = blueView.topAnchor.constraint(equalTo: greenView.topAnchor)
top.priority = 800
top.isActive = true
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 5) {
let bottom = self.blueView.topAnchor.constraint(equalTo: self.greenView.bottomAnchor)
bottom.priority = 1000
bottom.isActive = true
self.view.layoutIfNeeded()
}
}
}
i'm making a custom keyboard and wanna add shadow to buttons.
so added some code(keys.layer~~) in viewDidLoad()
but i can't set multiple button to one IBOutlet
what i want is all keys have 'keys(IBOutlet)' as value(?)
is it possible? if it's not, any other thing is fine :)
help!
this is my code (pls ignore next keyboard button)
#IBAction func keys(sender: AnyObject) {
}
#IBOutlet weak var keys: UIButton!
#IBOutlet var nextKeyboardButton: UIButton!
override func updateViewConstraints() {
super.updateViewConstraints()
// Add custom view sizing constraints here
}
override func viewDidLoad() {
super.viewDidLoad()
loadInterface()
keys.layer.cornerRadius = 4.0;
keys.layer.shadowColor = UIColor.blackColor().CGColor
keys.layer.shadowOffset = CGSizeMake(0.0, 2.0)
keys.layer.masksToBounds = false
keys.layer.shadowRadius = 1.0
keys.layer.shadowOpacity = 0.5
You can make UIButton extension like this and used with all the object of your custom keyboard Button
extension UIButton {
func setShadow() {
self.layer.cornerRadius = 4.0;
self.layer.shadowColor = UIColor.blackColor().CGColor
self.layer.shadowOffset = CGSizeMake(0.0, 2.0)
self.layer.masksToBounds = false
self.layer.shadowRadius = 1.0
self.layer.shadowOpacity = 0.5
}
}
Now you can call this method with your button object like this way
self.nextKeyboardButton.setShadow()
Edit:
If you want to access multiple Button object with same object you can create an Array of UIButton, and store all the Outlet Button inside that array.
var buttonArray = [UIButton]()