I have an UITableViewController with an iAD banner on top, under the top bar.
When banned is loaded and device is in portrait it looks good but, when there's no banners or device turn in landscape, between top bar and the first tableView's row there's an ugly empty space.
The best solution would be to move the TableView up but I can't find a way to do that; the best solution I thought was to try resizing the header of section 0 of table's but I can't go under 0; and 0 is too much!
Is there another way to move table, for example, 10 pixels up?
The table view's content inset property can be used to add a padding around its content view. If you set the top for 10 for example, there will be some padding between the table view's top, and its content's top.
Using Swift, you can set the tableView.contentInset.top property directly. In Objective-C, you can set it like so:
self.tableView.contentInset = UIEdgeInsetsMake(10, 0, 0, 0)
Related
I'm trying to create a custom dialog with a UITableView inside.
What I want to achieve is to have the lowest height possible, meaning it should be only wrapping the tableview.
BUT when the tableview has too many items (meaning its height is bigger than the screen), I want the dialog to have 20 px margin from the screen top and bottom.
So if the tableview has 2 items, the height of the dialog should be for example 20 px. But if the tableview has 200 items, the height of the dialog should take almost the entire screen height and have its content scrollable.Dialog with few items
Dialog with multiple items
Currently if the tableview has multiple items, I can only see some items and the top and bottom of the dialog disappear.
Thanks.
EDIT: I forgot to mention I intend to achieve this using the storyboard only, using constraints and changing priority in content hugging and compression.
GOT IT WORKING!
All I had to do was change the top and bottom constraints from "=" to ">=".
So now it allows the dialog to have a smaller height but not bigger than the screen. No code needed.
Thanks everybody for your help.
My answer will include several parts. They are solving a more general question of how to efficiently work with dialogs.
To create dialog use UIViewControllerTransitioningDelegate, UIPresentationController and UIViewControllerAnimatedTransitioning. It's a long way, but it will make your dialogs presentation reusable.
To determine size of the dialog with table inside of it, set peferredContentSize property of your dialog view controller. This property will be used by UIPresentationController to set dialog height. Before setting peferredContentSize you can adjust the height to the margins you like.
To calculate size of table view you can use several options. table.layoutIfNeeded() worked for me.
Update: check out the article I wrote about this approach.
You need to set the tableView height dynamically, so give it two position constraints (ie centerX, centerY), a fixed width constraint, and then a height constraint set to some arbitrary constant (0). Take an outlet to the height constraint. Whenever you update the data that backs the tableview you take the min of the calculated tableview height and the superview height and set the height constraint constant to that value, then call setNeedsLayout on the tableView's superview. This way the tableview will either be the height of its content, or if the content is too big, the height of the superview and it will scroll.
tableViewHeightConstraint.constant = min(superview?.bounds.size.height ?? 0, numberOfCells * heightPerCell + headerAndFooterSize)
superview?.setNeedsLayout()
I guess that you know how many items you have before present the dialog and I guess that you dialog is a custom view (xib)
if this premises are true, you can resolve whit this line.
let dialog = CustomDialog(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: (heighCell * elements) + (heightButtonClose) + (heighTitle))
dialog.center = self.view.center
let me know if you have doubts
In a regular app, in the initial viewController, if I add two UIHorizontalStackViews, and add two buttons to each, and set their heights to be 0.5 of the view, while setting the left, top, and right properties to 0, they behave as we expect:
However, if I do this exact same process on a custom keyboard extension that uses a viewController, I get this:
You would think that it would make each UIHorizontalStackViews take 50% of the keyboard height, but no the keyboard shrinks and the buttons get smaller.
I then tried adding one single vertical stackview, that had 4 rows of horizontalstackviews, making it have height of 1.0 of it's view, and margins of left 0, top 0, right 0, in this case, the window ended up taking far more than half of the screen, more than the custom keyboard's height is allowed to be.
Not sure if this is a bug or what. I was assuming autolayout would be adjusting the keyboard height depending on screen orientation, and phone model.
I am trying to replicate something similar to Android's collapsing toolbar (see this link to understand the effect I am trying to achieve). I found a nice turnaround here.
My main UIScrollView is named fgScrollView and the secondary which is pinned on top is named bgScrollView. The whole UIViewController is embedded in a UINavigationController.
I pin the fgScrollView to the Container View. I pin the bgScrollView top, right and left to the fgScrollView and I give it a steady height of 220, and I place inside the bgScrollView a UIImageView which I also pin to all sides and I give it a height of 220. (All pins are with 0 distance)
This is how it looks from the IB (the UILabel that you see in the hierarchy is placed there to give a scrollable height to the fgScrollView):
In the scrollViewDidScroll method I set:
bgScrollView.contentOffset.y = scrollView.contentOffset.y * 1.4
(I have already set only the fgScrollView to be the delegate and I chose the 1.4 randomly) and in Interface Builder I choose the Adjust Scroll View Insets option.
The result is this in the beginning:
but as soon as I click to scroll up this happens (you can see the gap - it stops being pinned to the top):
From thereon it stays like that when I scroll to the top.
I uncheck the Adjust Scroll View Insets option and a strange thing that I notice is that the image does not go under the navigation bar, although I have checked the options Under Top and Bottom Bars:
And when I start scrolling this happens:
and it stays like that even when I scroll back to the top.
I tried to fix the issue programmatically. I add the navigation bar and status bar heights and I declare this:
fgScrollView.contentInset = UIEdgeInsets(top: CGRectGetHeight((self.navigationController?.navigationBar.frame)!) + CGRectGetHeight(UIApplication.sharedApplication().statusBarFrame), left: 0,
bottom: CGRectGetHeight((self.navigationController?.toolbar.frame)!), right: 0)
and the result is this:
Any clues?...
I would like to achieve the following view layout:
A UITableView in the middle of my UIViewController's view. As shown, the rows should not be as wide as the view - that's easy: just make the table view smaller, which is what I did for the screenshot.
However, as can be seen in the screenshot, this means that scrolling can only happen in the middle of the view. If a user tries to scroll by dragging on the grey areas left and right of the table view, nothing happens. The UI feels unresponsive.
So: is there a way to have both:
Width of the table view equal to width of the enclosing view.
Width of the cells smaller than the width of their table view.
I have tried to achieve this by setting the contentInset:
tableView.contentInset = UIEdgeInsetsMake(0, 50, 0, 50)
but this just makes contentSize bigger, ie the cells are still as wide as the view but you can now scroll left and right as well.
Insert subview in cell content and make it as wide as you wish. Then make cell content view transparent and you are ready.
I have Table View in my Storyboard. So let's so I know I'm going to have a total of 5 rows. Those 5 rows to not take up the entire screen space vertically, so I would like the group of those 5 rows to be centered vertically on the screen, instead of starting from the top and having all the blank space on the button because there are only 5 rows.
How do I accomplish this (1) Using Storyboard or (2) using code?
you could use UIScrollViews contentOffset-property, since UITableView inherits from UIScrollView. Here is a link to the docs:
https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UIScrollView_Class/Reference/UIScrollView.html#//apple_ref/occ/instp/UIScrollView/contentOffset
Essentially you just set a Point to define the X- and Y-Offset. So if you want the TableViews content to be offset by 100pts from the top, you would set
myTableView.contentOffset = CGPointMake(0, -100); //(edited in response to Lavvo's comment)
and thats it!
EDIT: Since its a property, there is a chance that you can set it in Interface Builder, but i cant check that right now. If so, its probably in the "Sizes"-Panel, i would guess.
If your table view has a static height, the easiest thing to do in a storyboard is to set the height constraint of the table view to however tall you want it. For example, if your cells are 44, 5*44 = 220.
Then add a constraint to your table view to have it centered vertically in its container.
This will make it compatable with any screen size as auto layout will automatically center it in the view container no matter what size it changes to.