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)
Related
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),
])
}
}
I am trying to add an image to a subview. but whenever I run a simulation I cant see the image while I have label that shows up on the same view
let View:UIView = UIView()
let CheckImageView:UIImageView = UIImageView(image: UIImage(named: "Checked 1"))
view.addSubview(View)
View.backgroundColor = .white
View.translatesAutoresizingMaskIntoConstraints = false
View.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor,constant: -20).isActive = true
View.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true
View.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor,constant: 0).isActive = true
View.heightAnchor.constraint(equalToConstant: 200).isActive = true
View.layer.cornerRadius = 25
View.layer.shadowOpacity = 0.15
View.layer.shadowRadius = 20
View.layer.shadowOffset = .zero
View.layer.shadowColor = UIColor.black.cgColor
View.addSubview(CheckImageView)
CheckImageView.translatesAutoresizingMaskIntoConstraints = false
CheckImageView.heightAnchor.constraint(equalTo: CheckImageView.widthAnchor).isActive = true
CheckImageView.topAnchor.constraint(equalTo: View.topAnchor, constant: 30).isActive = true
CheckImageView.centerXAnchor.constraint(equalTo: View.centerXAnchor).isActive = true
CheckImageView.widthAnchor.constraint(equalToConstant: 50).isActive = true
It seems like your image size is smaller than expected.
Try to change your image width Anchor
CheckImageView.widthAnchor.constraint(equalToConstant: 100).isActive = true
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)
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()
}
}
Set programatacally autlo layout to UIView but not set height constraint. I can't identify what is issue.
let viewSep = UIView()
viewSep.backgroundColor = UIColor.red
viewSep.translatesAutoresizingMaskIntoConstraints = false
viewInner.addSubview(viewSep)
viewSep.leftAnchor.constraint(equalTo: viewInner.leftAnchor, constant: 10).isActive = true
viewSep.topAnchor.constraint(equalTo: lblDate.bottomAnchor, constant: 5).isActive = true
viewSep.rightAnchor.constraint(equalTo: viewInner.rightAnchor, constant: -10).isActive = true
viewSep.heightAnchor.constraint(equalToConstant: 21)