In my app I have a screen where I use a UIScrollView containing a UIStackView and multiple UITableViews to horizontally scroll through different kinds of content.
I have a problem with the iPhone X where the first tableviews left side and the last tableviews right side are inset correctly to give room for the iPhone X safe area. However, the right side of the first tableview, the left side of the last tableview and both sides of all tableviews in between are not correctly inset.
Question: What is the correct way to apply the inset to both sides of each tableview?
Update 1
While at the first look, the solution suggested by Sh_Khan (using leading/trailing constraints to the safe area on the container UIScrollView) looks quiet good, it is not actually what I would like to achieve. As you can see, the cell separators are not going all the way to the edge of the screen and when scrolling from one tableview to the next, the white bars where the safe area is are clearly visible.
I need to somehow inset the tableviews cell content views just like the system does it but I'd need to do it for every tableviews cell. Does anybody know how the system actually achieves this?
Related
I have a simple screen, with a slider and a label positioned next to each other horizontally. I have embedded these inside a UIScrollView (I set this to fill the screen and used 'Add missing constraints'), because I will need vertical scrolling later down the line. I don't however, want horizontal scrolling. I have seen numerous posts on here and other sources about people wanting to disable horizontal scrolling, however I'm not sure that's what I want to do, I think I need to restrict the UISlider from causing the horizontal scrolling; I think it is trying to take up more width than the screen. I have added what I think are the necessary horizontal constraints:
Leading space to container for the UISlider
Horizontal spacing to the UILabel, and
Trailing space to container for the UILabel
But this still causes horizontal scrolling, and the UISlider's are the cause, they are taking up more room than I want, as seen below:
I have tried disabling horizontal scrolling in the code using a few techniques, one being:
func scrollViewDidScroll(scrollView: UIScrollView) {
if scrollView.contentOffset.x>0 {
scrollView.contentOffset.x = 0
}
}
but this does not seem to stop the horizontal scrolling.
Can anyone offer any suggestions?
Thanks in advance.
My suggestion is to never use Add missing constraints. It never does what you really want.
Here's the problem. You are laying out your UI on a ViewController in the Storyboard that is square. Apple did this to remind you that you need to be flexible in your design, but it doesn't match the size of any device. When you Add missing constraints, it uses the absolute dimensions of that square to create the constraints which are certainly wrong.
In your specific case, it is giving the slider a width that is too wide, which is why the slider goes off the right side of your screen.
Here's the trick about scroll views. If the contents inside of a scroll view are wider than the scroll view itself, then that content will scroll. The same applies vertically: if the contents inside of a scroll view are taller than the scroll view, then the contents will scroll.
In order to design this to work on all phones, you need to make sure that the contents of the scroll view are laid out correctly for each phone size. Which certainly means you don't want to use specific widths for both the label and the slider because you'll end up with the wrong width for some device, if not all of them.
The best way to do this is to:
Drag out the scroll view and add it to your ViewController. Add constraints to make sure it is properly sized on all phones, such as attaching it on all sides to its superview with a fixed distance.
Drag out a new UIView and drop it on the scroll view. Drag its edges until it exactly matches the size of the scroll view. This will be your content view. Pin all four edges of this content view to the scroll view with offsets of 0.
Here's a tricky bit. Even though you've pinned the content view to the scroll view, its size of free to grow because that is what allows it to be bigger than the scroll view itself and allow there to be content to scroll over. To keep your scroll view from scrolling horizontally, you need to make sure the content view has the same width as the scroll view on all devices. To do that, find the scroll view and the content view in the Document Outline to the left of the Storyboard. Control-drag from the content view to the scroll view and select Equal Widths from the pop-up.
You still haven't told your content view how tall it should be. For now, give it an explicit height constraint of 1000. That will be enough to scroll.
Now, add your label and slider to the content view. In addition to constraining them to each other and to the edges of the content view, you will need to give your label a width constraint. Then Auto Layout will have all of the information it needs to compute the width of your slider. Auto Layout knows how wide the content view is (which will be different on different devices), it knows how wide your label is, and how far everything is from everything else, so it will just stretch the slider to fill in the rest.
If you do all of this, you will have a UI that is properly sized for all devices in all orientations that scrolls vertically.
Just embed all view in your UIScrollView in a UIView, give it the required constraints then the slider and label will stay.
That worked for me just now.
UIScrollView is special when you want use AutoLayout with it, subviews can not be added directly, it needs a container view to constraint the contentSize of UIScrollView, Auto Layout Guide:Working with Scroll Views explains the detail reason, and you can find many solutions to solve UIScrollView's auto layout on Google, Such as this answer.
To be honest, it's confused and complicated to understand UIScrollView's auto layout, but if you overcome this, others auto layout question is easy to resolve.
I just started iOS programming and I want to make a login screen. I want to align center horizontally the everything on all devices like the iPhone 5 and iPhone 6 and iPhone 6 Plus but it's not working. I just put the elements on the screen. Anything else i need to do?
There are a few ways you can do this...auto layout as #ozgur said is your friend.
what I would do is throw them into a Stack View
To do that tap each horizontal group so for example "username" label AND the text field to the right and while they are both selected tap the icon at the bottom right that is on the left of the 4 icons (it has a downward arrow)...now do the same for the password...now do the same for the login button...now select all 3 stackviews and tap stackview again...
NOW....on the left navigation select the topmost stackview and then again on the bottom this time tap the small icon to the right of the stackview button...to make it simple and in the center tap horizontally in container and vertically in container then add the 2 constraints....
you will also need a height and width so now once more with the whole thing selected tap the |o| looking icon to the right...now give it the height and width you like but before you tap add 2 contraints at the bottom of that menu is a drop down menu..tap it and select "update all frames in container"
that should do it
Use AutoLayOut Constraints to fix your issue.
Contraints will set the spacing with the view.You have to apply it on every single element of your view.
if you only want every thing in center no different spacing for different iPhone use stack View. it will provide the best solution for you.
stackView means collection of your objects. it act as group of your elements so only apply constraints to your stackview.
Rule of thumb is to use Stack views and then use auto layout. Just put the Username and the text field in a stack view (horizontal stack view), same for the other) and then apply necessary spacing and/or autolayout constraints.
You need to learn how to work with Autolayout (I read you just started) and it could be hard concept to grasp at first (it was for me at least) but with practice, you'll master it.
If you do not use the stack view, you need to learn auto layout and size class for adapting the screen.
auto layout began in iOS 6, sizeclass began in iOS 8.
Here is the official apple documentation, to study it. https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/
I've read quite a few tutorials and watched numerous videos on using constraints in Xcode. For some reason, I'm still missing certain aspects that are necessary to make the user interface look the way it's supposed to for all screen sizes.
Currently, I have a UITableView laying on a view controller. The view controller is set to "Inferred" size and I have all of the different sized devices open in Assistant Editor Preview to the right so I can view the changes. I've encountered multiple problems attempting to get the constraints correct for the different screen sizes.
Problem 1: The UITableView has a width set to 600. This causes dead space to the right of the table view on the iPad preview and it causes the UITableView to extend too far on the smaller devices. If I make the width of the table view smaller so that it fits within the preview of all screen sizes and then pin the left and right edges of the table view to the edge of the Superview by specifying 0 and unchecking constrain to margins, the result I'm seeing in preview is that the entire table view disappears completely from each device size. I was surprised by this because I thought by pinning the table view to the margins, it would make the table view fit within each of the screens.
Problem 2: (This is a completely different scenario from Problem 1, above.) In this situation, I've left the size of the table view to 600 and just specified constraints for the internal components of the cell contained within the tableview. In this case, the table view is still slightly not wide enough for the iPad dimensions and it extends too far on the smaller devices which makes components in the cells to be truncated and off of center.
I've primarily been working in Storyboard with Any width, Any height set. However, if I change the setting to Compact width, Any height, I can alter the constraints to fit the smaller devices a little better, but there's still a problem with getting things to work between the 5.5 inch screen and the smaller devices.
I would like to get my UITableView to extend all the way to the edges on each device and I would like to have the view inside of the cell remain centered and keep it's relative size on each of the devices. Does anyone have any suggestions on how I can accomplish this?
if you want to make your tableview to "fill" the whole screen (device-independent) the only thing you have to do is to pin its 4 edges (top, left, bottom, right) to its superview (the viewcontrollers view in your case) with a constant of 0.
you do not specify a specific width (like in your case 600) or height.
good luck :)
I'm having a problem with auto layout in XCode 6. I have 2 buttons in a view - the buttons overlap each other. I've tried spacing them out further from each other in storyboard, I've also tried resetting onstraints on them, various combinations of constraints on them, and various constraints on the View Controller. None of this seems to work, they always seem to overlap each other, when I want to have at least some space between horizontally.
I'm attaching a screenshot for reference. Thanks for any advice on this.
There is no way in AutoLayout to set an even number of items to be equally spaced from the center of the superview. You will need to create a clear placeholder view between them, center it in the superview (and give it constraint-based height width), then set each button to be horizontally offset from that.
I have a grouped UITableView that was really designed to look nice in portrait mode for iPhone. Its cell subviews have autosizing set up so that they stretch in landscape mode, but this makes it a lot less aesthetically pleasing -- the cells just look too wide for their content.
I'm now making it a universal app but on iPad the autosizing causes even more stretching and it looks just unacceptable.
It would be ideal if I could make the UITableView's groups of cells have a fixed width (or a max width), or if I could somehow control the horizontal margins.
Having not found support for this in UITableView, I have done a few quick attempts at subclassing it to constrain its size at layout time and, as an alternative, at introducing a container view in order to make the UITableView autoresize vertically only. Both approaches work but create new problems: Scrolling doesn't work when swiping in the margins, and I am now forced to make the UITableView's background transparent (which goes against Apple's recommendations) as there is now a discontinuity of background between the UITableView's frame and the margins.
Has anyone found a trick to solve my problem (i.e. constrain the width of the groups in a UITableView, causing margins to expand to fill the width of the view), or an open source solution to it?
Good news! I finally found a way to achieve this satisfactorily with only tiny code changes:
Shrink the cells by subclassing UITableViewCell and overriding -setFrame, as per the solution to this post:
How to set the width of a cell in a UITableView in grouped style
And to add vertical padding, using the contentInset property of the UITableView (inherited from UIScrollView) works pretty well.
You can always keep the standard table view and provide custom backgrounds with transparent sides for the table view cell's so that they look smaller than they are.
Cocoa With Love has a great article on how to do that here: Easy custom UITableView drawing.
The basic gist of the article is that you need to make six different versions of the backgrounds, and supply the correct one when tableView:cellForRowAtIndexPath: asks for a cell. You will need one with rounded corners at the top (for the first row of a section), one with rounded corners at the bottom (for the bottom row of a section), and one with all four corners rounded (for when there is only one row in the section). Then you will need the same three, but customized for the "selected" version of each row.