UIButton not added to subview swift - swift

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)
}
}

Related

Unable to simultaneously satisfy constraints of InputAccessoryView

I have an InputAccessoryView with a single button in. However, I am getting the following output.
I have set up my InputAccessoryView in my ViewController as below;
lazy var customInputView: ButtonInputView = {
let frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 50)
let view = ButtonInputView(frame: frame)
view.doneButton.addTarget(self, action: #selector(signIn), for: .touchUpInside)
return view
}()
override var inputAccessoryView: UIView? {
return customInputView
}
Xcode is breaking the height constraint of 50 set in the frame of my view. Any reason why??
CUSTOM ACCESSORY INPUT VIEW CLASS
class ButtonInputView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setUpView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var doneButton: UIButton = {
let view = UIButton()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = Color.accent
view.setTitle("Done", for: .normal)
view.titleLabel?.font = Font.mainButton
view.layer.cornerRadius = 19
return view
}()
let separator: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .opaqueSeparator
return view
}()
private func setUpView() {
backgroundColor = Color.background
addSubview(doneButton)
addSubview(separator)
let separatorHeight = (1 / (UIScreen.main.scale))
if let titleLabelText = doneButton.titleLabel?.text {
doneButton.widthAnchor.constraint(equalToConstant: titleLabelText.width(usingFont: Font.mainButton) + 32).isActive = true
}
NSLayoutConstraint.activate([
separator.topAnchor.constraint(equalTo: topAnchor),
separator.leadingAnchor.constraint(equalTo: leadingAnchor),
separator.trailingAnchor.constraint(equalTo: trailingAnchor),
separator.heightAnchor.constraint(equalToConstant: separatorHeight),
doneButton.topAnchor.constraint(equalTo: separator.bottomAnchor, constant: 6),
doneButton.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
doneButton.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -6),
])
}
override var intrinsicContentSize: CGSize {
return CGSize.zero
}
override func didMoveToWindow() {
super.didMoveToWindow()
if #available(iOS 11.0, *) {
if let window = window {
bottomAnchor.constraint(lessThanOrEqualToSystemSpacingBelow: window.safeAreaLayoutGuide.bottomAnchor,
multiplier: 1.0).isActive = true
}
}
}
}

UIScrollView animate offset change when removing nested view

I have a UIScrollView that contains a stack view - I'm basically replicating a tabs feature.
One tab has a taller view than the other, so when I hide the view in the stack view it resizes.
This causes the scroll view to jump to the offset that fits the shorter view, in the event the user has scrolled to the top.
Is it possible to instead animate this change? Instead of the jump, the view scrolls to the correct offset? I am unsure how to achieve this.
final class ScrollViewController: UIViewController {
private var visibleTab: TabState = .overview {
didSet {
guard oldValue != visibleTab else { return }
switch visibleTab {
case .overview:
self.spacesTab.isHidden = true
self.overviewTab.isHidden = false
case .spaces:
self.spacesTab.isHidden = false
self.overviewTab.isHidden = true
}
}
}
enum TabState {
case overview
case spaces
}
private lazy var scrollView: UIScrollView = {
let view = UIScrollView(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .white
view.delegate = self
view.alwaysBounceVertical = true
return view
}()
private let contentStackView: UIStackView = {
let view = UIStackView(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
view.axis = .vertical
view.alignment = .fill
view.spacing = 8
view.distribution = .fill
return view
}()
private let tabSelectorView: UIStackView = {
let view = UIStackView(frame: .zero)
view.axis = .horizontal
view.distribution = .fillEqually
return view
}()
private let overviewTab: UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = .darkGray
view.heightAnchor.constraint(equalToConstant: 100).isActive = true
view.isHidden = false
return view
}()
private let spacesTab: UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = .lightGray
view.heightAnchor.constraint(equalToConstant: 780).isActive = true
view.isHidden = true
return view
}()
private let profileHeader = ScrollViewProfileHeaderView(frame: .zero)
private lazy var overviewTabButton = makeButton(title: "Overview")
private lazy var spacesTabButton = makeButton(title: "Spaces")
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
}
extension ScrollViewController: UIScrollViewDelegate { }
private extension ScrollViewController {
func configureUI() {
overviewTabButton.addTarget(self, action: #selector(showOverviewTab), for: .touchUpInside)
spacesTabButton.addTarget(self, action: #selector(showSpacesTab), for: .touchUpInside)
[overviewTabButton, spacesTabButton].forEach(tabSelectorView.addArrangedSubview)
profileHeader.translatesAutoresizingMaskIntoConstraints = false
tabSelectorView.translatesAutoresizingMaskIntoConstraints = false
[overviewTab, spacesTab].forEach(contentStackView.addArrangedSubview)
[profileHeader, tabSelectorView, contentStackView].forEach(scrollView.addSubview(_:))
view.addSubview(scrollView)
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
profileHeader.topAnchor.constraint(equalTo: scrollView.topAnchor),
profileHeader.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
profileHeader.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
tabSelectorView.topAnchor.constraint(equalTo: profileHeader.bottomAnchor),
tabSelectorView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
tabSelectorView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
contentStackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
contentStackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
contentStackView.topAnchor.constraint(equalTo: tabSelectorView.bottomAnchor, constant: 8),
contentStackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
contentStackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
])
}
func makeButton(title: String) -> UIButton {
let button = UIButton(type: .system)
button.setTitle(title, for: .normal)
button.backgroundColor = .lightGray
return button
}
#objc func showOverviewTab() {
visibleTab = .overview
}
#objc func showSpacesTab() {
visibleTab = .spaces
}
}
final class ScrollViewProfileHeaderView: UIView {
private let headerImage: UIImageView = {
let view = UIImageView(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
view.contentMode = .scaleAspectFill
view.clipsToBounds = true
view.backgroundColor = .systemTeal
return view
}()
private let profileCard: ProfileCardView = {
let view = ProfileCardView(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .purple
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
[headerImage, profileCard].forEach(addSubview(_:))
NSLayoutConstraint.activate([
headerImage.topAnchor.constraint(equalTo: topAnchor),
headerImage.leadingAnchor.constraint(equalTo: leadingAnchor),
headerImage.trailingAnchor.constraint(equalTo: trailingAnchor),
headerImage.heightAnchor.constraint(equalToConstant: 180),
profileCard.topAnchor.constraint(equalTo: headerImage.centerYAnchor),
profileCard.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: 48),
profileCard.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -32),
profileCard.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -48),
profileCard.heightAnchor.constraint(equalToConstant: 270),
])
}
required init?(coder: NSCoder) {
return nil
}
}
You will probably want to make some additional changes, but this might get you on your way.
In your visibleTab / didSet block, use UIView.animate() when you hide the spacesTab:
private var visibleTab: TabState = .overview {
didSet {
guard oldValue != visibleTab else { return }
switch self.visibleTab {
case .overview:
// set duration longer, such as 1.0, to clearly see the animation...
UIView.animate(withDuration: 0.3) {
self.spacesTab.isHidden = true
self.overviewTab.isHidden = false
}
case .spaces:
self.spacesTab.isHidden = false
self.overviewTab.isHidden = true
}
}
}

Change view with Segment View Control

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()

Custom Button Subviews not Showing

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

creating custom UITextfield

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