How to create a search bar with mic icon in iOS 13? - ios

In iOS 13, search bars in all Apple apps have a mic icon on the right that allows for voice input. However, when I create a system search bar (or UISearchController), I don't get the mic icon. I've searched on Google and SO and couldn't find the answer - is it something we can adopt, and if so how?

One important note is that currently there is not a way to programmatically put the user into "Dictation mode". This means to implement this, your must use the Speech framework in order to get "speech-to-text" working from a button press.
You can accomplish the visual styling by updating the image for the search bar's bookmark icon and setting showsBookmarkButton on the search bar to true.
Here is an implementation with a UISearchController:
let searchController = UISearchController(searchResultsController: nil)
let micImage = UIImage(systemName: "mic.fill")
searchController.searchBar.setImage(micImage, for: .bookmark, state: .normal)
searchController.searchBar.showsBookmarkButton = true
You handle the button tap via the search bar's delegate:
searchController.searchBar.delegate = self
func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) {
// Do work here
}

Related

How to add a custom button between UISearch Bar and Cancel Button while a search is enabled in Swift?

I'm using ios 14 SDK for development and I want to add a custom button between UISearchBar and the Cancel button when the search is enabled.
I have checked all attributes in UISearchController and UISearchBar level, but i couldn't find any attribute for doing it. :(
I saw a similar kind of button in the default ios files view, I have attached the screenshot and marked it with a red color box.
Can someone give a clue for doing that? I really appreciate your help.
You can try this:
if searchController.isActive {
searchController.searchBar.showsBookmarkButton = true
} else {
searchController.searchBar.showsBookmarkButton = false
}
searchController.searchBar.setImage(UIImage(named: "imgName"), for: .bookmark, state: .normal)

Change UINavigationItem accessibility elements order

I have a UINavigationBar which contains 3 parts:
titleView (which is UISearchBar)
leftBarButtonItems
rightBarButtonItems
when the voice-over is on, the search bar will be the first one to be focused.
which is not confirmed to the left to right order we are familiar with.
I tried to set UINavigationItem's accessibilityElements, but it still will highlight the searchBar first. assume because, inside the UINavigationItem, the titleView is the first subView.
any ideas on how to change the order, thanks~
Any ideas on how to change the order?
I assume your problem deals with the way you added the search bar in the navigation bar.
I created a blank project as follows:
The code snippet hereafter is an example of adding a search bar as the title view: 🤓
class SearchViewController: UIViewController, UISearchBarDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let search = UISearchBar()
search.showsCancelButton = true
search.delegate = self
self.navigationItem.titleView = search
}
}
The result with VoiceOver on gives rise to the following screenshots:
Following this rationale, you have the VoiceOver initial reading order from left to right in the navigation bar. 🥳🎊🎉
I suggest to take a look at this site if further information is needed about a11y in the navigation bar and especially if you want to make a specific reading order. 👍

Subtitle Above Large Nav Bar Title

I was wondering how we could get the subtitle (like a date) above the navbar title when using the prefersLargeTitles feature. Something like the music app. I would also like the large button beside it (like the profile button in the music app). I would still like the large title to animate to the top and become small when the screen is scrolled (like the browse page on the music app).
The code I am using so far is
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.prefersLargeTitles = true
collectionView.initialize()
self.title = "Home Screen"
}

UISearchController Needs an extra tap to become first responder

I switched my apps one screen from UISearchBar to UISearchController. It's a tableview controller. As per design I should not keep the search bar on UI initially unless it is activated, (Normally it's a common practice to keep search bar as the 'tableHeaderView'). The problem was, I have a search button, when tapped 'search bar' should be activated and become first responder.
When tapped on cancel button, it should be removed from UI. However when I'm tapping on the 'Search Bar Button' on navigation bar, the UISearchController gets activated, providing a dim background but the keyboard doesn't appear. I need to tap one more time on search bar to bring the keyboard upon UI.
Here's my search bar button action:
#IBAction func onTapSearch(_ sender: AnyObject) {
self.view.addSubview(searchController.searchBar)
searchController.isActive = true
searchController.becomeFirstResponder()
isSearchActive = true
self.navigationController?.setToolbarHidden(true, animated: false)
}
I'm configuring the UISearchController in my viewDidLoad method. Let me know if that part code is any of you want to see, however it's usual code. And I verified I'm not calling anywhere resignFirstResponder() method anywhere.
try this,
Just replace this line,
searchController.becomeFirstResponder()
With this below,
searchController.searchBar.becomeFirstResponder()
Edit,
func didPresentSearchController(_ searchController1: UISearchController) {
searchController1.searchBar.becomeFirstResponder()
}
Implement this delegate method and try.

How do you make a dropdown searchbar?

In the iOS calendar app, when you press the search icon, an animated dropdown containing a search bar is shown, and it instantly gains focus.
Before Pressing The Search Icon
After Pressing The Search Icon
How would I go about developing a similar search dropdown in my onw app? What sort of classes / methods would I use to achieve this and how would they be put together? Note, I'm sure I could find a third party library to handle this, but I want to know how the could be done using only core iOS libraries.
lazy var searchBar = UISearchBar(frame: CGRectMake(0, 0, 0, 0))
override func viewDidLoad() {
super.viewDidLoad()
searchBar.placeholder = "Search"
self.navigationItem.rightBarButtonItem.image = UIImage(named: searchIcon.png)
}
func searchIconTapped() {
navigationItem.titleView = searchBar
}
To go back to default, just set the navigationItem.titleView back to nil

Resources