Swift: TableViewController in NavigationController - Change distance between first static cell and top - ios

Ive created just a new xcode project without any coding. I just worked in the storyboard. There I have a Navigation Controller. My RootViewController has a TableView with Static cells in 3 sections (Grouped). The Section headers I deleted. My next step was to change the distances between the sections. For top I said 4 and for bottom 4, too. It looks now like this:
Now my problem: The size between the first section and the top is really big (I think 32 because thats the automatic distance between the sections). THe only place I found something was the size inspector - Content Insets. This is set to automatic. With no option I can put some values in myself. If I choose never there, the section got displayed under the Root View Controller header. My size inspector looks like this:
Can anyone tell me how I can reduce the size between viewController top and first section? Exactly I want to have a size of 16 between first section and the header of the Root View Controller.
And is there a way to do a change for the complete project so that also upcoming navigation controllers will have their tableview with a size of 16 between first section and the header?
What Ive tried: I found this question Why is there extra padding at the top of my UITableView with style UITableViewStyleGrouped in iOS7 Here someone asked for tableViews in general. The solutions I readed there which didnt worked for me:
Turn Adjust scroll view insets off. I tried this for the root as well as the navigation controller. I also tried to solve the problem in code.
Set edgesForExtendedLayout to none in viewDidLoad - nothing changed.
Set the header just for first section to 1.
self.navigationController?.navigationBar.isTranslucent = true changed nothing
Half correct: One solution was changing the contenInset manually in code. I dont like this because I would have to type the 16 points hard in my code. I dont know there the header of 32 comes from. So I dont know if the 16 points will stay forever. So I want a safer solution for future as well. THis was the hard solution:
self.tableView.contentInset = UIEdgeInsetsMake(-16, 0, 0, 0)

That top space comes from grouped style tableView header. You can add your own table header view at top of the table, set its color to "Group Table View Background Color", and set its height to what you want (16).

iOS11 Pure code Solution
Anyone looking to do this in pure code and remove the 35px empty space needs to add a tableHeaderView to their tableView - it appears having it as nil just sets it as default sizing of 35px
i.e.
tableView.tableHeaderView = tableHeaderView
var tableHeaderView:UIView = {
let view = UIView()
view.frame = CGRect(x: 0, y: 0, width: tableView.bounds.width, height: CGFloat.leastNormalMagnitude)
return view
}()
Note device width would be your bounds/view width and height is NOT 0 - but CGFloat.leastNormalMagnitude

Related

Why is there so much spacing between my tableview header and navigation controllers large title

So there is a lot of space between my TableView section headers and my Navigation Controllers Large title. I'm doing the EXACT thing for the two controllers and still there is a difference.
Already tried a lot but couldn't find a solution. What I've tried so far is:
Uncheck - Adjust scroll view insets.
tableView.contentInsetAdjustmentBehavior = .never
Setting the headers is the same with a switch case
Found out that there is an attribute in storyboard with Estimated Section Title Height, on some controllers it was 0 and some where Automatic. Setting everything the same solved it!
Theres an option to set it by code: (thanks B2Fq)
tableView.sectionHeaderTopPadding = 0.0

UITableView contentOffset for headerView misaligned

My headerView in my tableView should go all the way to the top of the device. On iPhone X the same so the notch goes over it.
Then when I scroll my tableView I use scrollViewDidScroll(scrollView: UIScrollView) to change the height of my headerView to add scrollView.contentOffset.y so it goes all the way.
It works as soon as I scroll but not initially.
So it looks like this:
and this on the X
How to I get rid of the white area so the grey one goes under it when it loads?
I tried a couple places but it seems the tableView still has no contentOffsets... I think I am missing something fundamental here how "it should be done"...
Update: ViewHierarchy, blue is tablewView, but then I get this distance there...
Ok I found it. So it has to do with the change with safe areas introduced for the iPhone X.
There are two possibilities, it really depends on the storyboard setup:
If you are using a storyboard and your base is a UIViewController with a tableView placed inside it:
Then fixing the auto layout is the answer:
When safe area is enabled, click on your topmost view and create the top constraint is relative to the superView with constant 0. By default it wants to protect the safe area so it is set relative to the safe area.
If you are using a UITableViewController template (e.g. default when dragging out a navigation controller - tableview combo (my case))
Here there are no constraints that can be set. Hence it didn't work for me (see above).
To fix it click on the root tableView, select the size inspector and then set "content insets" to "never".
Or programmatically in viewDidLoad:
self.tableView.contentInsetAdjustmentBehavior = .never
Are you making your tableview in storyboard?
in viewDidLoad try anchoring your tableview:
tableview.topAnchor.constraint(equalTo: view.topAnchor).isActive = true

MSStickerBrowserView stickers going out of frame

I am attempting to dynamically load stickers for a Messages Extension for iOS 10. I have successfully loaded these icons; however, they fail to properly constrain to the proportions of a message app.
In the compact view of a message extension, it has a footer. This can be seen here:
In the expanded view of a message extension, it has a header.
I am loading these stickers through a MSStickerBrowserView a subview of MSStickerBrowserView. I'm overriding the superclass methods of numberOfStickers and stickerBrowserView to load my images.
From what I can tell, the MSStickerBrowserView is just a wrapper for a UICollectionView.
Anyhow, after the stickers are loaded they are not being constrained to the header and footer. I've attached a gif of what I mean below:
As you can see, in the compact view the last row of stickers go under the footer. Accordingly, in the expanded view the top row of stickers go under the header.
As an experiment, I implemented the same dynamic sticker system but with an actual UICollectionViewController and UICollectionView (instead of the MSStickerBrowser wrappers) and the same effect was achieved. Further more, I attempted to create a custom layout for this but it produced the same result.
I would prefer to stick to the MSStickerBrowserView, since it was already made for this purpose; however, if you see the UICollectionView more fitting I would be willing to change.
Note that with the use of the MSStickerBrowserViewController and View, the UICollectionView seems to be created programatically, so storyboard constraints are not available and I have not been able to apply any programatic constrants to the cells of the views.
I'm not really sure how to fix this, and would love any suggestions.
The way I fixed this was to use a UICollectionViewController with a state variable to represent the current presentation style (.expanded or .compact) which I set at presentation time.
Then in viewWillAppear for my UICollectionViewController, I set the collectionView's contentInset depending on the presentation style
if let style = self.presentationStyle, style == .expanded {
collectionView?.contentInset = UIEdgeInsets(top: 95, left: cellPadding, bottom: cellPadding, right: cellPadding)
}
cellPadding is a number I've computed after setting the itemSize in my collectionViewLayout but the value of 95 is just a guesstimate/kludge as I haven't yet found out how to get the size of the containing iMessage top nav bar.
Try Uncheck below options for your view controller:
Under Top Bars
Hope it will work....
You can try using storyboard to layout view and add a empty view under the browserView to solve

iOS: Top UITableView row bleeds into carrier

The alignment of our table is working well except of the top alignment of the top cell which bleeds into the "carrier area". What is required to address this?
We're using self sizing cells:
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 68.0
tableView.rowHeight = UITableViewAutomaticDimension
Overview of the current constraints:
Basically Apple doesn't want you to do what you're doing. Look at Apple's apps (Settings, Mail, etc.). You will never see a full-screen table view without a navigation bar at the top. So imitate that. Instead of fighting the framework, wrap your view controller in a UINavigationController and let the navigation bar push the top of the table view down for you automatically.
Normally when you use a navigation controller to wrap the view controller, TopLayoutGuide (and BottomLayoutGuide will be set for you and with "Adjust Scroll View Insets" that you can set in the storyboard file, it will automatically set contentInsets of the outermost scrollview for you to accommodate that. But since you don't use a navigation controller to wrap your view controller here, you have like three options.
1. Manually set the frame of the table view to offset for the status bar's height.
We just move the table view down 20 points and make it 20 points shorter. The ideal place is somewhere in your code we know it will be called every time the superview's bound is changed. One of them is in viewDidLayoutSubviews.
Try putting this code in your view controller's code.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.view.superview!.backgroundColor = UIColor.whiteColor()
let insets = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
self.view.frame = UIEdgeInsetsInsetRect(self.view.superview!.bounds, insets)
}
Please note that I have to set the background color of the superview's to white because the superview (which is likely to be UIWindow) might have no background color and it will make the top part appears black. And normally in the production code, you might want to check whether the superview's bound has really changed before setting the frame.
2. Use UIViewController and add UITableView as subview.
This way Interface Builder will allow you to set the constraints all you want.
3. Just wrap this with UINavigationController
And it will appear like most apps that have a navigation bar on the top. This might not be what you want. But I rarely see a table view without wrapping by a navigation controller.
Select your table view. In the bottom right side of your screen (left of where you drag the objects to the screen) you will see 4 small buttons. If you click on the 2nd to the right (a square with 2 lines to it's sides) you will see a small sub-menu saying Add new constraints. Below it you have a square with 4 values (top-right-bottom-left). Make sure the top one is 0 and then click the semi-transparent dotted red line. It should become solid red. Now just click the "Add constraints" button at the bottom and you are done.

Adding margin to TableViewController

I am experimenting with Xcode 6 and Swift and having a little issue with the Interface Builder.
I created a new scene by dragging a TableViewController which comes with a TableView however when run it on a simulator the top cell is far too close to the top, it almost touches the central Date and Carrier logo.
As this seems to be a root view, I cannot add constraints, I also cannot find a way to adjust so that I have a margin that is flexible / responsive to different screen size.
You don't want to try to constrain the table to underneath the status bar, as this will cause the content of the scroll view to magically vanish as it goes above the 20pt mark. Instead, allow it to continue to be full screen and simply set the table's contentInset property (More info in documentation).
This will cause the table to scroll as it normally would with the content going out the top of the screen, with the added ability to come to rest just under the status bar.
let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.height
tableView.contentInset = UIEdgeInsetsMake(statusBarHeight, 0.0, 0.0, 0.0)

Resources