TVOS : Adjust the position of searchbar in UISearchViewController - swift

I am developing an TVOS app. I use below code to implement search feature in UITabBarController. The issue when tabbar is displayed then search bar is covered by tabbar. See below screenshots. is it possible to move searchBar position down if tabbar gets displayed?
let searchViewController = VVSearchViewController()
let searchController = UISearchController(searchResultsController: searchViewController)
searchViewController.searchViewController = searchController
searchController.searchResultsUpdater = searchViewController
searchController.obscuresBackgroundDuringPresentation = true
let searchPlaceholderText = "Search"
searchController.searchBar.placeholder = searchPlaceholderText
searchController.searchBar.tintColor = UIColor.black
searchController.searchBar.barTintColor = UIColor.black
searchController.searchBar.searchBarStyle = .minimal
searchController.searchBar.keyboardAppearance = .dark
searchController.view.backgroundColor = UIColor.black
searchController.definesPresentationContext = true;
UISearchContainerViewController(searchController: searchController)

It is possible.
It took me a while but my idea was to add the search controller into a "container" controller with constraint at the top. Nothing will appear if you try adding UISearchController as child view controller into the container. UISearchContainerViewController doesn't work as well. But a navigation controller with UISearchContainerViewController as root works. Here is my code:
// Create the search controller and it's results controller
let resultsController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SearchResultsViewController") as! SearchResultsViewController
let searchController = UISearchController(searchResultsController: resultsController)
searchController.searchResultsUpdater = resultsController
// Customize it
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [.foregroundColor: UIColor.text]
searchController.searchBar.placeholder = NSLocalizedString("Search", comment: "")
searchController.searchBar.tintColor = .text
searchController.searchBar.barTintColor = .text
searchController.searchBar.searchBarStyle = .minimal
searchController.searchBar.keyboardAppearance = .dark
// Embed it in UISearchContainerViewController
let searchContainerViewController = UISearchContainerViewController(searchController: searchController)
// Make UISearchContainerViewController root controller of a navigation controller
let navController = UINavigationController(rootViewController: searchContainerViewController)
// And a container to hold everything
let containerViewController = UIViewController()
// Do a standard child add of navController into containerViewController
navController.loadViewIfNeeded()
navController.viewWillAppear(false)
navController.willMove(toParent: containerViewController)
containerViewController.view.addSubview(navController.view)
navController.view.frame = containerViewController.view.bounds
// Add your constraints. In this case I just want the search bar to be 150 px down.
NSLayoutConstraint.activate([
navController.view.topAnchor.constraint(equalTo: containerViewController.view.safeAreaLayoutGuide.topAnchor, constant: 150),
navController.view.leftAnchor.constraint(equalTo: containerViewController.view.safeAreaLayoutGuide.leftAnchor),
navController.view.bottomAnchor.constraint(equalTo: containerViewController.view.safeAreaLayoutGuide.bottomAnchor),
navController.view.rightAnchor.constraint(equalTo: containerViewController.view.safeAreaLayoutGuide.rightAnchor)
]) containerViewController.addChild(navController)
containerViewController.addChild(navController)
navController.didMove(toParent: containerViewController)
navController.viewDidAppear(false)
// And from here use the containerViewController as normal to display a search into your app.
Note: Without passing the viewDidAppear on the navController this will not work.
Note 2: I tested this on tvOS 13 and 14 only.

You can find exactly the same case in the tab Search of the application "App Store".
This is because in tvOS the content of a viewController is not supposed to react to the visibility of the tab bar. The tab bar is presented instead on top of it, overlapping.
tvOS Human Interface GuideLines for Tab Bars:
https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/tab-bars/

Related

How to achieve the auto-shrink SwiftUI Navigation Title with UIKit?

I am trying to achieve the auto-shrink large nav title like the Navigation Title in SwiftUI, but no matter what my nav title always stay shrinked and never appear in large title mode. How do i fix this? (code below)
func setup() {
table.translatesAutoresizingMaskIntoConstraints = false
table.dataSource = self
table.delegate = self
table.register(UITableViewCell.self, forCellReuseIdentifier: "mycell")
table.separatorColor = .white
table.backgroundColor = .black
let appearance = UINavigationBarAppearance()
appearance.titleTextAttributes = [.foregroundColor: UIColor.black]
appearance.largeTitleTextAttributes = [.foregroundColor: UIColor.black]
appearance.configureWithOpaqueBackground()
navigationItem.title = "Todo List"
navigationItem.scrollEdgeAppearance = appearance
navigationItem.standardAppearance = appearance
view.addSubview(table)
}
As well as providing a configuration for large titles, you need to instruct your navigationController to use large titles
navigationController.navigationBar.prefersLargeTitles = true
The default configuration for a view controller should be to automatically use large titles if that is the preferred choice. However you can set it explicitly per view controller:
navigationItem.largeTitleDisplayMode = .always // or .automatic or .never
If the nav controller has prefersLargeTitle = false then large titles will never be displayed whatever the largeTitleDisplayMode setting.

Why is the search bar pushing the navigation bar out of the picture?

I added a UISearchBar programmatically to my view and every time you activate the searchBar the navigation bar is pushed out of the picture.
My view's hierarchy
searchController.searchBar.delegate = self
navigationItem.title = navigationItem.title ?? ci("plan_p")
tableView.rowHeight = 100.0
tableView.tableHeaderView = searchController.searchBar
tableView.setContentOffset(CGPoint(x: 0.0, y: (self.tableView.tableHeaderView?.frame.size.height)!), animated: false)
guard let projectId = GlobalState.selectedProjectId, let byProject : Results<Structure> = self.by(projectId: projectId) else { return }
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Suche nach Plan"
definesPresentationContext = true
Probably your UITableView is top of the view hierarchy (or more components in top of the view hierarchy).
If your tableView in top of the view hierarchy you should change the tableView's hierarchy in your Interface Builder for solve this issue.
You can simply put your tableView in another UIView component for solve this issue.

No navigation bar or any navigation bar attributes are showing up in view controller

I have a view controller that I want to have a navigation bar with a title and button to the right of the title. But for some reason the navigation bar is not showing up.
In the app delegate I added:
window?.rootViewController =
UINavigationController(rootViewController: MessagesController())
UITableViewCell.appearance().textLabel?.textColor = UIColor.white;
UITableViewCell.appearance().backgroundColor = UIColor.clear
UIApplication.shared.statusBarStyle = .lightContent
UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor : UIColor.white]
UINavigationBar.appearance().barTintColor = UIColor(red:0.13, green:0.15, blue:0.18, alpha:1.0)
UIApplication.shared.isStatusBarHidden = false
In the viewDidLoad of the view controller I want to have the navigation bar this is my code:
override func viewDidLoad() {
super.viewDidLoad()
let dummyViewController = UIViewController()
dummyViewController.view.backgroundColor = .white
dummyViewController.navigationItem.title = "TEST"
navigationController?.navigationBar.tintColor = .white
Why is there no navigation bar and why can't I add a title with buttons to it? Any help is welcome Thank You.
I once ran into the same issue with a dark UINavigationBar. Try to add this line in your viewDidLoad:
self.navigationController?.navigationBar.barStyle = .black
This solved the issue for me. Let me know if it helps.

Scope buttons hide under search bar on iOS 11

I have a search controller in my app which according to apple documentation on iOS 11 has to be added to the navigationItem's searchController property. I also have some scope buttons for the searchController. Everything works fine but when I rotate my device to landscape and rotate back to portrait then a wired thing happens. The scope buttons gets hidden under the search field. If I press the cancel button and tap on the search field again then it comes back to the normal state. The bug reproduces everytime only on iOS 11. The searchbar will look like this:
The normal state of the search controller:
This is how I add the searchController:
searchController.searchResultsUpdater = self as UISearchResultsUpdating
searchController.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.tintColor = UIColor.black
searchController.searchBar.sizeToFit()
searchController.searchBar.placeholder = "Search device"
searchController.searchBar.scopeButtonTitles = ["Device", "Person", "OS version", "Serial"]
if #available(iOS 11.0, *) {
self.navigationItem.searchController = self.searchController
self.navigationItem.hidesSearchBarWhenScrolling = false
if let textField = searchController.searchBar.value(forKey: "searchField") as? UITextField {
if let backgroundView = textField.subviews.first {
backgroundView.backgroundColor = UIColor.white
backgroundView.layer.cornerRadius = 10
backgroundView.clipsToBounds = true
}
}
} else {
tableView.tableHeaderView = searchController.searchBar
}
searchController.searchBar.delegate = self as UISearchBarDelegate

How to set the searchBar as the global focus for Siri on the Search Page?

Description
In my tvOS application, I have a search page with on top a Search Bar and under a Table View with the eventual list of results.
While we are focusing the searchBar and the user presses the voice for Siri, the results get inserted into the Search Bar (as expected). However, when the user is scrolling down through the results and is unable to find what they're looking for, they have to scroll up (all the way back up) to the searchBar to use Siri again.
If the user attempts to use Siri while the searchBar is NOT in focus, a global Siri starts looking for results in different apps (which is not what I want)
Question:
How to set the searchBar as the global focus for Siri on the Search Page?
What I've tried:
To be honest I have no idea how to go about this..
A function is called in AppDelegate.swift to create the Search View Controller and add it to the Tab Bar Controller.
I've thought about trying preferedFocusView but after reading the documentation, I doubt that's going to work.
func configueSearchController() -> UIViewController {
let storyboard = UIStoryboard(name: "Search", bundle: nil)
guard let searchResultsController = storyboard.instantiateViewController(withIdentifier: SearchViewController.storyboardIdentifier) as? SearchViewController else {
fatalError("Unable to instatiate a SearchResultViewController from the storyboard.")
}
/*
Create a UISearchController, passing the `searchResultsController` to
use to display search results.
*/
let searchController = UISearchController(searchResultsController: searchResultsController)
searchController.searchResultsUpdater = searchResultsController
searchController.searchBar.placeholder = NSLocalizedString("Enter keyword (e.g. Gastric Bypass)", comment: "")
searchController.view.backgroundColor = Constants.Color.backgroundcolor
searchController.searchBar.keyboardAppearance = UIKeyboardAppearance.dark
searchController.searchBar.tintColor = Constants.Color.backgroundcolor
searchController.searchBar.backgroundColor = Constants.Color.backgroundSearchBarColor
searchController.searchBar.setTextColor(color: .white)
searchController.hidesNavigationBarDuringPresentation = false
searchController.obscuresBackgroundDuringPresentation = true
searchController.searchBar.searchBarStyle = .minimal
searchController.searchBar.sizeToFit()
searchController.searchBar.focus
//TODO: Check if this works
searchController.searchBar.accessibilityLanguage = "en"
//searchResultsController.tableView.tableHeaderView = searchController.searchBar
// Contain the `UISearchController` in a `UISearchContainerViewController`.
let searchContainer: UISearchContainerViewController = UISearchContainerViewController(searchController: searchController)
// Finally contain the `UISearchContainerViewController` in a `UINavigationController`.
let searchNavigationController = UINavigationController(rootViewController: searchContainer)
searchNavigationController.navigationBar.isTranslucent = true
searchNavigationController.navigationBar.tintColor = Constants.Color.backgroundcolor
searchNavigationController.tabBarItem.title = "Search"
return searchNavigationController
}
Please read http://nerds.airbnb.com/tvos-focus-engine/ to make controls focusable.