Here is my code
import UIKit
class PageCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
let imageView: UIImageView = {
let iv = UIImageView()
iv.contentMode = .scaleAspectFill
iv.backgroundColor = .yellow
iv.image = UIImage(named: "page1")
return iv
}()
func setupViews() {
backgroundColor = .blue
addSubview(imageView)
imageView.(topAnchor, bottomAnchor, rightAnchor, leftAnchor)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
When compiling this it shows this error. Value of type 'UIImageView' has no member 'anchorToTop' By the way I am trying to anchor an image to an individual UIImageViewCell.
You can try
func setupViews() {
backgroundColor = .blue
imageView.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(imageView)
imageView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 0 ).isActive = true
imageView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: 0 ).isActive = true
imageView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 0 ).isActive = true
imageView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: 0 ).isActive = true
}
Related
I am new to swift - I want to add a label ONTO the ui image view image in a collectionview, however i am having some issues. The text sits below the image view, how can i adjust it so it stays in the middle of the image. I want to do this in code and not use storyboards or a nib file. I believe it may be due to my frames i have set:
import UIKit
class ExploreCollectionViewCell: UICollectionViewCell {
static let identifier = "ExploreCollectionViewCell"
private let label: UILabel = {
let label = UILabel()
label.textColor = .white
label.font = UIFont(name: Settings.shared.MAIN_APP_FONT_BOLD, size: 13)
return label
}()
private let imageView: UIImageView = {
let imageView = UIImageView()
imageView.clipsToBounds = true
imageView.layer.cornerRadius = 0
imageView.contentMode = .scaleAspectFill
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(label)
contentView.addSubview(imageView)
}
required init?(coder: NSCoder) {
fatalError()
}
override func layoutSubviews() {
super.layoutSubviews()
label.frame = CGRect(x: 5, y: 0, width: contentView.frame.size.width-10, height: 50)
//imageView.frame = contentView.bounds
imageView.frame = CGRect(x: 0, y: 0, width: 250, height: 250)
}
override func prepareForReuse() {
super.prepareForReuse()
imageView.image = nil
}
func configure(with urlString: String, label: String) {
guard let url = URL(string: urlString) else {
return
}
let task = URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
guard let data = data, error == nil else {
return
}
DispatchQueue.main.async {
self?.label.text = label
let image = UIImage(data: data)
self?.imageView.image = image
}
}
task.resume()
}
}
First, add the imageView before adding the label, so that it will be shown behind the label:
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(imageView) // behind
contentView.addSubview(label) // front
}
Second, it would be easier to use auto layout:
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.widthAnchor.constraint(equalToConstant: 250).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 250).isActive = true
label.translatesAutoresizingMaskIntoConstraints = false
label.centerYAnchor.constraint(equalTo: imageView.centerYAnchor).isActive = true
label.widthAnchor.constraint(equalTo: imageView.widthAnchor).isActive = true
private let label: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textColor = .white
label.font = UIFont(name: Settings.shared.MAIN_APP_FONT_BOLD, size: 13)
return label
}()
private let imageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.clipsToBounds = true
imageView.layer.cornerRadius = 0
imageView.contentMode = .scaleAspectFill
return imageView
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(label)
contentView.addSubview(imageView)
imageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 0).isActive = true
imageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0).isActive = true
imageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 0).isActive = true
imageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 0).isActive = true
label.heightAnchor.constraint(equalToConstant: 50).isActive = true
label.centerYAnchor.constraint(contentView.centerYAnchor).isActive = true
label.centerXAnchor.constraint(contentView.centerXAnchor).isActive = true
label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 5).isActive = true
label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -5).isActive = true
}
required init?(coder: NSCoder) {
fatalError()
}
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.
I have a prototype cell for a collection view and am trying to make the edges rounded, but I can't figure out how to use self.layer.cornerRadius = 3.0 and make it work. Could anyone tell me what I'm doing wrong?
import UIKit
final class TagCell: UICollectionViewCell {
let textLabel: UILabel
override init(frame: CGRect) {
self.textLabel = UILabel(frame: .zero)
self.textLabel.setFont(14)
self.textLabel.translatesAutoresizingMaskIntoConstraints = false
self.textLabel.textAlignment = .center
self.textLabel.backgroundColor = .red
self.textLabel.layer.cornerRadius = 2.0
super.init(frame: frame)
self.contentView.layer.cornerRadius = 2.0
self.contentView.clipsToBounds = true
self.contentView.addSubview(textLabel)
NSLayoutConstraint.activate([
self.textLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 16),
self.textLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -16),
self.textLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 16),
self.textLabel.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -16),
])
}
required init?(coder decoder: NSCoder) {
fatalError()
}
}
it's better to create a subView inside the contentView and apply the corner to it
self.contentView.layer.cornerRadius = 2.0
self.contentView.clipsToBounds = true
class ChatCollectionViewCell: UICollectionViewCell {
var chatView: UIView!
var chatTextView: UITextView!
var isTextFromCurrentUser: Bool = true
var chatViewWidth: CGFloat = 200
override init(frame: CGRect) {
super.init(frame: frame)
chatView = UIView()
chatTextView = UITextView()
contentView.addSubview(chatView)
contentView.addSubview(chatTextView)
setupViews()
}
override func layoutSubviews() {
if isTextFromCurrentUser {
chatView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
chatTextView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 15).isActive = true
chatTextView.backgroundColor = .white
} else {
chatView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
chatTextView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -15).isActive = true
chatTextView.backgroundColor = UIColor(r: 157, g: 255, b: 164)
}
chatView.widthAnchor.constraint(equalToConstant: chatViewWidth).isActive = true
chatView.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
chatTextView.widthAnchor.constraint(equalTo: chatView.widthAnchor, constant: -10).isActive = true
chatTextView.topAnchor.constraint(equalTo: chatView.topAnchor, constant: 5).isActive = true
chatView.translatesAutoresizingMaskIntoConstraints = false
chatTextView.translatesAutoresizingMaskIntoConstraints = false
}
func setupViews() {
chatView.backgroundColor = .blue
chatTextView.font = UIFont.systemFont(ofSize: 16)
chatTextView.layer.cornerRadius = 9
chatTextView.clipsToBounds = true
chatTextView.isScrollEnabled = false
}
override func prepareForReuse() {
super.prepareForReuse()
chatView = nil
chatTextView = nil
chatView = UIView()
chatTextView = UITextView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
(for clarification, I am setting the chatViewWidth and the chatTextView.text property in the ViewController's cellForRow method)
So right now, the error that XCode is giving is the following: "Unable to activate constraint with anchors and because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies?"
I looked through many posts regarding common ancestor errors on StackOverflow, but none of the solutions solved my problem.
Which is very confusing.
I tried using breakpoints to analyze what was wrong, but the program crashed after creating around ~14 cells or so. And sometimes it works, but when I add more cells, it will begin crashing. I'm not sure what the issue is--my views are definitely children views of the CollectionViewCell, correct?
Thank you!
This is how i would do it ... well basicy i would set all the stuff in Storyboard and set an Outlet for the widthConstraint ... but to take your code, this should work. But its not testet ... :)
class ChatCollectionViewCell: UICollectionViewCell {
var chatView: UIView!
var chatTextView: UITextView!
var isTextFromCurrentUser: Bool = true {
didSet {
if isTextFromCurrentUser {
NSLayoutConstraint.deactivate(rightAlignmentConstraints)
NSLayoutConstraint.activate(leftAlignmentConstraints)
chatTextView.backgroundColor = .white
} else {
NSLayoutConstraint.deactivate(leftAlignmentConstraints)
NSLayoutConstraint.activate(rightAlignmentConstraints)
chatTextView.backgroundColor = UIColor(r: 157, g: 255, b: 164)
}
}
}
var chatViewWidth: CGFloat = 200 {
didSet {
chatView.widthAnchor.constraint(equalToConstant: chatViewWidth).isActive = true
}
}
private var leftAlignmentConstraints: [NSLayoutConstraint] = []
private var rightAlignmentConstraints: [NSLayoutConstraint] = []
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
func setupViews() {
chatView = UIView()
chatTextView = UITextView()
contentView.addSubview(chatView)
contentView.addSubview(chatTextView)
chatView.translatesAutoresizingMaskIntoConstraints = false
chatTextView.translatesAutoresizingMaskIntoConstraints = false
chatView.backgroundColor = .blue
chatTextView.font = UIFont.systemFont(ofSize: 16)
chatTextView.layer.cornerRadius = 9
chatTextView.clipsToBounds = true
chatTextView.isScrollEnabled = false
leftAlignmentConstraints = [
chatView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10),
chatTextView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 15)
]
rightAlignmentConstraints = [
chatView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10),
chatTextView.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -15)
]
chatView.widthAnchor.constraint(equalToConstant: chatViewWidth).isActive = true
chatView.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
chatTextView.widthAnchor.constraint(equalTo: chatView.widthAnchor, constant: -10).isActive = true
chatTextView.topAnchor.constraint(equalTo: chatView.topAnchor, constant: 5).isActive = true
NSLayoutConstraint.activate(leftAlignmentConstraints)
}
override func prepareForReuse() {
super.prepareForReuse()
chatTextView.text = ""
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Good Luck and Happy Coding
I'm working on a exercise to create a custom control of anything. My idea is to have a UIView in the middle of the screen and a UILabel below it. When you tap on the view a random color will appear with the label changing to its hex value. When trying to create this custom control I'm having a problem trying to center the UIView programmatically. I get to an issue at `colorBox.center~
import UIKit
#IBDesignable
class Color: UIView {
private lazy var label : UILabel = {
let label = UILabel()
label.backgroundColor = UIColor.clear
label.translatesAutoresizingMaskIntoConstraints = false
label.heightAnchor.constraint(equalToConstant: 25.0).isActive = true
label.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
label.font = .systemFont(ofSize: 15.0, weight: UIFontWeightRegular)
return label
}()
private lazy var colorGen : UIView = {
let colorBox = UIView()
colorBox.backgroundColor = UIColor.black
colorBox.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
colorBox.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
colorBox.centerXAnchor.constraint(equalTo: colorBox.frame.size.width /2)
}()
override init (frame: CGRect) {
super.init(frame:frame)
setUpLabel()
setUpView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUpLabel()
setUpView()
}
I've tried the answers about using self.view but it doesn't work for me so I'm a bit lost.
You're close, but you need to add the label and the view so you can then constrain them relative to the superview...
#IBDesignable
class ColorView: UIView {
private lazy var colorLabel : UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.backgroundColor = UIColor.clear
label.heightAnchor.constraint(equalToConstant: 25.0).isActive = true
label.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
label.font = .systemFont(ofSize: 15.0, weight: UIFontWeightRegular)
return label
}()
private lazy var colorGen : UIView = {
let colorBox = UIView()
colorBox.translatesAutoresizingMaskIntoConstraints = false
colorBox.backgroundColor = UIColor.cyan
colorBox.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
colorBox.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
return colorBox
}()
override init (frame: CGRect) {
super.init(frame:frame)
commonSetup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonSetup()
}
func commonSetup() -> Void {
self.addSubview(colorGen)
self.addSubview(colorLabel)
colorGen.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0.0).isActive = true
colorGen.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0.0).isActive = true
colorGen.topAnchor.constraint(equalTo: self.topAnchor, constant: 0.0).isActive = true
colorLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 0.0).isActive = true
colorLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: 0.0).isActive = true
colorLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0.0).isActive = true
colorLabel.topAnchor.constraint(equalTo: colorGen.bottomAnchor, constant: 0.0).isActive = true
colorLabel.text = "the label"
}
}