UITableView how to "dim" the actual table when UISearchbar gets focus? - iphone

Many of the table searches I see actually dim (change alpha?) of the actual tableView when the search bar gets focused. I am trying to implement this.
When I overload
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
I am trying to do something like
self.tableView.alpha = .5f
But it is changing the alpha of the actual searchBar (if I have searchBar on its own) or changing the alpha of the entire table (including searchBar) if I have searchBar underneath the tableView in IB.
What am I doing wrong here. How can I just Dim the table and not everything.
I guess what I am really failing to understand is how all this stuff gets layered on the screen.
EDIT: The contacts application is a good example of what I am trying to do.

Most such apps just throw a black-background UIView on top of the table and fade it in (to an alpha of .5 or whatever) when the search bar gains focus.

If you use UISearchDisplayController, you get this behavior for free.

Since iOS 8 (and up to at least iOS 9.2) you would use a UISearchController. Unfortunately, currently the interface builder supports only the now deprecated UISearchDisplayController. So, this is how to add it programmatically to your table view controller, including the dim effect:
let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
// Use the current view controller to update the search results:
self.searchController.searchResultsUpdater = self
self.searchController.dimsBackgroundDuringPresentation = true
self.tableView.tableHeaderView = searchController.searchBar
}

Related

iOS 13 SearchController Back Button Color

I have a strange visual bug in my app that only applies to iOS 13 running from an Xcode 11 build. I have a table view embedded in a Navigation Controller with the default tint color set to my app's primary orange color. On iOS12, when you cancel the search action, you are presented with a back button that follows the global nav controller tint of primary orange. This is the expected behavior. Image shown below:
However, this same code in iOS13 produces a system default BLUE back arrow, as shown below:
I have tried EVERYTHING to try and override that blue back button, including creating a custom Bar Button Item with a custom action, but that is way too messy and I want to just simply override the tint color. I've tried the obvious searchController.searchBar.tintColor = UIColor(named:"Primary") where searchController is my UISearchController, and I have tried to override the self.navigationController tint color. I've tried accessing the SearchBar natively, like this: UISearchBar.appearance().tintColor = UIColor(named:"Primary"), but still no luck. I've tried everything else I can think of in the IB, but I can not figure out how to reach this back button's tint color. Can anybody help?
The only way I found so far to get this fix on iOS13.1 is to iterate through the subviews in the navigation bar and manually modified the tintColor.
None of the new UINavigationBarAppearance methods looks like they fix the problem. If you modified the backButtonAppearance in UINavigationBarAppearance I have been able to fix the title in back button but I haven't found a way to fix the image (<).
try this
override func viewWillAppear(_ animated: Bool) {
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
self.navigationItem.backBarButtonItem?.tintColor = .blue
}
In iOS 13 there are few new appearance types for the navigation bar. When you want to customize navigation bar which associated with a large title or any kind of scroll view just setup appearance parameters for .scrollEdgeAppearance
if #available(iOS 13.0, *) {
let standartAppearence = UINavigationBarAppearance()
standartAppearence.configureWithDefaultBackground()
// Your configuration
UINavigationBar.appearance().scrollEdgeAppearance = standartAppearence
}
It turns out that this was an XCode/Swift bug only affecting iOS 13.1. It should not be something that you have to account for in code, since only a very small portion of the user base is still on 13.1.

Prevent VoiceOver revealing views that are beneath a larger transparent view

Summary: I want to replicate the accessibility behaviour of a UIAlertView, where the background view is still visible but VoiceOver does not interact with it.
Detail: I have implemented accessibility for an iPhone app, but have one problem remaining. In some cases I display a large view on top of all others (partially transparent, covering most of the original view) containing labels and a close button. i.e. basically a custom popup/alert view. The problem is, VoiceOver continues to reveal the views/controls underneath it.
One method to prevent the hidden views from being revealed by VoiceOver is to set the whole custom view background to be accessible. However, this isn't really what we want as this containing view shouldn't really be interacted with by the user, only its subviews (labels/buttons) should.
I think you should use this on your top laying view:
Objective-C
- (BOOL)accessibilityViewIsModal {
return YES;
}
Swift
accessibilityViewIsModal = true
This makes every element of the View Controller that is hidden unaccessible.
An implementation could be to set it to true when you show the view and set it to false when you dismiss that view.
More info
Note: Requires iOS5 and up
Swift 4
In swift try this:
Before your view is presented setup your viewController’s view like this:
yourViewController.view.accessibilityViewIsModal = true
Also try setting the self.view.accessibilityViewIsModal to true in viewWillAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
view.accessibilityViewIsModal = true
}
It also might help if you send a screen chances notification when your modal or pop up view is appearing by adding this to the viewWillAppear:
UIAccessibility.post(notification: .screenChanged, argument: nil)
You can set the following properties on the view overlaying the background:
view.isAccessibilityElement = false;
view.isAccessibilityViewModal = true;
Does this work?
In obj-c:
view.isAccessibilityElement = NO;
view.accessibilityViewIsModal = YES;
When you hide the item, you can set isAccessibilityItem to NO.

UITableView -reloadSectionIndexTitles not calling data source

I'm trying to implement a UISearchBar within a UITableView, which behaves like the one in the "Artists" tab of the iPod application.
I have it hiding the navigation bar, and resizing the search box to show the "Cancel" button, etc. but am unable to get it to hide the section index titles.
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
inSearchMode_ = YES; // tell sectionIndexTitlesForTableView: to return nil
tableView_.scrollEnabled = NO; // works correctly, var is definitely wired
[tableView_ reloadSectionIndexTitles]; // doesn't call sectionIndexTitlesForTableView:
...
Am I missing something? Is UITableView -reloadSectionIndexTitles broken?
Typically my response to this kind of thing would be to call reloadData, but that has the side effect of causing the UISearchBar to lose focus.
I think approach you want is along these lines (Say you have a ArtistController which you want to make searchable):
Add a sub-controller to the ArtistController called ArtistSearchController
When the search box is clicked, bring the ArtistSearchController to the front as modal (to hide artists) or add transparency if you still want to show artists in the background.
When a search term is entered, created a model for the ArtistSearchController which is the data from ArtistController, filtered using the search term, and then display it in a list view
close the modal view when the user hits cancel.
This will save you from manipulating your original controller/nav bar and give it better usability
It seems what I need to do is to use a UISearchDisplayController rather than hand-rolling my own. I was able to modify the "TableSearch" sample to use sections and section headings, and it behaves as I want it to.

UISearchBar disable table view on activation

I have a UISearchBar in the table cell. All done in code (not in IB). When the search bar is activated I want to disable the table view are between the search bar and keyboard, so there is no way to touch and navigate out of this view. Cannot really get it working. Help please.
You could place a transparent UIView on top of the UITableView when the search bar is active. This would effectively disable touch events, which would now be sent to the transparent UIView and would be ignored.
As a general UI technique, if you wanted to inform the end user that the table view is no longer touchable, you could set the alpha of the UIView to 50% or the like. This would "grey out" the table view underneath.
Sorry, this is an old thread, but if one comes here searching, this works for me:
self.tableView.allowsSelection = NO;
self.tableView.scrollEnabled = NO;
1.Make UISearchBar become first responder
2. Overrider capture touch event and discard when UISearchBar become first responder
- ( UITapGestureRecognizer can help you for this case)

How is iPhone Contact app's detail View implemented

I would like to implement a view similar to the detail view of Apple's own Contacts app where it displays the name, phone number, note, etc. and its Edit mode.
Can you dissect how the whole view is done? Is that view done with a UITableView or a UIScrollView?
The contact details screen is actually quite simple to mimic.
Start with a UITableView and provide it with a UITableViewDataSource and UITableViewDelegate. You'll need to provide sections for all the data you want to present. This means 1 for the custom header, 1 for the custom footer (buttons / actions), and approximately 6 or so sections for the data (one section for phone numbers, another for e-mail addresses, and so on)
Inside of each section, a number of rows need to be provided from your datasource to indicate how much data there is for that section. For each row, a UITableViewCell can be used to display the actual contact data (fax label / fax number value, etc). You can get fancy if you like, but there doesn't seem to be a need. For things like ringtone you'll need to specify a disclosure indicator.
For the header you'll need a UIImageView and a UILabel, for the footer you'll need a few UIButtons. You can create a child of UITableViewCell in InterfaceBuilder with these views inside of it and wire it up like anything else. You can use NSBundle to load views from other xibs that are not already loaded.
An alternative is to dynamically generate the UI widgets at runtime with no xibs. It all depends on what you would rather manage (code or xibs), to me it seems about the same amount of effort either way. I highly recommend reading through the table view programming guide if you haven't already.
Or you could use Apple's own ABPersonViewController:
http://developer.apple.com/library/ios/#documentation/AddressBookUI/Reference/ABPersonViewController_Class/Reference/Reference.html
The allowsEditing property specifies whether the user can edit the person’s information.
My implementation uses a UITableView with custom header (for the "Add Photo" and edit name equivalents) and a custom footer (using the UISegmentedControl hack for a big button) for the "Delete" equivalent.
You can use F-Script for exploring this. Here's a screenshot from the F-Script browser while browsing Address Book. Basically, it looks like a lot of custom views which all inherit from NSView.
To do this yourself:
Download F-Script from the link above
Follow the instructions in the extras/F-Script Anywhere directory for attaching to Address Book
Choose F-Script -> Open Object Browser from the Address Book menu
Click Select View
Highlight the Address Book View you want to explore and click it.
Navigate around to your heart's content.
Just to show you the way, you can subclass UITableViewController for that purpose and then in order to implement the Edit mode similar to the Contacts app you would:
Add a property to store a reference to Cancel button.
var cancelButton: UIBarButtonItem!
In ViewDidLoad(), add edit button to the navigation bar as a right item and prepare Cancel button to later add it as a left item.
self.navigationItem.rightBarButtonItem = self.editButtonItem()
self.cancelButton = UIBarButtonItem(title: "Cancel", style: .Plain, target: self, action: "cancelPressed:")
Override setEditing(_:animated:) method to set up your cells for Edit/Preview mode and show/hide a Cancel button on the navigation bar, based on the editing flag.
override func setEditing(editing: Bool, animated: Bool) {
super.setEditing(editing, animated: true)
if editing {
// Set up cells and prepare for Edit mode here
self.navigationItem.setLeftBarButtonItem(self.cancelButton, animated: true)
} else {
// Set up cells and prepare for Preview mode here
self.navigationItem.setLeftBarButtonItem(nil, animated: true)
}
}
Override UITableViewDelegate's tableView(_:editingStyleForRowAtIndexPath:) and tableView(_:shouldIndentWhileEditingRowAtIndexPath:) methods to configure row styles and indentation when in Edit mode.
Implement cancelPressed method to exit Edit mode when Cancel is pressed.
func cancelPressed(button: UIBarButtonItem) {
self.setEditing(false, animated: true)
}
I know the question is pretty old, but somebody might find it helpful.