Trying to programmatically add UIScrollView to my App and I keep getting a blank View - ios

Trying to create a UIScrollView and I cant seem to get my labels to appear as I would like them dead center.
lazy var label : UILabel = {
let label = UILabel()
label.text = "center of container view.center of container view"
label.font = UIFont(name: "Bebas Neue", size: 23)!
label.textColor = .black
return label
}()
// Mark: Properties
lazy var contentViewSize = CGSize(width: self.view.frame.width + 1200, height: self.view.frame.height)
// Mark: Views
fileprivate lazy var parentScrollView : UIView = {
var newView = UIView()
newView.translatesAutoresizingMaskIntoConstraints = false
newView.backgroundColor = .black
newView.frame = self.scrollView.bounds
newView.frame.size = contentViewSize
return newView
}()
fileprivate lazy var scrollView : UIScrollView = {
var uiScrollView = UIScrollView(frame: .zero)
uiScrollView.translatesAutoresizingMaskIntoConstraints = false
uiScrollView.frame = view.bounds
uiScrollView.backgroundColor = .gray
uiScrollView.addViewBorder(borderColor: UIColor.gray.cgColor, borderWith: 10, borderCornerRadius: 0)
// uiScrollView.alpha =
uiScrollView.contentSize = contentViewSize
// uiScrollView.autoresizingMask = .flexibleHeight
uiScrollView.showsVerticalScrollIndicator = true
uiScrollView.bounces = true
return uiScrollView
}()
fileprivate lazy var tutorialView : UIStackView = {
var tutView = UIStackView(arrangedSubviews: [label,label,label])
tutView.axis = .horizontal
tutView.backgroundColor = .white
tutView.distribution = .fillEqually
tutView.spacing = 0
return tutView
}()
override func viewDidLoad() {
view.backgroundColor = .white
view.addSubview(scrollView)
scrollView.addSubview(parentScrollView)
parentScrollView.addSubview(tutorialView)
scrollView.widthAnchor.constraint(equalTo:self.view.widthAnchor,multiplier: 0.9).isActive = true
scrollView.heightAnchor.constraint(equalTo:self.view.heightAnchor,multiplier: 0.7).isActive = true
scrollView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 75).isActive = true
tutorialView.topAnchor.constraint(equalTo: parentScrollView.topAnchor,constant: +10).isActive = true}
It seems that when I add that last constraight with the topAnchor I get a blank screen. When I take that off I actually get the borders between the two views and I am able to do some scrolling.
Any help would be appreciated. Thank you

Did you give a value to the scrollView?
uiScrollView.contentSize.width = 1200
Then give the tutorialView the same width constraint with the other constraints.
NSLayoutConstraint.activate([
tutorialView.widthAnchor.constraint(equalToConstant: 1200),
tutorialView.heightAnchor.constraint(equalTo: uiScrollView.heightAnchor)
])

You have to add tutView.translatesAutoresizingMaskIntoConstraints = false when giving layout constraints in closure of tutorialView and also there are some mistakes in your code. So included some changes in your code and check updated code:
lazy var label : UILabel = {
let label = UILabel()
label.text = "center of container view.center of container view"
label.font = UIFont(name: "Bebas Neue", size: 23)!
label.textColor = .green
return label
}()
// Mark: Properties
lazy var contentViewSize = CGSize(width: self.view.frame.width + 1200, height: self.view.frame.height)
// Mark: Views
fileprivate lazy var parentScrollView : UIView = {
var newView = UIView()
newView.translatesAutoresizingMaskIntoConstraints = false
newView.backgroundColor = UIColor.clear
// newView.layer.borderWidth = 2
// newView.layer.borderColor = UIColor.yellow.cgColor
return newView
}()
fileprivate lazy var scrollView : UIScrollView = {
var uiScrollView = UIScrollView()
uiScrollView.translatesAutoresizingMaskIntoConstraints = false
// uiScrollView.frame = view.bounds
uiScrollView.backgroundColor = .orange
uiScrollView.layer.borderColor = UIColor.blue.cgColor
uiScrollView.layer.borderWidth = 2
uiScrollView.layer.cornerRadius = 0
// uiScrollView.alpha =
uiScrollView.contentSize = contentViewSize
// uiScrollView.autoresizingMask = .flexibleHeight
uiScrollView.showsVerticalScrollIndicator = true
uiScrollView.bounces = true
return uiScrollView
}()
fileprivate lazy var tutorialView : UIStackView = {
var tutView = UIStackView(arrangedSubviews: [label,label,label])
tutView.axis = .horizontal
tutView.backgroundColor = .red
tutView.distribution = .fill
tutView.translatesAutoresizingMaskIntoConstraints = false
return tutView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(scrollView)
scrollView.addSubview(parentScrollView)
parentScrollView.addSubview(tutorialView)
scrollView.widthAnchor.constraint(equalTo:self.view.widthAnchor,multiplier: 0.9).isActive = true
scrollView.heightAnchor.constraint(equalTo:self.view.heightAnchor,multiplier: 0.7).isActive = true
scrollView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 25).isActive = true
parentScrollView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
parentScrollView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 10).isActive = true
parentScrollView.heightAnchor.constraint(equalToConstant: 200).isActive = true
parentScrollView.widthAnchor.constraint(equalToConstant: 200).isActive = true
// scrollView.layer.borderWidth = 2
// scrollView.layer.borderColor = UIColor.blue.cgColor
tutorialView.heightAnchor.constraint(equalTo: parentScrollView.heightAnchor).isActive = true
tutorialView.widthAnchor.constraint(equalToConstant: 1200).isActive = true
}

Related

Variable-width StackView?

This is my code:
import UIKit
class DocumentViewController: UIViewController, UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return scrollViewContainer
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
let scrollViewSize = scrollView.bounds.size
let scrollViewContainerSize = scrollViewContainer.frame.size
let verticalPadding = scrollViewContainerSize.height < scrollViewSize.height ? (scrollViewSize.height - scrollViewContainerSize.height) / 2 : 0
let horizontalPadding = scrollViewContainerSize.width < scrollViewSize.width ? (scrollViewSize.width - scrollViewContainerSize.width) / 2 : 0
scrollView.contentInset = UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
}
let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.minimumZoomScale = 0.1
scrollView.maximumZoomScale = 4.0
scrollView.zoomScale = 1.0
return scrollView
}()
let scrollViewContainer: UIStackView = {
let view = UIStackView()
view.translatesAutoresizingMaskIntoConstraints = false
view.axis = .vertical
view.spacing = 15
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
view.backgroundColor = .gray
view.addSubview(scrollView)
scrollView.addSubview(scrollViewContainer)
let uiview1 = UIView(frame: .zero)
uiview1.heightAnchor.constraint(equalToConstant: 1000).isActive = true
uiview1.widthAnchor.constraint(equalToConstant: 1000).isActive = true
scrollViewContainer.addArrangedSubview(uiview1)
uiview1.backgroundColor = .white
let uiview2 = UIView(frame: .zero)
uiview2.heightAnchor.constraint(equalToConstant: 1000).isActive = true
uiview2.widthAnchor.constraint(equalToConstant: 1000).isActive = true
scrollViewContainer.addArrangedSubview(uiview2)
uiview2.backgroundColor = .white
let uiview3 = UIView(frame: .zero)
uiview3.heightAnchor.constraint(equalToConstant: 1000).isActive = true
uiview3.widthAnchor.constraint(equalToConstant: 1000).isActive = true
scrollViewContainer.addArrangedSubview(uiview3)
uiview3.backgroundColor = .white
let uiview4 = UIView(frame: .zero)
uiview4.heightAnchor.constraint(equalToConstant: 1000).isActive = true
uiview4.widthAnchor.constraint(equalToConstant: 1000).isActive = true
scrollViewContainer.addArrangedSubview(uiview4)
uiview4.backgroundColor = .white
let uiview5 = UIView(frame: .zero)
uiview5.heightAnchor.constraint(equalToConstant: 1000).isActive = true
uiview5.widthAnchor.constraint(equalToConstant: 2000).isActive = true
scrollViewContainer.addArrangedSubview(uiview5)
uiview5.backgroundColor = .white
showBounds()
setConstraints()
}
func setConstraints() {
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
scrollViewContainer.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
scrollViewContainer.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
scrollViewContainer.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
scrollViewContainer.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
}
func showBounds() {
view.layer.borderWidth = 5.0
view.layer.borderColor = UIColor.blue.cgColor
scrollViewContainer.layer.borderWidth = 5.0
scrollViewContainer.layer.borderColor = UIColor.red.cgColor
scrollView.layer.borderWidth = 3.0
scrollView.layer.borderColor = UIColor.yellow.cgColor
}
}
This code gives the following behaviour:
https://i.stack.imgur.com/gNxnD.gif
You can see that whereas the last test UIView I made in viewDidLoad has a width of 2000, it ends up being cut off for some reason, as if its width is 1000. Additionally, if I change the width of the last view to 500, I get this behaviour.
So it seems that scrollViewContainer (?) is resizing to the smallest width out of those test UIViews. All I want is for it to allow different sized views, with the default width being the widest child view, as in this mockup.
You need to add 'alignment' to your stack view. Please try this:
let scrollViewContainer: UIStackView = {
let view = UIStackView()
view.translatesAutoresizingMaskIntoConstraints = false
view.axis = .vertical
view.alignment = .center
view.spacing = 15
return view
}()

How to programmatically align elements in a Stackview using SnapKit?

I'm trying to achieve a specific design inside a custom reusable view.
(Something like this: )
So I pass an URL to retrive the image and I pass a String to add below.
Firstly, I want the entire view to be the width of the elements (if the text is long then the entire view will be wider), I don't know how to do that, the view seems to be the entire width of the screen.
Secondly, I want the items to be centered horizontally and vertically, what I tried does not work.
Here is my current code :
func initLayout() {
stackView.axis = NSLayoutConstraint.Axis.vertical
stackView.distribution = UIStackView.Distribution.fillEqually
stackView.alignment = UIStackView.Alignment.center
stackView.spacing = 10.0
stackView.addArrangedSubview(imageView)
stackView.addArrangedSubview(textContainer)
stackView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(stackView)
self.snp.makeConstraints { (make) -> Void in
make.height.equalTo(70)
}
self.stackView.snp.makeConstraints{ (make) -> Void in
make.edges.equalTo(self)
}
}
And it results in something like this:
As you can (or cannot) see, the view is centered in the middle of the screen, which is not what I want. The view should be the width of the text and everything centered inside this particular width, then I add it inside my VC and place it so it's leading.
if I understand well the is your constraint without Snapkit:
Set your objects under your class controller declaration:
let myImageView: UIImageView = {
let iv = UIImageView()
iv.contentMode = .scaleToFill
iv.clipsToBounds = true
iv.backgroundColor = .red
iv.translatesAutoresizingMaskIntoConstraints = false
return iv
}()
let myLabel: UILabel = {
let label = UILabel()
label.text = "Débats"
label.textColor = .white
label.textAlignment = .center
label.font = .systemFont(ofSize: 30, weight: .semibold) // set your font size here
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
Now in viewDidLoad set parameters and constraints:
myImageView.image = UIImage(named: "profilo") // set here your image
let myWidth = myLabel.intrinsicContentSize.width // This reveal only text width in label
view.addSubview(myLabel)
myLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5).isActive = true
myLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
myLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 25).isActive = true
myLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
view.addSubview(myImageView)
myImageView.widthAnchor.constraint(equalToConstant: myWidth).isActive = true
myImageView.heightAnchor.constraint(equalTo: myImageView.widthAnchor).isActive = true
myImageView.bottomAnchor.constraint(equalTo: myLabel.topAnchor).isActive = true
myImageView.centerXAnchor.constraint(equalTo: myLabel.centerXAnchor).isActive = true
This is the result:
Intere code:
class Aiutotipo: UIViewController {
let myImageView: UIImageView = {
let iv = UIImageView()
iv.contentMode = .scaleToFill
iv.clipsToBounds = true
iv.backgroundColor = .red
iv.translatesAutoresizingMaskIntoConstraints = false
return iv
}()
let myLabel: UILabel = {
let label = UILabel()
label.text = "Débats"
label.textColor = .white
label.textAlignment = .center
label.font = .systemFont(ofSize: 30, weight: .semibold)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
myImageView.image = UIImage(named: "profilo") // set here your image
let myWidth = myLabel.intrinsicContentSize.width // This reveal only text width in label
view.addSubview(myLabel)
myLabel.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5).isActive = true
myLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
myLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 25).isActive = true
myLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
view.addSubview(myImageView)
myImageView.widthAnchor.constraint(equalToConstant: myWidth).isActive = true
myImageView.heightAnchor.constraint(equalTo: myImageView.widthAnchor).isActive = true
myImageView.bottomAnchor.constraint(equalTo: myLabel.topAnchor).isActive = true
myImageView.centerXAnchor.constraint(equalTo: myLabel.centerXAnchor).isActive = true
}
}

UIButton in a view with animation not detecting touch

I'm following a tutorial to create an interactive popup animation (http://www.swiftkickmobile.com/building-better-app-animations-swift-uiviewpropertyanimator/), and now would like to add buttons to the popup rather than have static text as in the tutorial.
The animation works fine, but the buttons are not detecting touch. Touching the button causes the animation to reverse, instead of printing my "test" statement.
From research, it looks to either be an issue with view hierarchies, the animation disabling the button touch, or layout/constraint issues with the button. I've tried addressing the above issues, but nothing has worked, was hoping someone might be able to help?
I've left out the code pertaining to the animation since I think the issue is to do with layout (and the animation seems to be working fine) - but it's still a lot; apologies in advance for the large amount of code.
class ViewController: UIViewController {
private let popupOffset: CGFloat = 440
private lazy var contentImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "Background")
return imageView
}()
private lazy var overlayView: UIView = {
let view = UIView()
view.backgroundColor = .black
view.alpha = 0
return view
}()
private lazy var popupView: UIView = {
let view = UIView()
view.backgroundColor = .white
view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOpacity = 0.1
view.layer.shadowRadius = 10
return view
}()
private lazy var closedTitleLabel: UILabel = {
let label = UILabel()
label.text = "Hello"
label.font = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight.medium)
label.textColor = UIColor.darkGray
label.textAlignment = .center
return label
}()
private lazy var openTitleLabel: UILabel = {
let label = UILabel()
label.text = "Which door will you choose?"
label.font = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight.medium)
label.textColor = UIColor.darkGray
label.textAlignment = .center
label.alpha = 0
label.transform = CGAffineTransform(scaleX: 1.6, y: 1.6).concatenating(CGAffineTransform(translationX: 0, y: 15))
return label
}()
private lazy var reviewsImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "LabelBackground")
return imageView
}()
let stackView = UIStackView()
let buttonA = UIButton()
let buttonB = UIButton()
let buttonC = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
layout()
popupView.addGestureRecognizer(panRecognizer)
}
override var prefersStatusBarHidden: Bool {
return true
}
//Layout
private var bottomConstraint = NSLayoutConstraint()
private func layout() {
contentImageView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(contentImageView)
contentImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
contentImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
contentImageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
contentImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
overlayView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(overlayView)
overlayView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
overlayView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
overlayView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
overlayView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
popupView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(popupView)
popupView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
popupView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
bottomConstraint = popupView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: popupOffset)
bottomConstraint.isActive = true
popupView.heightAnchor.constraint(equalToConstant: 500).isActive = true
closedTitleLabel.translatesAutoresizingMaskIntoConstraints = false
popupView.addSubview(closedTitleLabel)
closedTitleLabel.leadingAnchor.constraint(equalTo: popupView.leadingAnchor).isActive = true
closedTitleLabel.trailingAnchor.constraint(equalTo: popupView.trailingAnchor).isActive = true
closedTitleLabel.topAnchor.constraint(equalTo: popupView.topAnchor, constant: 20).isActive = true
openTitleLabel.translatesAutoresizingMaskIntoConstraints = false
popupView.addSubview(openTitleLabel)
openTitleLabel.leadingAnchor.constraint(equalTo: popupView.leadingAnchor).isActive = true
openTitleLabel.trailingAnchor.constraint(equalTo: popupView.trailingAnchor).isActive = true
openTitleLabel.topAnchor.constraint(equalTo: popupView.topAnchor, constant: 20).isActive = true
reviewsImageView.translatesAutoresizingMaskIntoConstraints = false
popupView.addSubview(reviewsImageView)
reviewsImageView.leadingAnchor.constraint(equalTo: popupView.leadingAnchor).isActive = true
reviewsImageView.trailingAnchor.constraint(equalTo: popupView.trailingAnchor).isActive = true
reviewsImageView.bottomAnchor.constraint(equalTo: popupView.bottomAnchor).isActive = true
reviewsImageView.heightAnchor.constraint(equalToConstant: 428).isActive = true
buttonA.backgroundColor = UIColor.clear
let heightConstraintA = buttonA.heightAnchor.constraint(equalToConstant: 135)
heightConstraintA.isActive = true
heightConstraintA.priority = UILayoutPriority(rawValue: 999)
buttonA.translatesAutoresizingMaskIntoConstraints = false
buttonA.setTitle("A", for: .normal)
buttonA.setTitleColor(UIColor.darkGray, for: .normal)
buttonA.backgroundColor = UIColor.clear
buttonA.addTarget(self, action: #selector(buttonATapped(sender:)), for: .touchDown)
//self.popupView.addSubview(buttonA)
buttonB.backgroundColor = UIColor.clear
let heightConstraintB = buttonB.heightAnchor.constraint(equalToConstant: 135)
heightConstraintB.isActive = true
heightConstraintB.priority = UILayoutPriority(rawValue: 999)
buttonB.translatesAutoresizingMaskIntoConstraints = false
buttonB.setTitle("B", for: .normal)
buttonB.setTitleColor(UIColor.darkGray, for: .normal)
buttonB.backgroundColor = UIColor.clear
//self.popupView.addSubview(buttonB)
buttonC.backgroundColor = UIColor.clear
let heightConstraintC = buttonC.heightAnchor.constraint(equalToConstant: 135)
heightConstraintC.isActive = true
heightConstraintC.priority = UILayoutPriority(rawValue: 999)
buttonC.translatesAutoresizingMaskIntoConstraints = false
buttonC.setTitle("C", for: .normal)
buttonC.setTitleColor(UIColor.darkGray, for: .normal)
buttonC.backgroundColor = UIColor.clear
//self.popupView.addSubview(buttonC)
popupView.addSubview(stackView)
stackView.backgroundColor = UIColor.clear
stackView.addArrangedSubview(buttonA)
stackView.addArrangedSubview(buttonB)
stackView.addArrangedSubview(buttonC)
stackView.translatesAutoresizingMaskIntoConstraints = false
popupView.addSubview(stackView)
stackView.leadingAnchor.constraint(equalTo: popupView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: popupView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: popupView.bottomAnchor).isActive = true
stackView.heightAnchor.constraint(equalToConstant: 428).isActive = true
stackView.axis = .vertical
stackView.distribution = .fill
stackView.translatesAutoresizingMaskIntoConstraints = false
}
#objc func buttonATapped(sender: UIButton) {
print ("test")
}
private func animateTransitionIfNeeded(to state: State, duration: TimeInterval) {
//Animation code
}
#objc private func popupViewPanned(recognizer: UIPanGestureRecognizer) {
//Animation code
}
}
***For anyone else having the same issue, here is how I solved it, thanks to #OverD:
I removed the reviewsImageView completely (because that was only for color in my case, and I can easily add the color to the UIButton instead) Then instead of adding the buttons to the popupView, I added them to the stack view, and the stack view to the popupView. Lastly, my syntax for addTarget was not correct, and for some reason changing it to touchDown instead of touchUpInside made it work.
I noticed from the provided code that you are adding the same buttons multiple times, once as a subview of the popView and once in the stackView. Also you are not assigning any targets for the buttons.
I hope this helps

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

Text jumps while automatically resize textView in swift

if have a simple messageView in my app. on the messageView is a input-container with a textView. The textView should resize depending on its content.
It works so far, but every time while wrapping into the next line the text "jumps" for the first character, but reposition with the second character. it looks like:
the most of my code. i assume that it has something to do with the scroll capabilities of the textView(?)
private let container: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
view.layer.cornerRadius = 20
view.layer.masksToBounds = true
view.layer.borderColor = UIColor(red:0.90, green:0.90, blue:0.90, alpha:1.0).cgColor
view.layer.borderWidth = 0.5
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private lazy var inputTV: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.font = UIFont(name: "OpenSans-Light", size: 16)
tv.backgroundColor = .red
tv.delegate = self
tv.textContainer.lineBreakMode = .byWordWrapping
return tv
}()
override internal init(frame: CGRect) {
super.init(frame: CGRect.zero)
translatesAutoresizingMaskIntoConstraints = false
addSubview(container)
container.addSubview(inputTV)
container.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -16).isActive = true
container.leftAnchor.constraint(equalTo: leftAnchor , constant: 16).isActive = true
container.rightAnchor.constraint(equalTo: rightAnchor, constant: -16).isActive = true
containerHeightAnchor = container.heightAnchor.constraint(equalToConstant: 40)
containerHeightAnchor?.isActive = true
inputTV.leftAnchor.constraint(equalTo: uploadButton.rightAnchor).isActive = true
inputTV.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
inputTV.rightAnchor.constraint(equalTo: sendButton.leftAnchor, constant: -5).isActive = true
textViewHeightAnchor = inputTV.heightAnchor.constraint(equalTo: container.heightAnchor)
textViewHeightAnchor?.isActive = true
}
internal func textViewDidChange(_ textView: UITextView) {
let contentHeight = textView.contentSize.height
containerHeightAnchor?.constant = max(contentHeight, 40)
inputTV.frame.size.height = contentHeight
}
I hope somebody could help. regards
thanks to #DonMag i do remove the heightAnchor from textViewand it does work for me. The new code is as following:
disable scrolling on the textView (isScrollEnabled = false)
private lazy var inputTV: UITextView = {
let tv = UITextView()
tv.translatesAutoresizingMaskIntoConstraints = false
tv.font = UIFont(name: "OpenSans-Light", size: 16)
tv.delegate = self
tv.isScrollEnabled = false
return tv
}()
remove heightAnchor (no inputTV.heightAnchor resp. my textViewHeightAnchor)
override internal init(frame: CGRect) {
super.init(frame: CGRect.zero)
translatesAutoresizingMaskIntoConstraints = false
addSubview(container)
container.addSubview(inputTV)
...
inputTV.leftAnchor.constraint(equalTo: uploadButton.rightAnchor).isActive = true
inputTV.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
inputTV.rightAnchor.constraint(equalTo: sendButton.leftAnchor, constant: -5).isActive = true
}

Resources