Flicker during transition when Search bar (within Large Title Navigation Bar) tapped - Swift 4.2 - ios

I have added search bar in navigation bar large title. I am facing a flicker issue when the search bar is tapped to type into it.
Here is the video to the explain the issue:
The code I have written to achieve this is:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.title = "Leads"
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(addNewLeadsAction(_:)))
let mysearchController = UISearchController(searchResultsController: nil)
mysearchController.searchResultsUpdater = self
mysearchController.searchBar.placeholder = "Search Lead"
mysearchController.searchBar.showsCancelButton = true
mysearchController.searchBar.barStyle = UIBarStyle.default
mysearchController.searchBar.backgroundColor = UIColor(patternImage: Common.gradientImage(view: (self.navigationController?.navigationBar)!))
if let textfield = mysearchController.searchBar.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.white
if let backgroundview = textfield.subviews.first {
backgroundview.backgroundColor = .white
backgroundview.layer.cornerRadius = 10
backgroundview.clipsToBounds = true
}
}
for searchBarView in mysearchController.searchBar.subviews{
for cancelButtonView in searchBarView.subviews{
if cancelButtonView.isKind(of: UIButton.self) {
let filterButton:UIButton = cancelButtonView as! UIButton
filterButton.isEnabled = true
filterButton.setTitle("", for: .normal)
let image1 = UIImage(named: "filterIcon")?.withRenderingMode(.alwaysTemplate)
filterButton.setImage(image1, for: .normal)
filterButton.contentMode = .scaleAspectFit
filterButton.tintColor = .white
filterButton.addTarget(self, action: #selector(filterAction(_:)), for: .touchUpInside)
}
}
}
self.navigationItem.searchController = mysearchController
self.definesPresentationContext = true
leadsTableView.reloadData()
}
Trying to make the transition smooth is what i'm looking to achieve.
Following are the things I have tried already:
iOS 11 UISearchBar in UINavigationBar
Navigation bar + Search controller + Large title: Hairline during scrolling
Any help will be appreciated

Related

How do I set up my navigation search bar in Swift to look like the Reddit App

I just started to learn how to code with Swift in Xcode, I need some help regarding the search bar. I want to add a search field bar to my navigation bar in center, and next to it i want to add two items . So far I managed to add a UISearch to my navigation bar but once I try to add items next to it, it pushes my icons above the search field.
Pressed State
Normal State
Does anyone know what to add the two menu items next to it programmatically or in the storyboard? And how to make the search field centered and a bit thinner?
My code now:
override func viewDidLoad() {
super.viewDidLoad()
let searchController = UISearchController(searchResultsController: nil)
searchController.delegate = self as? UISearchControllerDelegate
let searchBar = searchController.searchBar
searchBar.tintColor = UIColor.white
searchBar.barTintColor = UIColor.white
if let textfield = searchBar.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
if let navigationbar = self.navigationController?.navigationBar {
navigationbar.barTintColor = UIColor.blue
}
navigationItem.searchController = searchController
navigationItem.hidesSearchBarWhenScrolling = false
}
Reddit Example
Okay, fixed it! Just used the code below. Now my next struggle is changing the background of the textfield.
//SEARCH
let searchController = UISearchController(searchResultsController: nil)
searchController.hidesNavigationBarDuringPresentation = false
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.delegate = self as? UISearchBarDelegate
let frame = CGRect(x: 0, y: 0, width: 300, height: 44)
let titleView = UIView(frame: frame)
searchController.searchBar.backgroundImage = UIImage()
searchController.searchBar.frame = frame
titleView.addSubview(searchController.searchBar)
navigationItem.titleView = titleView
}

How to add a segmented control to a navigation bar ? (iOS)

I would like to add a segmented control to a navigation bar like this
but when i drag the segmented control to the navigation bar the large title is gone. How can create the above UI ?
You should add the segmented control as the titleView of the navigation bar.
Below is the sample code:
let titles = ["All", "Missed"]
segmentControl = UISegmentedControl(items: titles)
segmentControl.tintColor = UIColor.white
segmentControl.backgroundColor = UIColor.blue
segmentControl.selectedSegmentIndex = 0
for index in 0...titles.count-1 {
segmentControl.setWidth(120, forSegmentAt: index)
}
segmentControl.sizeToFit()
segmentControl.addTarget(self, action: #selector(segmentChanged), for: .valueChanged)
segmentControl.selectedSegmentIndex = 0
segmentControl.sendActions(for: .valueChanged)
navigationItem.titleView = segmentControl
You can try the below simple code,
var segmentedController: UISegmentedControl!
let items = ["Label A", "Label B"]
segmentedController = UISegmentedControl(items: items)
navigationItem.titleView = segmentedController
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Edit", style: .plain, target: self, action: #selector(handleSignOut))
navigationItem.rightBarButtonItem?.tintColor = UIColor.black
If you want to add UISegmentControl by using XIB then you can do that by following these simple steps:
Design your custom view in XIB (Refer XIB for your reference https://i.stack.imgur.com/AJDCo.png)
Put the code in your ViewController
class ViewController: UIViewController {
lazy var navSegmentedView: YourCustomView = {
guard let aView = Bundle.main.loadNibNamed("\(YourCustomView.self)", owner: self, options: nil)?.first as? YourCustomView else { return YourCustomView() }
aView.backgroundColor = .clear
aView.frame = CGRect(x: 0, y: 0, width: 160, height: 40)
aView.segmentControl.addTarget(self, action: #selector(segmentChanged(_:)), for: .valueChanged)
return aView
}()
override func viewDidLoad() {
super.viewDidLoad()
setupNavBar()
}
func setupNavBar() {
navigationItem.titleView = navSegmentedView
navigationItem.titleView?.backgroundColor = .clear
}
#objc func segmentChanged(_ sender: UISegmentedControl) {
print(sender.selectedSegmentIndex)
}
}

Swift 4: removing UISearchbar's editing shadow

I am new to swift, i built an application with search feature,
when the view loads, the searchBar is fine, but when it begins editing, a shadow appears i want to remove it
i tried this code at TextDidChange, but it didn't work
searchBar.barTintColor = UIColor.clear
searchBar.backgroundColor = UIColor.clear
searchBar.isTranslucent = true
searchBar.setBackgroundImage(UIImage(), for: .any, barMetrics: .default)
Screenshot Before Editing
,
Screenshot After Editing
code:
func addSearchbar(){
if #available(iOS 11.0, *) {
let sc = UISearchController(searchResultsController: nil)
let scb = sc.searchBar
scb.showsCancelButton = false
if let navigationbar = self.navigationController?.navigationBar {
//navigationbar.tintColor = UIColor.green
//navigationbar.backgroundColor = UIColor.yellow
navigationbar.barTintColor = UIColor.white
}
navigationController?.navigationBar.tintColor = UIColor.green
navigationItem.searchController = sc
navigationItem.searchController?.searchBar.delegate = self
navigationItem.searchController?.searchBar.barStyle = .blackTranslucent
navigationItem.hidesSearchBarWhenScrolling = false
}
}

UISearchController iOS 11 Customization

I had been using the following code prior to iOS 11 to customize the appearance of the UISearchController search bar:
var searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.setDefaultSearchBar()
searchController.searchResultsUpdater = self
if #available(iOS 11.0, *) {
navigationItem.searchController = searchController
} else {
tableView.tableHeaderView = searchController.searchBar
}
extension UISearchBar {
func setDefaultSearchBar() {
self.tintColor = UIColor.blue
self.searchBarStyle = .minimal
self.backgroundImage = UIImage(color: UIColor.clear)
let searchBarTextField = self.value(forKey: "searchField") as! UITextField
searchBarTextField.textColor = UIColor.white
searchBarTextField.tintColor = UIColor.blue
searchBarTextField = .dark
}
}
However, the appearance of the search bar fails to update when running the same code on iOS 11.
iOS 10:
iOS 11:
Much of the attention to this question so far has focused on the text color of the search bar. I am looking at more than this - the background color, tint color, the search indicator, clear button color, etc.
I just found out how to set them: (with some help of Brandon and Krunal, thanks!)
The "Cancel" text:
searchController.searchBar.tintColor = .white
The search icon:
searchController.searchBar.setImage(UIImage(named: "my_search_icon"), for: UISearchBarIcon.search, state: .normal)
The clear icon:
searchController.searchBar.setImage(UIImage(named: "my_search_icon"), for: UISearchBarIcon.clear, state: .normal)
The search text:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSAttributedStringKey.foregroundColor.rawValue: UIColor.white]
The placeholder:
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).attributedPlaceholder = NSAttributedString(string: "placeholder", attributes: [NSAttributedStringKey.foregroundColor: UIColor.white])
The white background:
if #available(iOS 11.0, *) {
let sc = UISearchController(searchResultsController: nil)
sc.delegate = self
let scb = sc.searchBar
scb.tintColor = UIColor.white
scb.barTintColor = UIColor.white
if let textfield = scb.value(forKey: "searchField") as? UITextField {
textfield.textColor = UIColor.blue
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
if let navigationbar = self.navigationController?.navigationBar {
navigationbar.barTintColor = UIColor.blue
}
navigationItem.searchController = sc
navigationItem.hidesSearchBarWhenScrolling = false
}
Taken from here.
To properly set the text typed into the search bar to white use (when using a dark field color):
searchController.searchBar.barStyle = .black
To set the textfield background color
if #available(iOS 11.0, *) {
if let textfield = searchController.searchBar.value(forKey: "searchField") as? UITextField {
if let backgroundview = textfield.subviews.first {
// Background color
backgroundview.backgroundColor = UIColor.white
// Rounded corner
backgroundview.layer.cornerRadius = 10;
backgroundview.clipsToBounds = true;
}
}
}
However using something like
textfield.textColor = UIColor.blue
in the above does not seem to work.
Try setting the search bar's bar style.
searchController.searchBar.barStyle = UIBarStyleBlack;
Moving the call to setDefaultSearchBar into viewDidAppear should fix this.
You need to find the UISearchBar's underlying UITextField and change its text color.
Notice this only have effect when search controller is going to present (UISearchControllerDelegate.willPresentSearchController) or presented.
class ViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// setup your search controller...
// set search controller's delegate
navigationItem.searchController?.delegate = self
}
}
extension ViewController : UISearchControllerDelegate {
func willPresentSearchController(_ searchController: UISearchController) {
// update text color
searchController.searchBar.textField?.textColor = .white
}
}
extension UISearchBar {
var textField: UITextField? {
for subview in subviews.first?.subviews ?? [] {
if let textField = subview as? UITextField {
return textField
}
}
return nil
}
}
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).defaultTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
Try it: searchController.<YOUR SEARCHBAR>.barStyle = .blackOpaque instead of self.searchBarStyle = .minimal.
Thus:
var searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.setDefaultSearchBar()
//Add this line below
searchController.searchBar.barStyle = .blackOpaque
searchController.searchResultsUpdater = self
if #available(iOS 11.0, *) {
navigationItem.searchController = searchController
} else {
tableView.tableHeaderView = searchController.searchBar
}
extension UISearchBar {
func setDefaultSearchBar() {
self.tintColor = UIColor.blue
//Delete this line below
self.searchBarStyle = .minimal
self.backgroundImage = UIImage(color: UIColor.clear)
let searchBarTextField = self.value(forKey: "searchField") as! UITextField
searchBarTextField.textColor = UIColor.white
searchBarTextField.tintColor = UIColor.blue
searchBarTextField = .dark
}
}
If you need to change the background colour of the textField in the searchBar, see my answer here:
https://stackoverflow.com/a/46315974/1109892
You have to access the UITextField inside the UISearchBar. You can do that by using
let textFieldInsideSearchBar = yourSearchbar.value(forKey: "searchField") as? UITextField
textFieldInsideSearchBar?.textColor = yourcolor
OR

NavigationItem titleView is coming at left side for some time then move to Center

I am setting a custom view as titleView of the navigation. When viewcontroller appear its title view comes at left side for a moment and then move to center,what could be wrong? I am using the following code
let itemImgs: [UIImage] = [UIImage(named: "MORE_Location")!, UIImage(named: "MORE_Department")!, UIImage(named: "By_Teams")!, UIImage(named: "MORE_Status")!]
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
menuView = BTNavigationDropdownMenu(navigationController: self.navigationController, containerView: self.navigationController!.view, title: AppMessage.EDEmployeePeople, items: items as [AnyObject], itemImgs: itemImgs)
menuView.cellHeight = 60
menuView.cellBackgroundColor = UIColor.red
menuView.cellSelectionColor = UIColor.clear
menuView.cellSeparatorColor = UIColor.clear
menuView.shouldKeepSelectedCellColor = false
menuView.cellTextLabelColor = UIColor.white
menuView.shouldChangeTitleText = false
menuView.cellTextLabelFont = UIFont(name: "Helvetica", size: 17)
if appNeedsAutoResize
{
menuView.cellTextLabelFont = UIUtils.getFontForApproprieteField(.subHeadline).font
}
menuView.cellTextLabelAlignment = .left // .Center // .Right // .Left
menuView.arrowPadding = 15
menuView.animationDuration = 0.5
menuView.maskBackgroundColor = UIColor.clear
menuView.maskBackgroundOpacity = 0.3
menuView.didSelectItemAtIndexHandler = {(indexPath: Int) -> () in
print("Did select item at index: \(indexPath)")
if indexPath == 3
{
let byStatusViewController = ByStatusViewController(nibName: "ByStatusViewController", bundle: nil)
//UIUtils.pushViewWhenHideBottom(self, anotherVC: byStatusViewController)
self.navigationController?.pushViewController(byStatusViewController, animated: true)
}
else
{
let dropVC = DepartmentViewController(nibName: "DepartmentViewController", bundle: nil)
switch indexPath
{
case 0:
dropVC.employeeGroupInfo = EmployeeGroupInfo.locationInfo
break
case 1:
dropVC.employeeGroupInfo = EmployeeGroupInfo.departmentInfo
break
default:
dropVC.employeeGroupInfo = EmployeeGroupInfo.teamInfo
break
}
// UIUtils.pushViewWhenHideBottom(self, anotherVC: dropVC)
self.navigationController?.pushViewController(dropVC, animated: true)
}
}
self.navigationItem.titleView = menuView
}
Try to add constraints of autoresizing masks to your menu view to keep the view centered.
E.g.
menuView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin, .flexibleBottomMargin]
I had this problem and changing my function that customize my navigationItem from viewWillAppear() to viewDidLoad() resolved

Resources