Whenever you scroll, the title view bugs out and rapidly switches between two positions. The label manages to stay within the constraints of the view, and it is just the view's position that bugs.
I've made a gif of the issue if it is still unclear or you need to see an example of the problem.
https://gph.is/g/EJ09l9Z
I've tried playing around with constraints to no avail. I still believe that the issue is to do with constraints, although I am not an expert by any means in Xcode or swift so I could be wildly wrong.
These are the constraints that I have been working with and around in attempts to get this working.
titleView.leftAnchor.constraint(equalTo: scrollView.contentView.leftAnchor).isActive = true
titleView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor, constant: 6).isActive = true
titleView.rightAnchor.constraint(equalTo: scrollView.contentView.rightAnchor, constant: 6).isActive = true
titleView.bottomAnchor.constraint(equalTo: timeView.topAnchor).isActive = true
titleLabel.leftAnchor.constraint(equalTo: titleView.leftAnchor, constant: 10).isActive = true
titleLabel.topAnchor.constraint(equalTo: titleView.topAnchor).isActive = true
titleLabel.rightAnchor.constraint(equalTo: titleView.rightAnchor).isActive = true
titleLabel.bottomAnchor.constraint(equalTo: timeView.topAnchor).isActive = true
titleLabel.layer.masksToBounds = true
The goal is for the title to stay in the one position as the view is scrolled, like the labels and views beneath it. Feel free to suggest any other fixes or ask for more code, I just don't know what the problem would be if not constraints.
Also for clarification, I am not using a UIScrollView, but rather an OLEContainerScrollView.
https://github.com/ole/OLEContainerScrollView
https://oleb.net/blog/2014/05/scrollviews-inside-scrollviews/
Related
I've got a button whose top anchor is: backButton.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 2).isActive = true
And I've got a text view whose top anchor is: storyDescription.topAnchor.constraint(equalTo: numOfChapters.bottomAnchor, constant: 16).isActive = true (I've got elements between these but they don't affect this unusual behaviour).
When I tap on the textView it sometimes goes above the view, this only happens when I use view.safeAreaLayoutGuide, But when I don't use view.safeAreaLayoutGuide, it doesn't happen. And again, This only happens when I use view.safeAreaLayoutGuide and all the elements below are connected to the element that uses safeAreaLayoutGuide.
Sorry for the extremely basic question, but I'm trying to better understand MVC and how it pertains to more advanced screens.
Say I have a exampleView, that has multiple labels in it and I want to add this view to a ScrollView using addSubview. Should the ScrollView be instantiated in the View Controller and then calling self.view.addSubview(scrollView) and self.scrollView.addSubview(exampleView), or would you turn exampleView into a scrollView and just adding self.view.addSubview(exampleScrollView).
My friend has told me that there should never be programmatic constraints in the view controller if we're following MVC, but I'm not sure if that's true or not.
Constraints have nothing to do with MVC. MVC is a programming architecture or design pattern that attempts to divide the program into three categories: data (model), the visual objects that often represent the data (view), and the objects that bind them together (controller). And constraints are simply a way of positioning visual objects. The way you position visual objects has nothing to do with the architecture you decide for your program; they are completely independent of each other.
And the idea that a view controller should never have programmatic constraints is just ridiculous. Not only do constraints (let alone programmatic constraints) have nothing to do with MVC, forbidding the use of programmatic constraints for any reason is a sign of a very poor developer. You can code an entire application programmatically but you cannot even come close to coding an entire application non-programmatically.
The interface builder, in my opinion, is mostly there for professional programmers who program for a number of clients and find themselves constantly adding view objects (views, labels, buttons, scroll views, table views, etc.) because it's drag and drop. I personally find the whole IB experience very unappealing.
To your question about a scroll view, use this very basic template as a guide. Add the scroll view to the view and add the subviews to the scroll view. To make it work, however, you must anchor the objects in the scroll view to the edges of the scroll view (especially the bottom) so that its content view stretches and it scrolls.
class Slickdaddy: UIViewController {
private let scrollView = UIScrollView()
override func viewDidLoad() {
super.viewDidLoad()
addScrollView()
addAView()
}
private func addScrollView() {
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
}
private func addAView() {
let label = UILabel()
label.text = "slick daddy"
label.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(label)
label.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 16).isActive = true
label.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 32).isActive = true
label.sizeToFit()
label.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -32).isActive = true
}
}
I am currently trying to access the height of a view which I previously set anchors for. So for example, I set the left, right, top, and bottom anchors of searchTable using the following in my ViewController:
searchTable.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
searchTable.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
searchTable.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
searchTable.bottomAnchor.constraint(equalTo: menuBar.topAnchor).isActive = true
searchTable is an object of a class that I created that inherits from UIView and has a UIImageView in it. I constrain the UIImageView by using the following in the init function:
imageView.topAnchor.constraint(equalTo: topContainer.topAnchor, constant: 10).isActive = true
imageView.leftAnchor.constraint(equalTo: topContainer.leftAnchor, constant: 10).isActive = true
imageView.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: topContainerMultiplier * imageProfileMultiplier).isActive = true
imageView.widthAnchor.constraint(equalTo: self.heightAnchor, multiplier: topContainerMultiplier * imageProfileMultiplier).isActive = true
where:
let topContainerMultipler: Double = 1 / 7
let imageProfileMultipler: Double = 1 / 5
Inside the init function of searchTable, I try want to be able to set the corner radius to be half the image size. I tried to use self.frame.height, self.frame.size.height, self.bounds.height and also getting the .constant value of the self.heightAnchor constraint, but all returns 0.
I would think that there is a solution to get around this, but I haven't been able to find it.
You are querying the height of your view's frame after defining your constraints, but before layout has actually resolved those constraints into a frame rectangle. One approach would be to call layoutIfNeeded to force layout to happen immediately, then use view.frame.size.height. The init method is probably not an appropriate place to do this, as opposed to perhaps inside viewDidLoad on the controller. Or you might do this in viewDidLayoutSubviews to recalculate the corner radius every time your view's layout is updated (in which case you won't need layoutIfNeeded).
Don't use a height constraint if you already use top, bottom, leading, and trailing.
Try to visually debug your view by adding a background color, or using the debug view hierarchy button.
To get the height of a view you should use view.frame.size.height
EDIT (OP question edited)
Your problem is that you try to access the object height when it's just initialized but not displayed yet. You should create a function that update your UI and call it after your view is loaded.
I am trying to learn how to apply constraints to build a UITableViewCell. I am using iOS 10 using Swift. Here is my requirement.
I want to apply constraints to the green control which is a button and make sure that it is on the right hand side as shown above.
countView.widthAnchor.constraint(equalToConstant: 100).isActive = true
countView.heightAnchor.constraint(equalToConstant: 44).isActive = true
I have supplied the width and height constraints as above. But I don't know how to put it on the right hand side of the cell with some space as a margin.
UPDATE: I don't see anything on the screen.
countView.backgroundColor = UIColor.green
self.addSubview(countView)
countView.widthAnchor.constraint(equalToConstant: 100).isActive = true
countView.heightAnchor.constraint(equalToConstant: 44).isActive = true
countView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 20).isActive = true
countView.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
I'm developing iMessage Extension app.
My problem is that the collection view is visible behind navigation bar(I think navbar is automatically produced by iMessage Extension) in expand mode.
We can see collectionview (with transparency) behind navbar.
Is there anybody who has experience in this area?
Looking for any help.
After give Constraints(Top:0,Left:0,Right:0,Bottom:0),you should give Top Constraints of CollectionView to Top Layout Guide.Bottom ratherthan Superview.Top like this:
CollectionView.Top = Top Layout Guide.Bottom is set to 0.
In viewDidLoad():
CollectionView.frame = view.bounds
CollectionView.translatesAutoresizingMaskIntoConstraints = false
CollectionView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
CollectionView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
CollectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
CollectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
Referring to #seggy question comment:
have you set constraint perfectly?
You answered:
Yeah, of course, top:0, left:0, right:0, bottom: 0
The top constraint should be equals to 64 (it seems the top constraint is between the collectionView and the container view, not between the collectionView and the navigation bar).
Also, you might need to change the bottom constraint's constant value.
Hope this helped.