In my navigation stack's child, I set edgesForExtendedLayout = .None
When I click the back button, the UITableView in my parent gets "moved up", as if the navigation bar doesn't exist. (The Navigation Bar covers the table).
Why does the child's edge setting affect its parent? I only want it to affect the current viewController.
In my parent, this is how I created the UITableView:
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.frame = CGRectMake(0, 0, screenWidth, CGRectGetMinY(self.tabBarController!.tabBar.frame))
self.tableView.addSubview(self.refreshControl)
self.tableView.tableFooterView = UIView(frame: CGRectZero)
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 100.0
self.tableView.clipsToBounds = true
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.SingleLine
self.tableView.separatorColor = UIColor(hex: 0xededed)
self.tableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0)
self.tableView.layoutMargins = UIEdgeInsetsZero
self.view.addSubview(self.tableView)
Could it be that I am setting the tableView's frame incorrectly? I want the table to start below the navigation bar, but end before the tab bar.
It sounds like this might be the correct behavior, but the opposite of what you are expecting.
edgesForExtendedLayout = .None means that the view controller's view will not extend under the top navigation bar or the bottom tab bar. You say that your child view controller is set to edgesForExtendedLayout = .None but not the parent view controller. And that when you go back to the parent view controller, the table view moves under the nav bar. If you did not set the parent view controller in your example to edgesForExtendedLayout = .None, then it will still be using the default of edgesForExtendedLayout = .All. And that will extend the top of the table view under the top and bottom bars.
For the behavior you are looking for, try setting edgesForExtendedLayout = .None on the parent view controller with the table view. So your parent view controller code could look something like this:
self.edgesForExtendedLayout = .None
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.frame = CGRectMake(0, 0, screenWidth, screenHeight - self.navigationController!.navigationBar.bounds.height - self.tabBarController!.tabBar.bounds.height)
UPDATE -- To implement the same result using auto layout (preferred over manual frames), first make sure that the table view is already added as a subview of the view controller's main view, then you can simply set up the constraints as follows:
tableView.topAnchor.constraintEqualToAnchor(view.topAnchor).active = true
tableView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor).active = true
tableView.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true
tableView.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true
Using these NSLayoutAnchor convenience methods assumes iOS 9 or above. Of course an even easier approach would be to create the view controller in a Storyboard and just ctrl+drag the constraints in place. Either way, whether the constraints force the table view under the nav bar and tab bar or not will still be controlled by the view controller's edgesForExtendedLayout property. In a storyboard, you can control those setting by checking these different boxes in the inspector for the view controller:
Related
I am trying to achieve the following navigation bar with two titles and an image:
Large title variant:
Small title variant:
I tried subclassing UINavigationBar and adding subviews to it, but they did not render at all.
I tried setting a titleView in storyboard, however it seemed like the titleView is constrained in its height.
What is the proper way to achieve this custom navigation bar?
I also tried this (and setting the viewController in Storyboard to that class):
class NavViewController: UINavigationController {
var titleView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
self.navigationBar.topItem?.titleView?.backgroundColor = .gray
titleView.frame = CGRect(x: 0, y: 0, width: 100, height: 300)
self.navigationBar.topItem?.titleView = titleView
}
}
Inside the ViewControllerin viewDidLoad, add self.navigationController?.navigationBar.addSubview(imageView). (no need for subclassing)
There is even support for AutoLayout inside UINavigationbar, which is great for animation.
Design your custom view seprately in a xib file, then set that xib as the titleview for your navigationbar
self.navBar.topItem?.titleView = logoImage
Do this for large title, for the smaller one only populate an image in the titleView.
I'm trying to make bottom slider menu containing a table view controller and a search controller inside of table view header. At this point, I added table view controller as a child view controller. After search bar is focused dimming view triggers but it covers screen main bound. What I expect is that dimming view stays inside the child view controller boundaries. I could not understand the reason why dimming view always added screen main bounds ? I have a screen shot to demonstrate the issue I have.
Thanks for your help.
class ChildTableViewController: UITableViewController {
lazy var searchController: UISearchController = {
let temp = UISearchController(searchResultsController: resultSearchController)
temp.dimsBackgroundDuringPresentation = true
return temp
}()
private var resultSearchController = ResultSearchTableViewController(style: .plain)
override func viewDidLoad() {
super.viewDidLoad()
prepareViewController()
}
func prepareViewController() {
self.tableView = UITableView(frame: .zero, style: .plain)
self.tableView.separatorStyle = .singleLine
self.tableView.register(ChildTableViewCell.self, forCellReuseIdentifier: ChildTableViewCell.identifier)
self.tableView.tableHeaderView = searchController.searchBar
self.definesPresentationContext = true
}
}
Screen shot
Even if its content appears over a child view controller context, the search controller itself is a presented view controller and prevents interaction with any other interface. Thus it makes sense that if you ask for the dimming view, the dimming view covers everything other than the search controller interface. If you don't like that, set obscuresBackgroundDuringPresentation to false.
(You should not be using dimsBackgroundDuringPresentation. Use obscuresBackgroundDuringPresentation instead.)
How make animation like ios default mail. I need the same effect like search bar is hide at initial and when i drag table view download the it shows the search bar.
like in the screenshot
update to the question.- Right now i am using a searchBar above tableview in the view controller.
var resultSearchController = UISearchController()
self.resultSearchController = ({
let controller = UISearchController(searchResultsController: nil)
controller.searchResultsUpdater = self
controller.dimsBackgroundDuringPresentation = false
controller.searchBar.sizeToFit()
workActivityTableView.tableHeaderView = controller.searchBar
workActivityTableView.contentOffset = CGPoint(x: 0, y: controller.searchBar.frame.height)
navigationController?.extendedLayoutIncludesOpaqueBars = true
return controller
})()
Drag search bar in to your tableview in your storyboard as it should be the first subview of your tableview!
Tableview will consider it as a header.
Your view hierarchy will be look like,
And the default size of search bar will be 44.
Now in your viewDidload set content offset of your table view like,
_tblView.contentOffset = CGPointMake(0, 44);
or in swift you can say,
tblView.contentOffset = CGPoint(x: 0, y: 44)
and you're done!
bellows are screenshot of results,
Initially
After scroll
This will not work if prefersLargeTitles set to true then initially you will get search bar!
I'd suggest you add the search bar as a tableHeaderView to your tableView, and in your viewDidLoad, add the following lines:
tableView.tableHeaderView = your_searchbar
tableView.contentOffset = CGPoint(x: 0, y: your_searchar.frame.height)
navigationController?.extendedLayoutIncludesOpaqueBars = true
UPDATE:
This can be easily achieved by adding the search controller as a part of navigationItem. Something like this:
self.navigationItem.searchController = searchController
This is available from iOS 11.
I have created a separate customView class containing collection view along with its Xib, and then i try to load this customView to one of the controller's view which is connected to a Tab Bar Controller. The view gets loaded perfectly but the last item of collection view is hidden behind the tab bar.
It would be great to have a solution for that.
My customView looks as
Try this
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let bottomOffset: CGFloat = (tabBarController?.tabBar.frame.height)! // this your tabbar height you can replace with static number eg. 44
collectionView?.contentInset = UIEdgeInsetsMake(0, 0, bottomOffset, 0)
}
Try to uncheck Under Bottom Bars..
It worked for me.
set
self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = YES;
self.automaticallyAdjustsScrollViewInsets = NO;
I'm trying to keep the search bar in view as the table scrolls. At the moment I'm placing it as the header in a tableview, and it works as it should, but of course the search bar scrolls off screen as you go down the table. I thought I could do this simply modifying this code sample:
How do I use UISearchController in iOS 8 where the UISearchBar is in my navigation bar and has scope buttons?
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.delegate = self
searchController.searchBar.delegate = self
searchController.dimsBackgroundDuringPresentation = false
searchController.hidesNavigationBarDuringPresentation = false
tableview.tableHeaderView = searchContoller.searchBar // How to put it elsewhere?
//Alternative that also works
navigationItem.titleView = searchController.searchBar
The idea was to take some other view and do
otherview = searchController.searchBar
For instance an outlet to a UISearchBar, or a blank UIView, or something like that.
But it doesn't show the searchBar if I do that. It seems to only work as the header view of a table or as a navigationItem.titleView.
Am I missing something?
If you have a blank UIView that is placed above the tableview.
let's assume you have an outlet to that blank UIView called searchContainer.
Then you can add the search bar of the UISearchController to that view by adding the following line
searchContainer.addSubview(searchController.searchBar)