When adding the code below the subview appears way out of where I intended it to be. It appears almost outside the parent view, and not inside as I expected. I am trying to add the view in viewDidLoad-method.
Parent view bounds:
(0.0, 0.0, 336.0, 200.0)
I am trying to add a view as a subview of this parent:
let subView = UIView(frame: CGRect(x: 200.0, y: 0.0, width: 100.0, height: 20.0))
Answer:
How can I get a view's current width and height when using autolayout constraints?
Following the answer fixes the problem without me understanding it fully. Isn't the size of the view updated when laid out by auto layout? Why do I need to invoke this method?
Before I invoke this method the width of the view is 336 points and after I invoke it it is 215 points.
Related
I'm trying to put an uiview over the main view controller. The way i'm doing it, looks like this (the red view is the view, and the black one is the main view controller)
But i want it to look like this...
This is the code i have tried (the "viewww" is the red view)
viewww = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height - navBar.frame.height))
What i want is to have a space in the top (the height of a navbar) and not in the bottom when the "viewww" appears, but i don't know how to set the space in the top.
Thanks in advance!!!
This puts your view down to the height of the navBar
viewww = UIView(frame: CGRect(x: 0, y: navBar.frame.height, width: self.view.frame.width, height: self.view.frame.height - navBar.frame.height))
The cleanest way to do this, without hard-coding navigation bar heights, is to use autolayout. Constrain the view's leading and trailing edges to the superview's, and constrain the view's top and bottom edges to the top layout guide and bottom layout guide (or, if you're using iOS 11, the Safe Area edges). See https://useyourloaf.com/blog/safe-area-layout-guide/ for a fuller explanation.
I have a UIScrollView with several buttons in it. The buttons at the bottom of the scrollview are visible, but don't respond when they're pressed. My problem appears to be the same as the one in this Stackoverflow Question, but the accepted answer does not seem to solve my problem; the frame of the scrollview, the contentSize of the scrollview, and the frame of the view inside the scrollview (which is also the superview of the problematic buttons) all have width 414pt and height 900pt. That should definitely be large enough to encompass the buttons which aren't responding.
EDIT:
I created the scrollview in Interface Builder. The edges of the the container view within the scrollview are pinned to the edged of the scrollview.
I tried adding these lines of code:
scrolling.frame = CGRect(x: 0, y: 0, width: 414, height: 900)
viewInsideScrollview.frame = CGRect(x: 0, y: 0, width: 414, height: 900)
scrolling.contentSize = CGSizeMake(414, 900)
self.view.frame = CGRect(x: 0, y: 0, width: 414, height: 900)
Adding these lines didn't change how the scrollview looked or acted (scrolling fine, but with unresponsive buttons on the bottom.)
A UIScrollView infers its size by the view/views inside of it. You created your views in the interface builder so that could be why the lines of code you added did not work (I am not entirely sure why they did not). However, what will work is setting constraints on your viewInsideScrollview so that the scrolling expands to the full content size. For example, if you have 10 buttons in your viewInsideScrollview, you should set a top space constraint on the top most button, leading and trailing constraints, constraints to give spacing in between buttons, and a bottom space constraint on the bottom most button. The scrolling will expand to accommodate all of the buttons, and you will be able to select all of them.
Here is an image of what I'm envisioning.
Two bottoms at the bottom will always stay there. And height of textview and container view is dynamic. I will container another viewcontroller in container view. When sum of height of textview and container view is bigger than current viewcontroller's height, I want them to be scrollable.
I've been looking into 2 things: UICollectionView, UIScrollView.
However, I could not figure out how to make what I'm envisioning with those two components.
I also tried with stackview but that was not suitable for my purposes.
My gut tells me that UIScrollView is way to go but I cannot figure out. My current attempt was putting a scroll view and set the constraints to Nav bar and 2 buttons. Then, put textview and container view inside scroll view using storyboard.
If somebody can guide me a bit, that would be super helpful to me. Sorry for not containing any code, btw. I just couldn't even start :/
let margin = CGFloat(10)
let scrollView = UIScrollView(frame: view.frame)
let textView = UITextView(frame: CGRectMake())//Set textViewFrame
let containerView = UIView(frame: CGRectMake(x:margin, y: textView.height + margin, width: view.frame.width - 2 * margin, height: view.frame.height)
let button1 = UIButton(frame: CGRectMake(x:margin, y: textView.height + contentView.height + 2 * margin, width: (view.frame.width - 2 * margin) /2, height: 30)
scrollView.contentSize = CGSize(width: view.frame.width, height: button1.frame.origin.y + button1.frame.height + margin)
That should be enough to get you started. The important thing is adjusting the scrollView's content size to extend past the frame of the view. To test where this would get you you still need to add as subviews and you could also set backround colors different colors and adjust as necessary.
I got frustrated with AutoLayout so I decided to disable it and just set the positions and sizes of the elements in my view programatically. I tried this:
func setScrollViewBounds() {
var windowFrame = self.view.frame;
var scrollerHeigth = (windowFrame.height/100)*15
BottomScroll.frame = CGRect(x: CGFloat(10), y: windowFrame.height-scrollerHeigth, width: windowFrame.width-20, height: scrollerHeigth);
TopScroll.frame = CGRect(x: CGFloat(10), y: BottomScroll.frame.maxY-10, width: windowFrame.width-20, height: scrollerHeigth)
}
Im trying to set the two scroll views (TopScroll and BottomScroll) to be at the bottom of the page and have one be on top of the other. This however doesn't seem to do anything. Any ideas why?
I'm calling the function in ViewDidLoad().
TopScroll and BottomScroll are IBOutlets.
Apply constraint following order
Put your subviews in UIView Object(Which will subview of ScrollView).
Select Both ScrollView and UIView
Go->Pin->Equal Width.(Not Equal Height)
Select UIScrollView Go-> Pin uncheck Constraint to Margin and give Top,Bottom,Left,Right constraint.
Now Select UIView(Subview of UIScrollview say contentView) control click contentView to Main View(Default controller's View) and select Leading,Trailing,Top,Bottom constraint.
Finally Select contentView Go-> Resolve Auto-layOut issue -> Reset to Suggested constraints.
Constraints for subview of ContentView as usual with respect to contentView. use viewDidLayoutSubview for setting content-size to UIScrollView.
In the following function I define all the necessary characteristics of a UIView:
func OpenController() {
var gameOverView: UIView = UIView()
gameOverView.center = super.view.center
gameOverView.frame.size = CGSize(width: 200, height: 300)
gameOverView.backgroundColor = UIColor.grayColor()
self.view.addSubview(gameOverView)
}
Even though I define the center of the UIView "gameOverView" as that of the the viewcontroller it resides in, it appears with a corner in the center of the viewcontroller and not centered in the viewcontroller. I have tried various other ways of defining the position (NSLayoutConstraints, frame.x, frame.y etc.) but all have this result.
If anyone can tell me why this happens and how to center the UIView within its parent view controller I would greatly appreciate it!
Your issue here is that your center is being set before the frame. Since you are creating the view without the frame argument your frame is {0, 0}.
So you are currently centering the subview then resizing it, so this is happening:
What you need to do is resize the subview then center it, like this:
So you can just swap your centering and framing logic:
gameOverView.frame.size = CGSize(width: 200, height: 300)
gameOverView.center = super.view.center
Otherwise even easier just pass the frame when creating the view (you could even pass in the proper x, y coordinates to center it here too):
var gameOverView: UIView = UIView(frame: CGRectMake(0, 0, 200, 300))
You have to set the center of the view after setting its size. This is because before setting the size or frame of a view its frame rect is (x:0,y:0,width:0,height:0). If you then immediately set its center, then a view of size zero will get centered so its new frame rect could be (x:20,y:20,width:0,height:0) (if the parent view is 40x40). If you now change the view's size, the origin point of the view will not actually move so the new frame could be (x:20,y:20,with:5,height:5) which means the view is no longer centered.
So to center a view you have to first set its size and the its center.