heightAnchor.constraint not change height of view - swift

I use this code:
func show(){
view.translatesAutoresizingMaskIntoConstraints = false
view.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
view.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
view.heightAnchor.constraint(equalToConstant: view.frame.height - 300).isActive = true
view.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
}
func hide(){
view.translatesAutoresizingMaskIntoConstraints = false
view.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
view.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
view.heightAnchor.constraint(equalToConstant: view.frame.height + 300).isActive = true
view.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
}
show function works fine, but hide function does not work and heightAnchor does not work.

First declare constraints
var heightArchonWhenShow = view.heightAnchor.constraint(equalToConstant: view.frame.height - 300)
var heightArchonWhenHide = view.heightAnchor.constraint(equalToConstant: view.frame.height + 300)
After init your constraints on ViewDidLoad
func setConstraints(){
view.translatesAutoresizingMaskIntoConstraints = false
view.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
view.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
view.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
heightArchonWhenShow.isActive = true
}
And simple active them , don't overwrite. Like this:
func show(){
heightArchonWhenShow.isActive = true
heightArchonWhenHide.isActive = false
}
func hide(){
heightArchonWhenShow.isActive = false
heightArchonWhenHide.isActive = true
}
If u want u can also animate changes, like that :
func hide(){
heightArchonWhenShow.isActive = false
heightArchonWhenHide.isActive = true
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}

I recommend you to setup your constraint in a different function like maybe setup() and store them in some variable that you can modify after, I'll show you an example
var constraint: NSLayoutConstraint?
func setup() {
constraint = view.heightAnchor.constraint(equalToConstant: view.frame.height)
}
func show() {
if constraint != nil {
constraint!.constant = constraint!.constant + 300
}
}
func hide() {
if constraint != nil {
constraint!.constant = constraint!.constant - 300
}
}

You need only 1 var
var heightCon = view.heightAnchor.constraint(equalToConstant: view.frame.height - 300)
heightCon.isActive = true
Then manage it's constant value
func showOrHide(_ te:Bool){
heightCon.constant = te ? view.frame.height - 300 : view.frame.height + 300
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}

Related

Can't set specific spacing when using UICollectionViewFlowLayout.automaticSize

I'm trying to recreate pinterest UI, basically auto height for cell base on photo height.
I'm already able to make it height dynamic but the spacing for each cell is weird, it keeps auto set my cell spacing like this:
This is the code I used for collectionView:
func setupCollectionView() {
let layout2: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let width = view.frame.size.width * 0.9
collectionViewParent = UICollectionView(frame: .zero, collectionViewLayout: layout2)
collectionViewParent.backgroundColor = .red
view.addSubview(collectionViewParent)
collectionViewParent.translatesAutoresizingMaskIntoConstraints = false
collectionViewParent.dataSource = self
collectionViewParent.delegate = self
collectionViewParent.register(LoansCell.self, forCellWithReuseIdentifier: "cellLoan")
collectionViewParent.register(FirstRowCollectionViewCell.self, forCellWithReuseIdentifier: "cellFirst")
collectionViewParent.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
collectionViewParent.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20).isActive = true
collectionViewParent.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
collectionViewParent.widthAnchor.constraint(equalToConstant: width).isActive = true
if let flowLayout = collectionViewParent.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
flowLayout.minimumLineSpacing = 5
flowLayout.minimumInteritemSpacing = 5
flowLayout.scrollDirection = .vertical
}
}
For the cell, I just put everything in a UIView:
addSubview(view) //view is a uiview
view.translatesAutoresizingMaskIntoConstraints = false
view.topAnchor.constraint(equalTo: topAnchor).isActive = true
view.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
view.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
view.widthAnchor.constraint(equalToConstant: ((UIScreen.main.bounds.width * 0.8)/2)).isActive = true
view.addSubview(labelEligible)
labelEligible.topAnchor.constraint(equalTo: view.topAnchor, constant: 10).isActive = true
labelEligible.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
view.addSubview(imageView)
imageView.topAnchor.constraint(equalTo: labelEligible.bottomAnchor, constant: 20).isActive = true
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 100).isActive = true
imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
addSubview(labelPrice)
labelPrice.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 20).isActive = true
labelPrice.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
view.addSubview(labelDescription)
labelDescription.topAnchor.constraint(equalTo: labelPrice.bottomAnchor, constant: 20).isActive = true
labelDescription.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
labelDescription.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
view.addSubview(labelPayUpTo)
labelPayUpTo.topAnchor.constraint(equalTo: labelDescription.bottomAnchor, constant: 20).isActive = true
labelPayUpTo.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10).isActive = true
labelPayUpTo.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
let finalConstraint = labelPayUpTo.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10)
finalConstraint.isActive = true
finalConstraint.priority = UILayoutPriority(rawValue: 999)

UITextFields keyboard not appearing in UIScrollview

I have 2 textfields as subViews of a contentView and the contentView is a subView of a scrollView. The textfields appear with no issue.But the problem I am having is when I tap or select the textfield to enter text neither a keyboard appears or the blue cursor, the textfields placeholder remains there. Is there something wrong with my constraints? How can I get the keyboard to appear and edit the text?
class SignInViewController: UIViewController {
private let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
private let contentView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let emailOrPhoneTextField: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = "Email or Phone Number"
textField.textAlignment = .center
textField.backgroundColor = .red
return textField
}()
private let passwordTextField: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = "Password"
textField.backgroundColor = .yellow
return textField
}()
override func viewDidLoad() {
super.viewDidLoad()
setupScrollView()
setupTextFields()
}
}
extension SignInViewController{
private func setupScrollView(){
view.addSubview(scrollView)
scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
scrollView.addSubview(contentView)
contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
}
private func setupTextFields(){
contentView.addSubview(emailOrPhoneTextField)
contentView.addSubview(passwordTextField)
emailOrPhoneTextField.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
emailOrPhoneTextField.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 25).isActive = true
emailOrPhoneTextField.widthAnchor.constraint(equalTo: contentView.widthAnchor).isActive = true
emailOrPhoneTextField.heightAnchor.constraint(equalToConstant: 44).isActive = true
passwordTextField.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
passwordTextField.topAnchor.constraint(equalTo: emailOrPhoneTextField.bottomAnchor, constant: 25).isActive = true
passwordTextField.widthAnchor.constraint(equalTo: contentView.widthAnchor).isActive = true
passwordTextField.heightAnchor.constraint(equalToConstant: 44).isActive = true
}
}
Try this and check if it works:
extension ViewController{
private func setupScrollView(){
view.addSubview(scrollView)
scrollView.addSubview(contentView)
contentView.addSubview(emailOrPhoneTextField)
contentView.addSubview(passwordTextField)
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor)
])
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.rightAnchor.constraint(equalTo: scrollView.rightAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
contentView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
contentView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
])
NSLayoutConstraint.activate([
emailOrPhoneTextField.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 50),
emailOrPhoneTextField.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
emailOrPhoneTextField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
])
NSLayoutConstraint.activate([
passwordTextField.topAnchor.constraint(equalTo: emailOrPhoneTextField.bottomAnchor, constant: 25),
passwordTextField.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
passwordTextField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
])
}
}

Use slider to manipulate anchors constrained by a multiplier in swift

I want to use a slider to make pic imageview smaller. Right now its in its max size. The slider should be able to make it smaller. When I use the slider the pic does decrease but I cant increase it, I can only decrease it. This is a pic of what I am looking to do.
My code is in all code no storyboard used.
import UIKit
class ViewController: UIViewController {
var sd = UISlider()
var pic = UIImageView()
var start = [NSLayoutConstraint]()
var change = [NSLayoutConstraint]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
[sd,pic].forEach{
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
$0.backgroundColor = .systemOrange
}
pic.topAnchor.constraint(equalTo: view.topAnchor, constant: 12).isActive = true
pic.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
pic.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
start = [
pic.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
pic.heightAnchor.constraint(equalTo: view.layoutMarginsGuide.heightAnchor, multiplier: 1/2),
sd.trailingAnchor.constraint(equalTo: view.centerXAnchor, constant :150),
sd.topAnchor.constraint(equalTo: view.centerYAnchor, constant : +250),
sd.widthAnchor.constraint(equalToConstant: 150),
sd.heightAnchor.constraint(equalToConstant: 40)
]
NSLayoutConstraint.activate(start)
sd.addTarget(self, action: #selector(moveRight), for: .allTouchEvents)
}
#objc func moveRight(_ sender: UISlider) {
NSLayoutConstraint.deactivate(start)
let jessicaAlba = 300 + ( 300 * CGFloat(sd.value) )
print(CGFloat(sd.value))
pic.topAnchor.constraint(equalTo: view.topAnchor, constant: -jessicaAlba).isActive = true
pic.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: jessicaAlba).isActive = true
pic.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -jessicaAlba).isActive = true
start = [
pic.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
pic.heightAnchor.constraint(equalTo: view.layoutMarginsGuide.heightAnchor, multiplier: 1/2),
sd.trailingAnchor.constraint(equalTo: view.centerXAnchor, constant :150),
sd.topAnchor.constraint(equalTo: view.centerYAnchor, constant : +250),
sd.widthAnchor.constraint(equalToConstant: 100),
sd.heightAnchor.constraint(equalToConstant: 40)
]
NSLayoutConstraint.activate (start)
}
}
Apologies for the very crude code, but this works:
var myView = UIView()
var topConstraint: NSLayoutConstraint!
var bottomConstraint: NSLayoutConstraint!
var leadingConstraint: NSLayoutConstraint!
var trailingConstraint: NSLayoutConstraint!
var jessicaAlba:Float = 50
var slider = UISlider()
override func viewDidLoad() {
super.viewDidLoad()
myView.translatesAutoresizingMaskIntoConstraints = false
myView.backgroundColor = UIColor.orange
view.addSubview(myView)
slider.translatesAutoresizingMaskIntoConstraints = false
slider.minimumValue = 50
slider.maximumValue = 200
slider.setValue(jessicaAlba, animated: false)
slider.addTarget(self, action: #selector(changeSize), for: .valueChanged)
view.addSubview(slider)
slider.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
slider.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
slider.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10).isActive = true
topConstraint = myView.topAnchor.constraint(equalTo: view.topAnchor, constant: CGFloat(jessicaAlba))
topConstraint.isActive = true
bottomConstraint = myView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: CGFloat(-jessicaAlba))
bottomConstraint.isActive = true
leadingConstraint = myView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: CGFloat(jessicaAlba))
leadingConstraint.isActive = true
trailingConstraint = myView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: CGFloat(-jessicaAlba))
trailingConstraint.isActive = true
}
#objc func changeSize() {
jessicaAlba = slider.value
topConstraint.constant = CGFloat(jessicaAlba)
bottomConstraint.constant = CGFloat(-jessicaAlba)
leadingConstraint.constant = CGFloat(jessicaAlba)
trailingConstraint.constant = CGFloat(-jessicaAlba)
}
The main thing is to:
declare the specific constraints you want to change
set isActive = true in a separate line (I know, stupid but the compiler doesn't recognize the NSLayoutConstraint type and will not build if you do it on a single line
change the constraint as needed

Multiple buttons triggered with one function programmaticaly swift

Tried to summarize my code. Problem is i am getting "newCalculator[2861:53607] -[UIButton buttonClicked:]: unrecognized selector sent to instance 0x7fd912651e50" error and trying to understand what i need to do? I researched some solutions changing selector syntax however still this problem persists. What i want is; inside a stackview i add multiple buttons with an order and all buttons should call same function when they are clicked.
o//
// ViewController.swift
// newCalculator
//
// Created by taylank on 17.10.2019.
// Copyright © 2019 TKT. All rights reserved.
//
import UIKit
var stackViews = [UIStackView]()
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Layer 1
let containerStackView1 = UIStackView()
containerStackView1.translatesAutoresizingMaskIntoConstraints = false
containerStackView1.axis = .vertical
containerStackView1.distribution = .fillEqually
containerStackView1.spacing = 1
//Layer 2
let topHalfView2 = UIView()
topHalfView2.translatesAutoresizingMaskIntoConstraints = false
topHalfView2.backgroundColor = .white
let botHalfView2 = UIView()
botHalfView2.translatesAutoresizingMaskIntoConstraints = false
//Layer 3
let topLabel3 = UILabel()
topLabel3.translatesAutoresizingMaskIntoConstraints = false
topLabel3.text = "0"
topLabel3.font = UIFont.boldSystemFont(ofSize: 40)
let containerStackView3 = UIStackView()
containerStackView3.translatesAutoresizingMaskIntoConstraints = false
containerStackView3.axis = .vertical
containerStackView3.distribution = .fillEqually
containerStackView3.spacing = 1
//Layer 4
stackViews = createStackViews(from: 0, to: 4, align: "h")
let yamaView = UIView()
yamaView.translatesAutoresizingMaskIntoConstraints = false
yamaView.backgroundColor = .black
//ADDING VIEWS TO SCENE .VIEW->Contstckview1->Top-BotHalfView->contstckview2-ResultLabel->horzstackviews
containerStackView1.addArrangedSubview(topHalfView2)
containerStackView1.addArrangedSubview(botHalfView2)
view.addSubview(containerStackView1)
topHalfView2.addSubview(topLabel3)
botHalfView2.addSubview(containerStackView3)
containerStackView3.addArrangedSubview(stackViews[0])
view.addSubview(yamaView)
//stackViews[0].topAnchor.constraint(equalTo: containerStackView3.topAnchor, constant: 0).isActive = true
for a in 1...stackViews.count-1{
containerStackView3.addArrangedSubview(stackViews[a])
// stackViews[a].leadingAnchor.constraint(equalTo: stackViews[0].leadingAnchor, constant: 0).isActive = true
// stackViews[a].trailingAnchor.constraint(equalTo: stackViews[0].trailingAnchor, constant: 0).isActive = true
}
//stackViews[0].leadingAnchor.constraint(equalTo: containerStackView3.leadingAnchor, constant: 0).isActive = true
// stackViews[0].trailingAnchor.constraint(equalTo: containerStackView3.trailingAnchor, constant: 0).isActive = true
//Uiheight--v:?--uibottom--uifillequ
//ConstraintsStackView1
containerStackView1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
containerStackView1.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
containerStackView1.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
containerStackView1.heightAnchor.constraint(equalToConstant: view.frame.height).isActive = true
//TopHalfView2
topHalfView2.topAnchor.constraint(equalTo: containerStackView1.topAnchor, constant: 0).isActive = true
topHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
topHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
// topHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true
//creates problem conflicts with other constraint fill equally?
//BotHalfView2
botHalfView2.bottomAnchor.constraint(equalTo: containerStackView1.bottomAnchor, constant: 0).isActive = true
botHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
botHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
// botHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true
//topLabel3
topLabel3.bottomAnchor.constraint(equalTo: topHalfView2.bottomAnchor, constant: 0).isActive = true
topLabel3.trailingAnchor.constraint(equalTo: topHalfView2.trailingAnchor, constant: -5).isActive = true
//ConstraintsStackView3
containerStackView3.leadingAnchor.constraint(equalTo: botHalfView2.leadingAnchor, constant: 0).isActive = true
containerStackView3.trailingAnchor.constraint(equalTo: botHalfView2.trailingAnchor, constant: 0).isActive = true
containerStackView3.topAnchor.constraint(equalTo: botHalfView2.topAnchor, constant: 0).isActive = true
containerStackView3.bottomAnchor.constraint(equalTo: botHalfView2.bottomAnchor, constant: 0).isActive = true
//constraint button
stackViews[4].arrangedSubviews[2].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[1].widthAnchor,multiplier: 1).isActive = true //sonbutton bir yandakine
stackViews[4].arrangedSubviews[1].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[0].widthAnchor,multiplier: 0.5).isActive = true // ortadaki buton en soldakine
yamaView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
yamaView.topAnchor.constraint(equalTo: stackViews[4].bottomAnchor).isActive = true
yamaView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
yamaView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
}
}
func createButtons(_ named: String...)->[UIButton]{
var c = 0
return named.map { name in
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(name, for: .normal)
button.backgroundColor = UIColor.gray
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 1
button.addTarget(button, action: #selector(buttonClicked) ,for:.touchUpInside)
return button
}
}
#objc func buttonClicked(_ sender:UIButton){
print("clicked")
}
func createStackViews(from x: Int,to y:Int, align type: String)->[UIStackView]{
// use tag instead of name---
//use dictionary..keys name values
if (type == "v"){
for a in x...y{
let stackVertical = UIStackView()
stackVertical.translatesAutoresizingMaskIntoConstraints = false
stackVertical.axis = .vertical
stackVertical.spacing = 1
stackVertical.distribution = .fillEqually
stackVertical.tag = a
}
}
else if(type=="h"){
var counter = 0
for a in x...y{
counter += 1
switch counter{
case 1: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("Clear","+/-","%","÷"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 90+a
stackViews.append(stackHorizontal)
case 2: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("7","8","9","x"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 100 + a
stackViews.append(stackHorizontal)
case 3: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("4","5","6","-"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 110+a
stackViews.append(stackHorizontal)
case 4: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("1","2","3","+"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 120 + a
stackViews.append(stackHorizontal)
case 5: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("0",",","="))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillProportionally
stackHorizontal.tag = 130 + a
stackViews.append(stackHorizontal)
default:
break
}
}
return stackViews
}
return [UIStackView.init()]
}
------------SOLUTION----------
All of the functions are inside the viewcontroller class
class ViewController: UIViewController {
override func viewDidLoad() {
stackViews = createStackViews(from: 0, to: 4, align: "h")
}
func createButtons(_ named: String...)->[UIButton]{
//codes
button.addTarget(self, action: #selector(buttonClicked) ,for:.touchUpInside)
//codes
}
#objc func buttonClicked(_ sender:UIButton){
print("clicked")
}
func createStackViews(from x: Int,to y:Int, align type: String)->[UIStackView]{
//codes
UIStackView(arrangedSubviews:createButtons("Clear","+/-","%","÷"))
//codes
}
}
You have several problems:
Your selector needs to be selector(buttonClicked(:)), so
button.addTarget(self, action: #selector(buttonClicked(:)) ,for:.touchUpInside)
Your functions buttonClicked(_:) and createButtons() need to be inside your view controller class. As it is, buttonClicked(_:) is a global function, which means it can't be part of a target/action. (Action methods need to be inside a target object (usually the view controller that owns the button.)
Replace
button.addTarget(button, action: "buttonClicked:" ,for:.touchUpInside)
with
button.addTarget(self, action: #selector(buttonClicked) ,for:.touchUpInside)
#objc func buttonClicked(_ sender:UIButton){
import UIKit
var stackViews = [UIStackView]()
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Layer 1
let containerStackView1 = UIStackView()
containerStackView1.translatesAutoresizingMaskIntoConstraints = false
containerStackView1.axis = .vertical
containerStackView1.distribution = .fillEqually
containerStackView1.spacing = 1
//Layer 2
let topHalfView2 = UIView()
topHalfView2.translatesAutoresizingMaskIntoConstraints = false
topHalfView2.backgroundColor = .white
let botHalfView2 = UIView()
botHalfView2.translatesAutoresizingMaskIntoConstraints = false
//Layer 3
let topLabel3 = UILabel()
topLabel3.translatesAutoresizingMaskIntoConstraints = false
topLabel3.text = "0"
topLabel3.font = UIFont.boldSystemFont(ofSize: 40)
let containerStackView3 = UIStackView()
containerStackView3.translatesAutoresizingMaskIntoConstraints = false
containerStackView3.axis = .vertical
containerStackView3.distribution = .fillEqually
containerStackView3.spacing = 1
//Layer 4
stackViews = createStackViews(from: 0, to: 4, align: "h")
let yamaView = UIView()
yamaView.translatesAutoresizingMaskIntoConstraints = false
yamaView.backgroundColor = .black
//ADDING VIEWS TO SCENE .VIEW->Contstckview1->Top-BotHalfView->contstckview2-ResultLabel->horzstackviews
containerStackView1.addArrangedSubview(topHalfView2)
containerStackView1.addArrangedSubview(botHalfView2)
view.addSubview(containerStackView1)
topHalfView2.addSubview(topLabel3)
botHalfView2.addSubview(containerStackView3)
containerStackView3.addArrangedSubview(stackViews[0])
view.addSubview(yamaView)
//stackViews[0].topAnchor.constraint(equalTo: containerStackView3.topAnchor, constant: 0).isActive = true
for a in 1...stackViews.count-1{
containerStackView3.addArrangedSubview(stackViews[a])
// stackViews[a].leadingAnchor.constraint(equalTo: stackViews[0].leadingAnchor, constant: 0).isActive = true
// stackViews[a].trailingAnchor.constraint(equalTo: stackViews[0].trailingAnchor, constant: 0).isActive = true
}
//stackViews[0].leadingAnchor.constraint(equalTo: containerStackView3.leadingAnchor, constant: 0).isActive = true
// stackViews[0].trailingAnchor.constraint(equalTo: containerStackView3.trailingAnchor, constant: 0).isActive = true
//Uiheight--v:?--uibottom--uifillequ
//ConstraintsStackView1
containerStackView1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
containerStackView1.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
containerStackView1.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
containerStackView1.heightAnchor.constraint(equalToConstant: view.frame.height).isActive = true
//TopHalfView2
topHalfView2.topAnchor.constraint(equalTo: containerStackView1.topAnchor, constant: 0).isActive = true
topHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
topHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
// topHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true
//creates problem conflicts with other constraint fill equally?
//BotHalfView2
botHalfView2.bottomAnchor.constraint(equalTo: containerStackView1.bottomAnchor, constant: 0).isActive = true
botHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
botHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
// botHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true
//topLabel3
topLabel3.bottomAnchor.constraint(equalTo: topHalfView2.bottomAnchor, constant: 0).isActive = true
topLabel3.trailingAnchor.constraint(equalTo: topHalfView2.trailingAnchor, constant: -5).isActive = true
//ConstraintsStackView3
containerStackView3.leadingAnchor.constraint(equalTo: botHalfView2.leadingAnchor, constant: 0).isActive = true
containerStackView3.trailingAnchor.constraint(equalTo: botHalfView2.trailingAnchor, constant: 0).isActive = true
containerStackView3.topAnchor.constraint(equalTo: botHalfView2.topAnchor, constant: 0).isActive = true
containerStackView3.bottomAnchor.constraint(equalTo: botHalfView2.bottomAnchor, constant: 0).isActive = true
//constraint button
stackViews[4].arrangedSubviews[2].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[1].widthAnchor,multiplier: 1).isActive = true //sonbutton bir yandakine
stackViews[4].arrangedSubviews[1].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[0].widthAnchor,multiplier: 0.5).isActive = true // ortadaki buton en soldakine
yamaView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
yamaView.topAnchor.constraint(equalTo: stackViews[4].bottomAnchor).isActive = true
yamaView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
yamaView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
}
func createButtons(_ named: String...)->[UIButton]{
var c = 0
return named.map { name in
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(name, for: .normal)
button.backgroundColor = UIColor.gray
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 1
button.addTarget(self, action: #selector(buttonClicked) ,for:.touchUpInside)
return button
}
}
#objc func buttonClicked(_ sender:UIButton){
print("clicked")
}
func createStackViews(from x: Int,to y:Int, align type: String)->[UIStackView]{
// use tag instead of name---
//use dictionary..keys name values
if (type == "v"){
for a in x...y{
let stackVertical = UIStackView()
stackVertical.translatesAutoresizingMaskIntoConstraints = false
stackVertical.axis = .vertical
stackVertical.spacing = 1
stackVertical.distribution = .fillEqually
stackVertical.tag = a
}
}
else if(type=="h"){
var counter = 0
for a in x...y{
counter += 1
switch counter{
case 1: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("Clear","+/-","%","÷"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 90+a
stackViews.append(stackHorizontal)
case 2: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("7","8","9","x"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 100 + a
stackViews.append(stackHorizontal)
case 3: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("4","5","6","-"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 110+a
stackViews.append(stackHorizontal)
case 4: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("1","2","3","+"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 120 + a
stackViews.append(stackHorizontal)
case 5: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("0",",","="))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillProportionally
stackHorizontal.tag = 130 + a
stackViews.append(stackHorizontal)
default:
break
}
}
return stackViews
}
return [UIStackView.init()]
}
}

UIImage Aspect Fill and clipsToBounds

I want to set an image to a UIImage, but as soon as I set it it the UIImageView gets bigger and goes over other elements.
There is a solution provided here:
Crop UIImage to fit a frame image
But I can not get it to work, I set the properties like in the solution provided.
Maybe somebody can have a look and help me:
Without setting the image:
After setting the image:
class Cell: UICollectionViewCell, CollectionViewCellConfigurable {
var image = UIImageView()
var dateDay = UILabel()
var dateMonth = UILabel()
var title = UILabel()
lazy private var dateContainer: UIView = {
let v = UIView()
v.sv(dateDay, dateMonth)
dateDay.heightAnchor.constraint(equalTo: self.dateMonth.heightAnchor, multiplier: 1).isActive = true
dateDay.leadingAnchor.constraint(equalTo: v.leadingAnchor, constant: 5).isActive = true
dateDay.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: -5).isActive = true
dateDay.topAnchor.constraint(equalTo: v.topAnchor, constant: 15).isActive = true
dateDay.bottomAnchor.constraint(equalTo: dateMonth.topAnchor, constant: -5).isActive = true
dateMonth.heightAnchor.constraint(equalTo: self.dateDay.heightAnchor, multiplier: 1).isActive = true
dateMonth.leadingAnchor.constraint(equalTo: v.leadingAnchor, constant: 5).isActive = true
dateMonth.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: -5).isActive = true
dateMonth.topAnchor.constraint(equalTo: dateDay.bottomAnchor, constant: 5).isActive = true
// dateMonth.bottomAnchor.constraint(greaterThanOrEqualTo: v.bottomAnchor, constant: -5).isActive = true
return v
}()
lazy private var container: UIView = {
return UIView()
}()
func configureCellAtIndexPath(item: Journaling) {
self.image.image = UIImage.baliBeach
self.image.backgroundColor = .green
self.dateDay.text = "16"
self.dateMonth.text = "May"
self.title.text = "Text visible"
}
override init(frame: CGRect) {
super.init(frame:frame)
setUpLayout()
additionalSetUp()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func additionalSetUp() {
backgroundColor = .clear
let colorText: UIColor = .grau
dateDay.textColor = colorText
dateMonth.textColor = colorText
title.textColor = colorText
dateDay.textAlignment = .center
dateMonth.textAlignment = .center
title.textAlignment = .center
image.contentMode = .scaleAspectFill
image.clipsToBounds = true
image.autoresizesSubviews = true
}
func setUpLayout() {
sv(dateContainer, container)
container.sv(image,title)
dateContainer.widthAnchor.constraint(equalToConstant: 45).isActive = true
// dateContainer.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.15).isActive = true
dateContainer.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
dateContainer.trailingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
dateContainer.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
dateContainer.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
// container.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.5).isActive = true
container.leadingAnchor.constraint(equalTo: dateContainer.trailingAnchor, constant: 0).isActive = true
container.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
container.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
container.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
image.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 5).isActive = true
image.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -5).isActive = true
image.topAnchor.constraint(equalTo: self.topAnchor, constant: 15).isActive = true
image.bottomAnchor.constraint(equalTo: title.topAnchor, constant: -5).isActive = true
title.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
title.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: 0).isActive = true
title.topAnchor.constraint(equalTo: image.bottomAnchor, constant: 5).isActive = true
title.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: 0).isActive = true
}
}
You need to higher vertical compression priority of the title label as the imageView is equal it = 750 , so it occupies the space
title.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 751), for: .vertical)