iOS Swift - How to move searchBar up when scrolling? - ios

Here is the screenshot of my view:
Now when the user scrolls up, I need to hide this searchBar. When the user scrolls down, I need to show this searchBar. And also it should be gradual, not just show and hide.
Here are my codes right now inside viewDidLoad:
self.searchBar.frame = CGRect(x: 0, y: 0, width: (navigationController?.view.bounds.size.width)!, height: 55)
self.searchBar.barStyle = .default
self.searchBar.isTranslucent = false
self.searchBar.barTintColor = UIColor.groupTableViewBackground
self.searchBar.backgroundImage = UIImage()
self.searchBar.delegate = self
self.view.addSubview(searchBar)
self.definesPresentationContext = true
Also, I set the distance of the tableView to the top to be 55 so that the searchBar does not cover the tableView.
What should I do?
Thanks!

The usual thing is to have a UISearchController and assign its search bar to the view controller's navigation item's searchController property. That causes the search bar to behave as you seem to describe, automatically.
Here's an example from my own code:
let src = SearchResultsController(data: self.sections)
let searcher = UISearchController(searchResultsController: src)
searcher.searchResultsUpdater = src
self.navigationItem.searchController = searcher

Related

My navigation bar is not moving up when scrolling UITableView with background image

I have this view hierarchy on a view embedded in a UINavigationController:
When I scroll the UITableView the navigation bar is not moving up (the title is not becoming smaller) it stays like this:
If I remove the image view as background view everything works well.
My navigation is configured like this:
navigationItem.title = "Title here"
navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.isTranslucent = true
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.barStyle = UIBarStyle.blackTranslucent
navigationController?.navigationBar.backgroundColor = .clear
A project demonstrating the problem is available here:
https://drive.google.com/file/d/181Aggala2ZfGN0lDjEtHWg0vobkM0iJc/view?usp=sharing
I already tried to change the insets of the tableview but it didn't work.
tableView.contentInset = UIEdgeInsets(top: navigationController?.navigationBar.height, left: 0, bottom: 0, right: 0)
Thanks!
As you discovered, to make large title fonts work as you want them to, the UIScrollView or any of its subclass needs to be the first element in the view hierarchy.
To fix your problem, you can try setting the background image to be the background of the UITableView directly.
Edit: Okay soo according to your comment you want a background behind everything including navigation bar. There is one way of achieving this and that is to subclass your UINavigationController and inside viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
let image = UIImage(named: "wallpaper")
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.frame = UIScreen.main.bounds
//this below part is important. Make sure to set it to 0 otherwise it will cover everything else
view.insertSubview(imageView, at: 0)
}
And then make sure your UIViewController containing the UITableView has a clear color for the UIView and remove the background image from that UIViewController

Push ViewController subviews beneath NavigationBar when translucent is True, Programmatically

This question asked to be implemented in Swift 4, iOS 11
Is there any way to make every subview of ViewController's view to be pushed down when it is under UINavigationBar?
If navigation bar is NOT TRANSLUCENT the subview is under it. This is what I want.
Desired Result
But when navigation bar is TRANSLUCENT the subview is lying under it. I dont want it. I want the subview is pushed down just be like if navigation bar is not translucent.
Undesired Result
I create the view programmatically :
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.red
let navBar = (self.parent as? UINavigationController)?.navigationBar
navBar?.isTranslucent = true
}
func makeChildView() {
let myframe = CGRect(x: 0, y: 10, width: self.view.frame.width, height:
self.view.frame.height * 0.4)
let view = UIView(frame: myframe)
view.backgroundColor = UIColor.green
self.view.addSubview(view)
}
Using Autolayout
I am able to solve this problem using autolayout. But I just want to know how to achieve this result without autolayout if possible. Is there any other approach?
Swift 3.x
navBar?.isTranslucent = true
self.automaticallyAdjustsScrollViewInsets = false
Add this line & you are good to go.

ios swift search bar color change

I am trying to change the gray area (rectangle area) color of the search bar to a different color (orange). Ive tried using searchBar.barTintColor = but that is only changing the color of the cancel button and not the gray area.
EDIT
class usersVC: UITableViewController, UISearchBarDelegate {
// declare searchBar
var searchBar = UISearchBar()
// default function
override func viewDidLoad() {
super.viewDidLoad()
// implement search bar
searchBar.delegate = self
searchBar.showsCancelButton = true
searchBar.sizeToFit()
searchBar.placeholder = "Search"
searchBar.frame.size.width = self.view.frame.size.width - 30
let searchItem = UIBarButtonItem(customView: searchBar)
self.navigationItem.leftBarButtonItem = searchItem
}
Try this again.
I created this effect by loading a simple image with an orange background, seen below.
searchBar.backgroundImage = UIImage(named: "orange")
Background image:
EDIT 1
Based on your recent comment, I tested this with a programatically created searchbar and it works as well.

UISearchController search bar width not changing

Ran through a quick tutorial with search bars and figured that I could use searchBar.sizeToFit() to autosize the search bar, however the right end of the search bar still extends off of the screen.
class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating, UISearchBarDelegate {
var searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchBar.delegate = self
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.sizeToFit()
tableView.tableHeaderView = searchController.searchBar
definesPresentationContext = true
}}
I've tried to manually set the frame with something like searchController.searchBar.frame = CGRectMake(0, 0, 200, 200) but the width remained off of the screen. The search bar does not exist in the storyboard, however the tableView does.
Needed to set autolayout constraints for the tableView that the search bar was a part of. Setting these fixed the sizing issues.
If you're using Auto layout, then use leading and trailing edges instead of width constraints.
Just click on Pin option given below and select top,leading(left) and trailing(right) constraints, then click on Add 3 constraints. Make sure "Constraint to margin" checkbox is unchecked. If the constraints satisfy, There will be no warning. Try changing the background color of your search bar to see its position on the screen.
If setting up auto layout constraints doesn't fix the problem, try calling searchController.searchBar.sizeToFit() in viewWillLayoutSubviews() rather than viewDidLoad(). This may help if the search bar is contained in a view other than the table header view.
Swift 4, works for all types of ViewControllers
After countless hours of trial and error here's what I came up for those who want to use it in code:
Set delegate
class SearchDatasourceController: UIViewController , UISearchBarDelegate { }
Set a customTitleView and the searchBar
IMPORTANT: set their frame
lazy var customTitleView: UIView = {
var view = UIView()
let frame = CGRect(x: 0, y: 0, width: 300, height: 44)
view.frame = frame
return view
}()
lazy var searchBar: UISearchBar = {
let searchBar = UISearchBar()
searchBar.placeholder = "Search"
searchBar.autocapitalizationType = .none
searchBar.backgroundImage = UIImage()
(searchBar.value(forKey: "searchField") as? UITextField)?.backgroundColor = UIColor(r: 230, g: 230, b: 230)
searchBar.delegate = self
searchBar.becomeFirstResponder()
let frame = CGRect(x: 0, y: 0, width: 300, height: 44)
searchBar.frame = frame
return searchBar
}()
in viewDidLoad add the customTitleView that holds the searchBar
override func viewDidLoad() {
super.viewDidLoad()
customTitleView.addSubview(searchBar)
navigationItem.titleView = customTitleView
searchBar.becomeFirstResponder()
}
add delegate method to listen for searches
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
print(searchText)
}
make sure you present your view controller on the navigation stack
func handleSearchBarButtonItemTapped() {
let controller = SearchDatasourceController()
navigationController?.pushViewController(controller, animated: true)
}

How to show/hide UISearchBar by action in Swift?

I have a UITableView with a UISearchBar. I need to show/hide my searchBar, by user action (button pressing):
I tried to use this code:
if self.tableView.contentOffset.y == 0 {
self.tableView.contentOffset = CGPoint(x: 0.0, y: self.searchBar.frame.size.height)
}
from this question.
Actually I've tried all of those answers. All of them just scroll my UITableView, and each time I'm scrolling my UITableView - searchBar appears.
I tried to do something like this:
self.newsTableView.tableHeaderView = nil; //Hide
and
self.newsTableView.tableHeaderView = self.SearchBar; //Show
But UITableView doesn't want to return searchBar;
How can I resolve this problem?
I need to hide searchBar by action, not to scroll my UITableView (hide like searchBar.hidden = true) Actually, searchBar.hidden = true works, but there is a white space instead of searchBar.
Use UIView.animation for searchBar and tableView
When you start scroll table
Change position/alpha of search bar and height of tableView
UIView.animateWithDuration(1.0, animations: {
searchBar.alpha = 0.0
tableView.view.frame.height = CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.width, height: UIScreen.mainScreen().bounds.height)
}, completion: {
(value: Bool) in
//do nothing after animation
})
In Xcode 7.3 in the ViewController.swift file it worked properly for me
CategoryTableView.tableHeaderView = searchController.searchBar // show
CategoryTableView.tableHeaderView = nil // hide
searchController.active = false
hope this could solve your problem. call this at launch of tableview to hide the searchBar and when you scroll down it will appear
var newBounds: CGRect? = self.newsTableView.bounds
newBounds?.origin.y = 0
newBounds?.origin.y = newBounds!.origin.y + self.searchBar.bounds.size.height
and then set the new bound of the tableView

Resources