I am creating a custom button and the code for this is below. All the styling elements are working, however my the name and image subviews are not being added. I am sure this is a simple error, but I would appreciate it if someone could help me. Thank you.
class MaterialButton: UIButton {
let name = UILabel()
let image = UIImageView()
override init(frame: CGRect) {
super.init(frame: frame)
setupButton()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
super.init(coder: aDecoder)
setupButton()
}
func setupButton() {
name.textColor = .white
// name.font = UIFont(name: "HelveticaNeue-UltraLight",size: 10.0)
name.textAlignment = .center
self.layer.cornerRadius = 20
addSubview(name)
positionName()
addSubview(image)
positionImage()
}
func positionName() {
name.translatesAutoresizingMaskIntoConstraints = false
name.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 10).isActive = true
name.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
name.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
name.heightAnchor.constraint(equalToConstant: self.bounds.height - image.bounds.height - 20).isActive = true
}
func positionImage() {
image.translatesAutoresizingMaskIntoConstraints = false
image.heightAnchor.constraint(equalToConstant: image.bounds.width).isActive = true
image.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
image.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
image.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
}
}
Example of how button is implemented (other button was declared initialized with Material Button earlier in the code)
func setupOtherButton() { // Setting up plastic button
otherButton.name.text = "Other"
otherButton.name.textColor = .white
otherButton.backgroundColor = .gray
miniSV1.addSubview(otherButton) // Add plastic button to view
otherButton.addTarget(self, action: #selector(otherButtonTapped), for: .touchUpInside)
}
Well don't know the exact UI that you are implementing but I did some changes in your code and got the following UI:
So for the button in viewDidLoad :
class ViewController: UIViewController {
var otherButton = MaterialButton()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
otherButton.frame = CGRect(x: 10, y: 180, width: 140, height: 140)
otherButton.name.text = "Other"
otherButton.name.textColor = .white
otherButton.backgroundColor = .gray
self.view.addSubview(otherButton)
}
}
And few changes in the constraints:
class MaterialButton: UIButton {
let name = UILabel()
let image = UIImageView()
override init(frame: CGRect) {
super.init(frame: frame)
setupButton()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
super.init(coder: aDecoder)
setupButton()
}
func setupButton() {
image.backgroundColor = UIColor.yellow
addSubview(image)
positionImage()
name.textColor = .white
name.textAlignment = .center
name.backgroundColor = .blue
self.layer.cornerRadius = 20
addSubview(name)
positionName()
}
func positionName() {
name.translatesAutoresizingMaskIntoConstraints = false
name.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true
name.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
name.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
name.heightAnchor.constraint(equalToConstant: 20).isActive = true
}
func positionImage() {
image.translatesAutoresizingMaskIntoConstraints = false
image.heightAnchor.constraint(equalToConstant: 50).isActive = true
image.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
image.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
image.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
}
}
Check out this URL for better understanding of the constraints programmatically:
How to add constraints programmatically using Swift
Related
I have created a view in my View controller which has UISegmentControl and a UIScrollView
let segmentControl : UISegmentedControl = {
let segmentItems = ["Personal","Statistics","Calendar"]
let segmentControl = UISegmentedControl(items: segmentItems)
segmentControl.selectedSegmentIndex = 0
segmentControl.addTarget(self, action: #selector(selectIn(sender:)), for: .valueChanged)
segmentControl.translatesAutoresizingMaskIntoConstraints = false
return segmentControl
}()
let subView : UIScrollView = {
let view = UIScrollView()
view.backgroundColor = .red
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
In viewDidLoad I added
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.isHidden = true
view.addSubview(segmentControl)
view.addSubview(subView)
setLayout()
}
and added layout as follows
func setLayout(){
NSLayoutConstraint.activate([
segmentControl.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10),
segmentControl.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20),
segmentControl.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20),
segmentControl.heightAnchor.constraint(equalToConstant: 30),
subView.topAnchor.constraint(equalTo: segmentControl.bottomAnchor, constant: 10),
subView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20),
subView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -20),
subView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
])
}
and tried to add PersonalView (UIView) when any segmentControl is pressed
#objc func selectIn(sender: UISegmentedControl){
subView.addSubview(pvc)
}
My personalView is as follows
class PersonalView: UIView, UICollectionViewDelegate, UICollectionViewDataSource, UITableViewDelegate, UITableViewDataSource {
let tempValueForTable : Int = 10
let todayLabel : UILabel = {
let label = UILabel()
label.text = "Today"
label.font = .montserratSemiBold
label.textAlignment = .center
label.backgroundColor = .green
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(todayLabel)
setLayout()
}
private func setLayout(){
NSLayoutConstraint.activate([
todayLabel.topAnchor.constraint(equalTo: self.topAnchor),
todayLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20),
todayLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20),
todayLabel.heightAnchor.constraint(equalToConstant: 25),
])
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}}
Still I am not able to get view and in further update I need to add more view in same ScrollView
1.when you are using auto layout constraints you must set this false after add.
SomeView.translatesAutoresizingMaskIntoConstraints = false
2.After you add your subView you must set its constraints and call view.layoutIfNeeded()
subView.addSubview(pvc)
pvc.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
pvc.trailingAnchor.constraint(equalTo: subView.trailingAnchor),
pvc.leadingAnchor.constraint(equalTo: subView.leadingAnchor),
pvc.topAnchor.constraint(equalTo: subView.topAnchor),
pvc.bottomAnchor.constraint(equalTo: subView.bottomAnchor),
])
view.layoutIfNeeded()
I am trying to align a custom UIView to the center of view using auto layout but I am getting a blank screen.
Please can someone advise on where my code is incorrect?
My Controller's code:
import UIKit
class TestViewController: UIViewController{
var margin: UILayoutGuide!
override func viewDidLoad() {
super.viewDidLoad()
margin = self.view.layoutMarginsGuide
let size = CGRect.init(x: 0, y: 0, width: 200, height: 100)
let sq1 = Square.init(frame: size, color: UIColor.blue)
view.addSubview(sq1)
sq1.translatesAutoresizingMaskIntoConstraints = false
sq1.centerXAnchor.constraint(equalTo: margin.centerXAnchor).isActive = true
sq1.topAnchor.constraint(greaterThanOrEqualTo: margin.topAnchor, constant: 20).isActive = true
sq1.leadingAnchor.constraint(greaterThanOrEqualTo: margin.leadingAnchor, constant: 20).isActive = true
sq1.trailingAnchor.constraint(greaterThanOrEqualTo: margin.trailingAnchor, constant: 20).isActive = true
}
}
My Custom View's code:
class Square: UIView{
init(frame: CGRect, color: UIColor) {
super.init(frame: frame)
makeSquare(frame: frame, colour: color)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func makeSquare(frame: CGRect, colour: UIColor){
self.layer.frame = self.bounds
self.layer.backgroundColor = colour.cgColor
}
}
You need a height constraint , also don't mix frame layout with auto layout you should use either of them
sq1.heightAnchor.constraint(equalToConstant:200).isActive = true
Also if you set leading and trailing
sq1.leadingAnchor.constraint(greaterThanOrEqualTo: margin.leadingAnchor, constant: 20).isActive = true
sq1.trailingAnchor.constraint(greaterThanOrEqualTo: margin.trailingAnchor, constant: 20).isActive = true
then no need for a centerX
sq1.centerXAnchor.constraint(equalTo: margin.centerXAnchor).isActive = true
NSLayoutConstraint.activate([
sq1.topAnchor.constraint(equalTo: margin.topAnchor, constant: 20),
sq1.leadingAnchor.constraint(equalTo: margin.leadingAnchor, constant: 20),
sq1.trailingAnchor.constraint(equalTo: margin.trailingAnchor, constant: -20),
sq1.heightAnchor.constraint(equalToConstant: 200)
])
After some small additions:
class Square: UIView {
init(color: UIColor) {
// The view is ignored with auto layout.
super.init(frame: .zero)
backgroundColor = color
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Then in the viewDidLoad function:
override func viewDidLoad() {
super.viewDidLoad()
let sq = Square(color: .orange)
sq.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(sq)
sq.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
sq.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
// -40 to compensate for the leading and trailing.
sq.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1, constant: -40).isActive = true
sq.heightAnchor.constraint(equalTo: sq.widthAnchor).isActive = true
// Do any additional setup after loading the view.
}
I've taken the freedom to set the height equal to the width, as you create a square, but not sure if you want that. Hope this helps!
try it
class Square: UIView {
func setColor(colour: UIColor){
self.backgroundColor = colour
}
}
call this func in ViewDidLoad
func initView() {
self.view.backgroundColor = .red
margin = self.view.layoutMarginsGuide
let sq1 = Square()
view.addSubview(sq1)
sq1.translatesAutoresizingMaskIntoConstraints = false
sq1.centerXAnchor.constraint(equalTo: margin.centerXAnchor).isActive = true
sq1.topAnchor.constraint(greaterThanOrEqualTo: margin.topAnchor, constant: 20).isActive = true
sq1.widthAnchor.constraint(equalToConstant: 200).isActive = true
sq1.heightAnchor.constraint(equalToConstant: 200).isActive = true
sq1.setColor( colour: UIColor.blue)
}
result
I created a UIButton and added it to my view controller but on load, the button does not show despite adding it to subview and constraints
var plusBtn: DefaultBtn = {
let plusBtn = DefaultBtn(type: .custom)
plusBtn.translatesAutoresizingMaskIntoConstraints = false
return plusBtn
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(plusBtn)
plusBtn.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
plusBtn.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
plusBtn.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
plusBtn.setTitle("BUT WHY", for: .normal)
}
class DefaultBtn: UIButton {
override func awakeFromNib() {
// layer.cornerRadius = self.frame.size.height / 2
layer.borderWidth = 1
layer.borderColor = UIColor.black.cgColor
backgroundColor = .white
// heightAnchor.constraint(equalToConstant: 50).isActive = true
// widthAnchor.constraint(equalToConstant: 50).isActive = true
translatesAutoresizingMaskIntoConstraints = false
setTitleColor(.black, for: .normal)
}
}
any help is appreciated
Try
view.backgroundColor = .red
OR
plusBtn.setTitleColor(.red, for: .normal)
the default title color of the button is white which is same as the view's background color
class DefaultBtn: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
shared()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func shared () {
layer.borderWidth = 1
layer.borderColor = UIColor.black.cgColor
backgroundColor = .white
translatesAutoresizingMaskIntoConstraints = false
setTitleColor(.black, for: .normal)
}
}
My UILabel is pinned to the top of the cell, just like UIImage but if the text below has f.e. 1 line (its also in UILabel) my top UILabel is in other place.
Here are my constraints and labels declaration. Thanks to anyone who will try to solve my problem :) I tried using sizeToFit method on my UILabels
var albumImage: UIImageView = {
let view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
view.contentMode = .scaleAspectFit
return view
}()
var albumName: UILabel = {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.numberOfLines = 0
view.sizeToFit()
return view
}()
var bandName: UILabel = {
let view = UILabel()
view.translatesAutoresizingMaskIntoConstraints = false
view.sizeToFit()
return view
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
drawLayout()
}
required init?(coder aDecoder: NSCoder) {
fatalError("ERROR")
}
func drawLayout(){
let guide = self.safeAreaLayoutGuide
//albumImage
addSubview(albumImage)
addSubview(albumName)
addSubview(bandName)
albumImage.heightAnchor.constraint(equalToConstant: 50).isActive = true
albumImage.widthAnchor.constraint(equalToConstant: 50).isActive = true
albumImage.leadingAnchor.constraint(equalTo: guide.leadingAnchor, constant: 8).isActive = true
albumImage.topAnchor.constraint(equalTo: self.topAnchor, constant: 8).isActive = true
albumImage.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8).isActive = true
//albumTitle
albumName.topAnchor.constraint(equalTo: bandName.bottomAnchor).isActive = true
albumName.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8).isActive = true
albumName.leadingAnchor.constraint(equalTo: albumImage.trailingAnchor, constant: 8).isActive = true
albumName.trailingAnchor.constraint(equalTo: guide.trailingAnchor, constant: -8).isActive = true
//bandName
bandName.topAnchor.constraint(equalTo: albumImage.topAnchor).isActive = true
bandName.leadingAnchor.constraint(equalTo: albumImage.trailingAnchor, constant: 8).isActive = true
}
how do i make custom UITextfield? i have created class with uitextfield as a subclass then i added label it shows up, but the border(UIView) are not showing up here is the code
import UIKit
class borderedTextField: UITextField{
let viewz:UIView! = UIView()
var border:UIView! = UIView()
var name:UILabel! = UILabel()
override func draw(_ rect: CGRect) {
self.addSubview(viewz)
}
override func layoutSubviews() {
backgroundColor = UIColor.green
}
func placement(){
border.frame.size.height = 15
border.backgroundColor = UIColor.black
border.translatesAutoresizingMaskIntoConstraints = false
viewz.addSubview(border)
border.heightAnchor.constraint(equalToConstant: 15).isActive = true
border.widthAnchor.constraint(equalToConstant: 100)
border.leftAnchor.constraint(equalTo: viewz.leftAnchor, constant: 10).isActive = true
border.bottomAnchor.constraint(equalTo: viewz.bottomAnchor, constant: -5).isActive = true
name.text = "whatt"
name.textAlignment = .left
name.textColor = UIColor.black
name.translatesAutoresizingMaskIntoConstraints = false
viewz.addSubview(name)
name.widthAnchor.constraint(equalToConstant: 100)
name.heightAnchor.constraint(equalToConstant: 50)
name.leftAnchor.constraint(equalTo: viewz.leftAnchor, constant: 5).isActive = true
name.topAnchor.constraint(equalTo: viewz.topAnchor, constant: 10).isActive = true
}
}
and i called it programatically (without storyboard) please let me know how to solve this problem without using storyboard i need it to be full code.
import UIKit
class signViewController: UIViewController,UITextFieldDelegate {
var animText:borderedTextField!
override func viewDidLoad() {
super.viewDidLoad()
let animText = borderedTextField()
animText.delegate = self
animText.placeholder = "click here"
animText.placement()
animText.frame = CGRect(x: 100, y: 500, width: 200, height: 90)
view.addSubview(animText)
}
}
You have to add init
override init (frame : CGRect) {
super.init(frame : frame)
self.placement()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.placement()
}
Also width of border is not active
border.widthAnchor.constraint(equalToConstant: 100).active = true
for name
name.widthAnchor.constraint(equalToConstant: 100).active = true
name.heightAnchor.constraint(equalToConstant: 50).active = true
Edit
border.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
border.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -5).isActive = true