Add UILabel as subview of UITextField on top - ios

I am in the process of implementing a UILabel as a subview of a UITextField which will be shown right above the UITextField itself. The UITextField has a rounded border and what I would like to achieve is the UILabel to be shown over the border.
Everything currently works as expected, but the UILabel is drawn behind the border of the UITextField. I want it to go "over" (above) the border so the white backgroundColor would be shown above part of the border and make the text more easily readible.
var priceTextField: CustomTextField = {
let priceTextField = CustomTextField()
priceTextField.layer.cornerRadius = 10.0
priceTextField.layer.borderWidth = 1.0
priceTextField.layer.borderColor = UIColor.darkGray.cgColor
priceTextField.translatesAutoresizingMaskIntoConstraints = false
priceTextField.font = UIFont.systemFont(ofSize: 15)
priceTextField.textColor = .black
priceTextField.text = "0"
priceTextField.suffix = "EUR"
priceTextField.suffixTextColor = .darkGray
priceTextField.suffixSpacing = 2.0
priceTextField.textAlignment = .center
priceTextField.labelText = "Price"
return priceTextField
}()
In my CustomTextField class (subclass of UITextField):
public var labelText: String?
var topLabel: UILabel = {
let topLabel = UILabel()
topLabel.translatesAutoresizingMaskIntoConstraints = false
topLabel.textAlignment = .center
topLabel.font = UIFont.systemFont(ofSize: 12)
topLabel.textColor = .lightGray
topLabel.backgroundColor = .white
topLabel.numberOfLines = 1
return topLabel
}()
func setupLabel() {
self.addSubview(topLabel)
topLabel.centerYAnchor.constraint(equalTo: self.topAnchor).isActive = true
topLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20).isActive = true
topLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -20).isActive = true
topLabel.text = labelText
}
I call setupLabel() at the end of the draw(_ rect: CGRect) method of UITextField (because I work with this to show the EUR sign always behind the entered value).
I have tried to play around with bringSubviewToFront and changing the zPosition of the layer of the UILabel, without success.
It now looks like this:
How can I bring the text "above" the border on the top?
EDIT: Tried Sh_Khan's solution, but it's still hidden behind the border.
import Foundation
import UIKit
public class CustomTextView: UIView, UITextFieldDelegate {
public var labelText: String?
var customTextField: CustomTextField = {
let customTextField = CustomTextField()
customTextField.translatesAutoresizingMaskIntoConstraints = false
customTextField.font = UIFont.systemFont(ofSize: 15)
customTextField.textColor = .black
customTextField.textAlignment = .center
customTextField.text = "0"
customTextField.suffix = "EUR"
customTextField.suffixTextColor = .lightGray
customTextField.suffixSpacing = 2.0
return customTextField
}()
var topLabel: UILabel = {
let topLabel = UILabel()
topLabel.translatesAutoresizingMaskIntoConstraints = false
topLabel.font = UIFont.systemFont(ofSize: 12)
topLabel.textColor = .darkGray
topLabel.numberOfLines = 1
topLabel.backgroundColor = .red
topLabel.textAlignment = .center
return topLabel
}()
override public init(frame: CGRect) {
super.init(frame: frame)
setupBorders()
}
public override func layoutSubviews() {
setupViews()
}
func setupBorders() {
self.layer.cornerRadius = 10.0
self.layer.borderColor = UIColor.lightGray.cgColor
self.layer.borderWidth = 1.0
}
func setupViews() {
addSubview(topLabel)
// insertSubview(topLabel, aboveSubview: customTextField)
insertSubview(customTextField, belowSubview: topLabel)
customTextField.topAnchor.constraint(equalTo: topAnchor).isActive = true
customTextField.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
customTextField.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
customTextField.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
topLabel.centerYAnchor.constraint(equalTo: topAnchor).isActive = true
topLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 10).isActive = true
topLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10).isActive = true
topLabel.text = labelText
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupViews()
}
}

You can try to organize it by creating a UIView subclass , so everything appear properly in it's order of adding
class CustomView: UIView {
var priceTextField: CustomTextField = {
let priceTextField = CustomTextField()
priceTextField.layer.cornerRadius = 10.0
priceTextField.layer.borderWidth = 1.0
priceTextField.layer.borderColor = UIColor.darkGray.cgColor
priceTextField.translatesAutoresizingMaskIntoConstraints = false
priceTextField.font = UIFont.systemFont(ofSize: 15)
priceTextField.textColor = .black
priceTextField.text = "0"
priceTextField.suffix = "EUR"
priceTextField.suffixTextColor = .darkGray
priceTextField.suffixSpacing = 2.0
priceTextField.textAlignment = .center
priceTextField.labelText = "Price"
return priceTextField
}()
var topLabel: UILabel = {
let topLabel = UILabel()
topLabel.translatesAutoresizingMaskIntoConstraints = false
topLabel.textAlignment = .center
topLabel.font = UIFont.systemFont(ofSize: 12)
topLabel.textColor = .lightGray
topLabel.backgroundColor = .white
topLabel.numberOfLines = 1
return topLabel
}()
var lableStr:String?
init(frame: CGRect,lblTex:String) {
super.init(frame: frame)
lableStr = lblTex
createSubviews()
}
override init(frame: CGRect) {
super.init(frame: frame)
createSubviews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
createSubviews()
}
func createSubviews() {
// all the layout code from above
// add the textfield then the label and set constraints properly
}
}

According to the Apple specification: It is composited above the receiver’s contents and sublayers.
So, the border will always be above all subviews, even if one brings the subview to the front and so on.
So one needs to make a background view to fake the border.
similar to Stackoverflow Question
Example:
Here self is "TextField"
activeborderView is "UiView"
activeborderView.frame = CGRect.init(x: -1, y: -1, width: self.frame.size.width+2, height: self.frame.size.height+2)
activeborderView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(activeborderView)
activeborderView.topAnchor.constraint(equalTo: self.topAnchor, constant:-1).isActive = true // Place our label 10 pts above the text field
activeborderView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: -1).isActive=true
activeborderView.heightAnchor.constraint(equalToConstant: self.frame.size.height+2).isActive=true
activeborderView.widthAnchor.constraint(equalToConstant: self.frame.size.width+2).isActive=true
activeborderView.layer.borderWidth = 3
activeborderView.layer.borderColor = CustomColor.blue().cgColor
activeborderView.layer.cornerRadius = 5
activeborderView.backgroundColor = .white
self.sendSubviewToBack(activeborderView)
self.setNeedsDisplay()

Related

Cannot edit textField and textView

I have a simple class that designs the display of title and content and other controller class that displays the content after fetching it from coredata, every thing works fine but the fields are not editable, where am i making the error,
repeating the same para as the editor was asking to made more words *
I have a simple class that designs the display of title and content and other controller class that displays the content after fetching it from coredata, every thing works fine but the fields are not editable, where am i making the error,
Design Class
import UIKit
class UpdateNoteDesignView: UIView {
let notesUpdateTitle = UITextField()
let notesUpdateContent = UITextView()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func commonInit() {
let updateStack = UIStackView()
updateStack.axis = .vertical
updateStack.alignment = .top
updateStack.distribution = .fill
updateStack.spacing = 5
notesUpdateTitle.translatesAutoresizingMaskIntoConstraints = false
notesUpdateContent.translatesAutoresizingMaskIntoConstraints = false
notesUpdateTitle.widthAnchor.constraint(greaterThanOrEqualToConstant: 150).isActive = true
notesUpdateContent.widthAnchor.constraint(greaterThanOrEqualToConstant: 300).isActive = true
notesUpdateTitle.heightAnchor.constraint(equalToConstant: 30).isActive = true
notesUpdateContent.heightAnchor.constraint(greaterThanOrEqualToConstant: 300).isActive = true
notesUpdateTitle.font = UIFont(name: "Arial", size: 30)
notesUpdateContent.font = UIFont(name: "Arial", size: 30)
notesUpdateContent.layer.cornerRadius = 5
notesUpdateContent.layer.borderWidth = 2
notesUpdateTitle.layer.borderWidth = 2
notesUpdateTitle.layer.cornerRadius = 5
updateStack.translatesAutoresizingMaskIntoConstraints = false
updateStack.addArrangedSubview(notesUpdateTitle)
updateStack.addArrangedSubview(notesUpdateContent)
addSubview(updateStack)
updateStack.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
updateStack.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20).isActive = true
}
}
Controller Class
import UIKit
class UpdateNotesController: UIViewController {
let updateDesign = UpdateNoteDesignView()
var note: Note?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
view.addSubview(updateDesign)
updateDesign.notesUpdateTitle.text = note?.title
updateDesign.notesUpdateContent.text = note?.contents
}
}
Here, the issue is that frame is not set for your view. Try to add background color to UpdateNoteDesignView. You will not able to see it.
Please add frame/constraint for UpdateNoteDesignView as shown here and make changes according to your requirement.
class ViewController: UIViewController {
var updateDesign: UpdateNoteDesignView!
// var note: Note?
override func viewDidLoad() {
super.viewDidLoad()
updateDesign = UpdateNoteDesignView()//frame: CGRect(x: 0, y: 0, width: 200, height: 260))
view.backgroundColor = UIColor.white
view.addSubview(updateDesign)
updateDesign.translatesAutoresizingMaskIntoConstraints = false
updateDesign.heightAnchor.constraint(equalToConstant: 450).isActive = true
updateDesign.widthAnchor.constraint(equalToConstant: 350).isActive = true
updateDesign.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
updateDesign.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
updateDesign.notesUpdateTitle.text = "Stack overflow"
updateDesign.notesUpdateContent.text = "Developer"
}
}

How to toggle hide imageView from subclassing UIButton

I have a subclass of UIButton and it have an initialiser that accept a name and boolean. I have a function to toggle the hide and show imageView, and my auto layout set to when imageView hidden the anchor move into another imageView. I use the content hugging priority programmatically in this. so here is my code, can you show me why my uiimageView not hiding.
// This is in my subclass of UIButton
let profileLbl = UILabel()
let badgeImageView = UIImageView()
let rightArrowImageView = UIImageView()
var isHiddenBadge = false
var visibleProfileTrailingConstraint: NSLayoutConstraint!
var hiddenProfileTrailingConstraint: NSLayoutConstraint!
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
configure()
}
init(name: String, isBadgeHidden: Bool = false) {
super.init(frame: .zero)
profileLbl.text = name
profileLbl.font = UIFont(name: "NunitoSans-SemiBold", size: 16)
profileLbl.textColor = #colorLiteral(red: 0.2, green: 0.2, blue: 0.2, alpha: 1)
isHiddenBadge = isBadgeHidden
toggleHide(badge: isHiddenBadge)
configure()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func configure() {
translatesAutoresizingMaskIntoConstraints = false
[profileLbl, badgeImageView, rightArrowImageView].forEach({ v in
v.translatesAutoresizingMaskIntoConstraints = false
addSubview(v)
})
visibleProfileTrailingConstraint = profileLbl.trailingAnchor.constraint(equalTo: badgeImageView.leadingAnchor, constant: -5)
hiddenProfileTrailingConstraint = profileLbl.trailingAnchor.constraint(equalTo: rightArrowImageView.leadingAnchor, constant: -5)
visibleProfileTrailingConstraint.priority = .defaultHigh
hiddenProfileTrailingConstraint.priority = .defaultLow
badgeImageView.image = #imageLiteral(resourceName: "warning_error 1")
rightArrowImageView.image = #imageLiteral(resourceName: "ic-arrow-right")
NSLayoutConstraint.activate([
profileLbl.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 24),
profileLbl.centerYAnchor.constraint(equalTo: centerYAnchor),
visibleProfileTrailingConstraint,
hiddenProfileTrailingConstraint,
badgeImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
badgeImageView.widthAnchor.constraint(equalToConstant: 24),
badgeImageView.heightAnchor.constraint(equalToConstant: 24),
rightArrowImageView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -24),
rightArrowImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
rightArrowImageView.widthAnchor.constraint(equalToConstant: 16),
rightArrowImageView.heightAnchor.constraint(equalToConstant: 16)
])
}
private func toggleHide(badge: Bool) {
if badge == false {
if badgeImageView.isHidden {
badgeImageView.isHidden = false
visibleProfileTrailingConstraint.priority = .defaultHigh
hiddenProfileTrailingConstraint.priority = .defaultLow
}
} else {
visibleProfileTrailingConstraint.priority = .defaultLow
hiddenProfileTrailingConstraint.priority = .defaultHigh
badgeImageView.isHidden = true
}
}
// I initialise it in my viewController
let infoBtn = GTProfileBtn(name: "Basic Info", isBadgeHidden: false)
// this is when I try to test it in my viewDidLoad
infoBtn.isHiddenBadge = true
Use following
var isHiddenBadge = false {
didSet {
toggleHide(badge: isHiddenBadge)
}
}
The problem is you not calling toggleHide after setting isHiddenBadge. The above code will solve the issue.

How can I add some insets to the text inside the UILabel?

I'm trying to add insets to the text inside the UILabel without subclassing it. Or even with UILabel subclass but without changing too much the code.
How can I do it?
class CustomCell: UICollectionViewCell {
var data:CustomData? {
didSet {
guard let data = data else { return }
//bg.image = data.image
bg.text = data.title
}
}
fileprivate let bg: UILabel = {
let iv = UILabel()
iv.layer.backgroundColor = UIColor.gray.cgColor
iv.textAlignment = .center
iv.numberOfLines = 0
iv.font = UIFont(name: "Helvetica", size: 40)
iv.adjustsFontSizeToFitWidth = true
iv.minimumScaleFactor = 0.5
iv.translatesAutoresizingMaskIntoConstraints = false
iv.layer.cornerRadius = 12
return iv
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(bg)
bg.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Use constant parameter
bg.topAnchor.constraint(equalTo: contentView.topAnchor,constant:30).isActive = true
for 30 pts inset do
NSLayoutConstraint.activate([
bg.topAnchor.constraint(equalTo: contentView.topAnchor,constant:30),
bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,constant:30),
bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,constant:-30),
bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor,constant:-30)
])
You can also set UIEdgeInsets
Your entire approach is wrong. If the goal is to show the label text centered in bg, then bg should not be a label; it should contain a label, centered.
This example uses no code at all; the outer view self-sizes to the label, and the label's constraints to the outer view provide the insets:

Swift: UIStackView of UIControls with selector method that doesn't fire

Introduction
I'm creating an app which uses a custom view in which I have a UIStackView to sort out 5 UIControls. When a user taps one of the UIControls an underscore line gets animated, sliding under the tapped UIControl.
However, for some reason the method/selector for these UIControls no longer gets called. I believe this has to do with that I updated my Mac to the macOS (and Xcode) update released this week (wk.44). (updated from swift 4.2 to swift 4.2.1). Before the updated this animation and selector worked perfectly. But I'm not sure. And I'm now completely stuck on what I'm doing wrong.
Context
I created a playground and scaled down everything as much as I could and the issue persists.
I have tried to define the UIStackView in the global scope of my SetupView class but it doesn't change anything. So I believe it is not an issue of the stackView or its subviews being deallocated?
Below I've provided my UIControl subclass and my SetupView (UIView subclass) that I use. I've created a playground so you may copy paste in Xcode playground to test if you want.
Question
Why doesn't the method goalViewControlTapped(_ sender: SetupViewControl) get called?
Code
import UIKit
import PlaygroundSupport
class SetupViewControl: UIControl {
let titleLabel : UILabel = {
let lbl = UILabel()
lbl.font = UIFont(name: "Futura", size: 14)
lbl.textColor = .white
lbl.backgroundColor = .clear
lbl.textAlignment = .center
lbl.translatesAutoresizingMaskIntoConstraints = false
return lbl
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupLabel()
layer.cornerRadius = 5
}
fileprivate func setupLabel() {
addSubview(titleLabel)
titleLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 5).isActive = true
titleLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -5).isActive = true
titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var isHighlighted: Bool {
didSet {
UIView.animate(withDuration: 0.12) {
self.backgroundColor = self.isHighlighted ? UIColor.lightGray : UIColor.clear
}
}
}
}
class SetupView: UIView {
let dataModel : [String] = ["2 weeks", "1 month", "2 months", "6 months", "1 year"]
var selectionLineCenterX : NSLayoutConstraint!
let selectionLine = UIView()
let labelZero = SetupViewControl()
let labelOne = SetupViewControl()
let labelTwo = SetupViewControl()
let labelThree = SetupViewControl()
let labelFour = SetupViewControl()
let labelFive = SetupViewControl()
lazy var controlArray = [self.labelZero, self.labelOne, self.labelTwo, self.labelThree, self.labelFour, self.labelFive]
init(frame: CGRect, color: UIColor) {
super.init(frame: frame)
self.backgroundColor = color
setupView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
fileprivate func setupView() {
layer.cornerRadius = 0
layer.borderColor = UIColor.black.cgColor
layer.borderWidth = 1
setupLabelText()
setupControlsInStackView()
}
fileprivate func setupLabelText() {
for num in 0...(dataModel.count - 1) {
controlArray[num].titleLabel.text = dataModel[num]
}
}
// let stackView = UIStackView(frame: .zero) I have tried to declare the stackView here but it doesn't fix my issue.
func setupControlsInStackView() {
var stackViewArray = [SetupViewControl]()
for num in 0...(dataModel.count - 1) {
controlArray[num].isUserInteractionEnabled = true
controlArray[num].addTarget(self, action: #selector(goalViewControlTapped(_:)), for: .touchUpInside)
stackViewArray.append(controlArray[num])
}
let stackView = UIStackView(arrangedSubviews: stackViewArray)
stackView.alignment = .fill
stackView.distribution = .fillEqually
stackView.axis = .horizontal
stackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(stackView)
stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8).isActive = true
stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8).isActive = true
stackView.topAnchor.constraint(equalTo: topAnchor, constant: 15).isActive = true
addSubview(selectionLine)
selectionLine.backgroundColor = .white
selectionLine.translatesAutoresizingMaskIntoConstraints = false
selectionLine.heightAnchor.constraint(equalToConstant: 1).isActive = true
selectionLine.topAnchor.constraint(equalTo: stackView.bottomAnchor).isActive = true
selectionLine.widthAnchor.constraint(equalToConstant: 50).isActive = true
selectionLineCenterX = selectionLine.centerXAnchor.constraint(equalTo: leadingAnchor, constant: -100)
selectionLineCenterX.isActive = true
}
#objc fileprivate func goalViewControlTapped(_ sender: SetupViewControl) {
print("This is not getting printed!!!")
selectionLineCenterX.isActive = false
selectionLineCenterX = selectionLine.centerXAnchor.constraint(equalTo: sender.centerXAnchor)
selectionLineCenterX.isActive = true
UIView.animate(withDuration: 0.25, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.5, options: .curveEaseIn, animations: {
self.layoutIfNeeded()
}, completion: nil)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let testView = SetupView(frame: .zero, color: UIColor.blue)
view.addSubview(testView)
testView.translatesAutoresizingMaskIntoConstraints = false
testView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
testView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
testView.heightAnchor.constraint(equalToConstant: 100).isActive = true
testView.widthAnchor.constraint(equalToConstant: 365).isActive = true
}
}
// For live view in playground
let vc = ViewController()
vc.preferredContentSize = CGSize(width: 375, height: 812)
PlaygroundPage.current.liveView = vc
Thanks for reading my question.
Does your UIStackView show as having an ambiguous layout when you open the view debugger? If so, that may be causing the internal views to not receive the touch events.
You can provide UIStackView with either:
x and y constraints only
or
x, y, width and height.
In the above case the height constraint is missing.

Swift: How to resize the font size within a UITextView while using AutoLayout?

I am one week into Swift programing and I want to build my first Application with Autolayout.
The current state of my app is that I generate a bunch of PictureCell in my ViewController. Their size is based on a slider value (and also calculated in the ViewController). This works just fine.
My struggle is customizing the inside of my PictureCell. My goal is to have a Label in the cell which font size is automatically resized when I resize the cell.
At the current state I can resize the Cell and the UITextView like I want, but I cannot resize the font within the Textview because it's constant is just called when it is initialized (I guess).
How can I address this problem in a good way?
Due to a not understanding of Swifts logic I have to post the whole code of the PictureCell:
class PictureCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
self.translatesAutoresizingMaskIntoConstraints = false
self.layer.cornerRadius = self.bounds.width / 20
self.clipsToBounds = true
setupViews()
}
let descriptionTextView: UITextView = {
let textView = UITextView()
textView.text = "Header"
textView.textColor = .black
textView.backgroundColor = .white
textView.translatesAutoresizingMaskIntoConstraints = false
textView.textAlignment = .center
textView.isEditable = false
textView.isScrollEnabled = false
textView.sizeToFit()
textView.font = UIFont.boldSystemFont(ofSize: textView.contentSize.height / 2) // Resize that
textView.layer.borderWidth = 2
textView.layer.borderColor = UIColor.red.cgColor
return textView
}()
var mainPicture: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
imageView.clipsToBounds = true
return imageView
}()
func setPictureForIndex(index: Int) {
self.mainPicture.image = UIImage(named: "color\(index)")
}
func setupViews() {
addSubview(mainPicture)
confMainPicture()
addSubview(descriptionTextView)
confDescriptionTextView()
}
func confMainPicture() {
mainPicture.translatesAutoresizingMaskIntoConstraints = false
mainPicture.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
mainPicture.heightAnchor.constraint(equalTo: self.heightAnchor).isActive = true
mainPicture.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
mainPicture.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
}
func confDescriptionTextView(){
descriptionTextView.translatesAutoresizingMaskIntoConstraints = false
descriptionTextView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
descriptionTextView.heightAnchor.constraint(equalTo: mainPicture.heightAnchor, multiplier: 0.25).isActive = true
descriptionTextView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
}
Too small for the text
Just fine
Too big to look good
This Code solved my problem more or less:
It doesn't work properly if the Cell is really small but it's better than the starting point and maybe someone can use it.
class PictureCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
self.translatesAutoresizingMaskIntoConstraints = false
self.layer.cornerRadius = self.bounds.width / 20
self.clipsToBounds = true
setupViews()
}
//MARK: -
var cellIdetifier = Int()
var mainPicture: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
imageView.clipsToBounds = true
imageView.layer.cornerRadius = imageView.bounds.width / 20
return imageView
}()
var descriptionBox: UIView = {
let descVie = UIView()
descVie.backgroundColor = UIColor(red: 0.1 , green: 0.1, blue: 0.1, alpha: 0.5)
descVie.layer.borderWidth = 0.5
descVie.layer.borderColor = UIColor.black.cgColor
descVie.clipsToBounds = true
descVie.layer.cornerRadius = descVie.bounds.height / 5
return descVie
}()
lazy var descLabel: UITextField = {
let label = UITextField()
label.textColor = .white
label.textAlignment = .center
label.clipsToBounds = true
label.font = UIFont.systemFont(ofSize: 15)
label.adjustsFontSizeToFitWidth = true
label.autoresizingMask = [.flexibleWidth,.flexibleHeight]
label.sizeToFit()
label.layoutIfNeeded()
label.isUserInteractionEnabled = false
return label
}()
func setPictureForIndex(index: Int, name: String) {
self.descLabel.text = name
self.mainPicture.image = UIImage(named: "color\(index)")
}
// MARK: -
// MARK: Layout
func setupViews() {
addSubview(mainPicture)
addSubview(descriptionBox)
descriptionBox.addSubview(descLabel)
confBounds()
}
func confBounds() {
mainPicture.translatesAutoresizingMaskIntoConstraints = false
mainPicture.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
mainPicture.heightAnchor.constraint(equalTo: self.heightAnchor).isActive = true
mainPicture.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
mainPicture.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
descriptionBox.translatesAutoresizingMaskIntoConstraints = false
descriptionBox.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
descriptionBox.heightAnchor.constraint(equalTo: mainPicture.heightAnchor, multiplier: 0.25).isActive = true
descriptionBox.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
descriptionBox.bottomAnchor.constraint(greaterThanOrEqualTo: mainPicture.topAnchor, constant: 1)
descLabel.translatesAutoresizingMaskIntoConstraints = false
descLabel.widthAnchor.constraint(equalTo: descriptionBox.widthAnchor).isActive = true
descLabel.heightAnchor.constraint(equalTo: descriptionBox.heightAnchor).isActive = true
descLabel.bottomAnchor.constraint(equalTo: descriptionBox.bottomAnchor).isActive = true
descLabel.heightAnchor.constraint(equalTo: descriptionBox.heightAnchor).isActive = true
}
}

Resources