in my swift 2 app i have a table view controller
where i added a custom search bar (dark grey row)
in the viewDidLoad i call
configureCustomSearchController()
this is the function:
func configureCustomSearchController() {
customSearchController = CustomSearchController(
searchResultsController: self,
searchBarFrame: CGRectMake(0.0, 0.0, MyTable.frame.size.width, 50.0),
MyTable.tableHeaderView = customSearchController.customSearchBar
customSearchController.searchBar.sizeToFit()
customSearchController.customDelegate = self
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
// DO SOMETHING
}
func didStartSearching() {
// DO SOMETHING
}
func didTapOnSearchButton() {
// DO SOMETHING
}
func didTapOnCancelButton() {
// DO SOMETHING
}
func didChangeSearchText(searchText: String) {
// DO SOMETHING
}
My Question is, how can i hide the searcher, if my tableview will appear and show the sidebar if i pull down.
a pull down refresh function is available.
i found my solution:
viewDidLoad
MYTable.contentInset = UIEdgeInsets(top: -1, left: 0, bottom: 0, right: 0)
this hide the searchbar on start and if i scroll a little bit up, the search Bar will be visible
if you want to show searchbar when user scroll down then add this Code
self.MyTable.tableHeaderView = customSearchController
self.MyTable.contentOffset = CGPointMake(0, CGRectGetHeight(customSearchController.frame))
customSearchController.delegate = self
If you want to hide the header which contains your custom search bar you can try the following solutions:
When you have to hide header (At start):
tableview.contentOffset = CGPointMake(0,44)
When you have to show header (On the pull down action ):
tableview.contentOffset = CGPointMake(0,0)
Ref:https://stackoverflow.com/a/14433304/4557505
Another option is
table.tableHeaderView = nil
And later if you want to show it then just assign it again,
table.tableHeaderView = theHeaderView;
You can find more information about this on https://stackoverflow.com/a/8079933/4557505
Hope this may help you
Else you may set your search bar on the viewController's view and show/hide that based on your pull to refresh
Related
When i want to the update data source of the tableview, firstly i want to scroll to top (to header view) then show the UIRefreshControl view, after data source updated then i want to hide the UIRefreshControll.
To do that i tried following line:
self.kisilerTable.scrollRectToVisible(CGRect(x: 0, y: 0, width: 1, height: 1), animated: false)
self.kisilerTable.setContentOffset(CGPoint(x: 0, y: self.kisilerTable.contentOffset.y - (self.refreshControl.frame.size.height)), animated: true)
self.kisilerTable.refreshControl?.beginRefreshing()
Above code is scrolling to top then it shows the UIRefreshControl. And after my data updated i tried to hide it with following code:
self.kisilerTable.reloadData()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.kisilerTable.refreshControl?.endRefreshing()
}
But the problem is, above code is hiding the indicator animation but it leaves a space there. As you can see in the screenshot:
If i try to hide with following code:
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.kisilerTable.reloadData()
self.kisilerTable.refreshControl?.endRefreshing()
}
It is hiding but, i am losing the hide animation. I don't want to lose hide animation.
How can i resolve this problem?
I think it happens, because in the beginning you use setContentOffset to leave a space, but that space is not removed.
I will suggest another implementation, which works very well:
First you declare the refreshControll before the method viewDidLoad():
let refreshControl = UIRefreshControl()
Now do you need create a method for stop the animation when needed:
func stopAnimatingRefreshControl() {
if let refreshControl =
tableView.subviews.first(where: { $0 is UIRefreshControl})as? UIRefreshControl,
refreshControl.isRefreshing {
refreshControl.endRefreshing()
}
}
Now you create an #objc function that be called when scrolls the table to update, normally in this moment you call methods that make your server request to update data.
When this data is updated, you call the function stopAnimatingRefreshControl():
#objc func refreshMyData() {
// call methods for get data from server
getDataFromServer()
}
func getDataFromServer() {
// request completed and data is updated, now i need stop the loading.
DispatchQueue.main.async {
self.tableView.reloadData()
}
stopAnimatingRefreshControl()
}
Finally, after creating the necessary methods, you need to link our #objc function to refreshControll and our tableView, do it in method viewDidLoad() :
refreshControl.addTarget(self, action: #selector(refreshMyData), for: .valueChanged)
tableView.addSubview(refreshControl)
Now you're done, I hope I helped.
I want to add a banner to the navigation bar, but by increasing the height of it. I want to copy the design and behaviour of an artist page in the Apple Music app:
It behaves just like a normal Large Title would, except for that it has been moved down, it has a sticky UIImageView behind it and it returns its background when the user scrolls down far enough. You can fire up Apple Music, search for an artist and go to their page to try it out yourself.
I've tried a bunch of things like setting the frame on the UINavigationBarLargeTitleView, and the code from this answer: https://stackoverflow.com/a/49326161/5544222
I already got a hold of the UINavigationBarLargeTitleView and its UILabel using the following code:
func setLargeTitleHeight() {
if let largeTitleView = self.getLargeTitleView() {
if let largeTitleLabel = self.getLargeTitleLabel(largeTitleView: largeTitleView) {
// Set largeTitleView height.
}
}
}
func getLargeTitleView() -> UIView? {
for subview in self.navigationBar.subviews {
if NSStringFromClass(subview.classForCoder).contains("UINavigationBarLargeTitleView") {
return subview
}
}
return nil
}
func getLargeTitleLabel(largeTitleView: UIView) -> UILabel? {
for subview in largeTitleView.subviews {
if subview.isMember(of: UILabel.self) {
return (subview as! UILabel)
}
}
return nil
}
Initially put a view with image and label and play button. Then clear the navigation bar it will show the image below it by
self.navigationController!.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController!.navigationBar.shadowImage = UIImage()
self.navigationController!.navigationBar.isTranslucent = true
later when you scroll up you have to handle it manually and again show the
navigation with title.
I have a ViewController embeded in a navigationBar. I want the back button in the navigation bar to have the following effect :
if a condition is fullfilled, apply the normal behavior of the back button
if the condition is not fullfilled, stay and remain on the same VC to do something else
Try like this :-
override func viewDidLoad() {
let transparentButton = UIButton()
transparentButton.frame = CGRectMake(0, 0, 50, 40)
transparentButton.backgroundColor = UIColor.orangeColor()
transparentButton.addTarget(self, action:"backAction:", forControlEvents:.TouchUpInside)
self.navigationController?.navigationBar.addSubview(transparentButton)
}
And the function is
func backAction(sender:UIButton) {
// check your condition
}
I'd like to reload my View but after I reload it my ScrollView not working, but everything else refresh correctly. Here is my code to refresh view:
extension UIViewController {
func reloadViewFromNib() {
let parent = view.superview
view.removeFromSuperview()
view = nil
parent?.addSubview(view) // This line causes the view to be reloaded
}
}
I tried to put these into my viewDidLoad maybe I just need to refresh the SrollView manually but it's still not working.
self.beSrcollView.bounces = true
self.beSrcollView.delegate = self
self.beSrcollView.updateConstraints()
self.beSrcollView.isScrollEnabled = true
self.beSrcollView.updateFocusIfNeeded()
self.beSrcollView.setNeedsFocusUpdate()
self.beSrcollView.needsUpdateConstraints()
Have you any idea how to fix this?
override func viewDidLayoutSubviews()
{
self.beSrcollView.contentSize = CGSize(width: self.view.frame.size.width, height: 1000) // height change according
}
Try This
scrollView.reloadInputViews()
I have a BaseViewController that my UIViewControllers extend so i can have explicit functions that i dont need to rewrite. Something i would like would be a functions such as self.showSpinner() and the viewController would show the spinner
My Code looks like this
class BaseViewController: UIViewController {
var actvIndicator : UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
self.actvIndicator = UIActivityIndicatorView(activityIndicatorStyle: .WhiteLarge)
self.actvIndicator.color = UIColor.blackColor()
self.actvIndicator.backgroundColor = UIColor.blackColor()
self.actvIndicator.frame = CGRectMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2, 100, 100);
self.actvIndicator.center = self.view.center
self.actvIndicator .startAnimating()
self.view.addSubview(self.actvIndicator)
self.actvIndicator.bringSubviewToFront(self.view)
self.edgesForExtendedLayout = UIRectEdge.None
self.navigationController?.navigationBar.translucent = false
}
func showSpinner(){
self.actvIndicator.startAnimating()
}
func hideSpinner(){
self.actvIndicator.stopAnimating()
}
}
And my viewcontrollers looks like this
class MyProjectViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.showSpinner()
}
}
MyProjectViewController have UITableView that fills the entire screen. When i set tblProjects.alpha = 0 i can see the spinner. But i want it in the front.
i also tried self.view.bringSubviewToFront(self.actvIndicator)
What am i missing?
A couple quick notes before I get into what I think your problem is:
When you add a subview it is automatically added to the top layer, no need for the bringSubviewToFront: in viewDidLoad: (which is being used wrong anyway).
You should not set view frames in viewDidLoad: (e.g. centering a view). Frames are not setup yet, so you should move that to viewWillAppear: or some other variant.
Now your issue is most likely a view hierarchy problem (further confirmed by your comment) and thus can probably be fixed by pushing the spinner to the front every time you want it to be shown, like:
func showSpinner() {
self.view.bringSubviewToFront(self.actvIndicator)
self.actvIndicator.startAnimating()
}
The problem here stands on the fact that table view is draw after you are calling self.view.bringSubviewToFront(self.actvIndicator). A possible workaround for this is to call bringSubviewToFront when showing the spinner
func showSpinner(){
self.view.bringSubviewToFront(self.actvIndicator)
self.actvIndicator.startAnimating()
}