Search bar as header in tableview - appear and disappear - ios

I need to put a search bar at the top of my tableview. I am making a network call and when the results are greater than 100 I want to search bar to appear and when they are less than 100 I don't want to search bar to appear. The tableview is on the right side of the VC and does not take up the whole view controller. I want the search bar to be at the top of the table view as a header.
I cannot use a search controller because in iOS 11, using a search controller makes the search bar pop to the top of the VC when it is active.
I tried to set the tableviewheader to nil to get it to disappear. But I can't get it back obviously because I made the header nil.
self.rightDetailFilterTableView.tableHeaderView = nil
self.rightDetailFilterTableView.sectionHeaderHeight = 0
I have put the search bar into the storyboard as seen in the image below. Is this the right way to add the search bar as a header?
What is the best way to get it to appear and disappear in the tableview? I have tried a bunch of different methods. They all either leave a blank header or do something else that causes problems. I also tried using the header delegate methods but that still did not work.
I am not using a tableview controller, I am using a normal VC. I am also not using a search bar controller because of issues it causes in iOS 11.

Here's what I've done in one of my recent project. First, laid out my views like so:
That is, the Search Bar was added to the parent view rather than the table view. This allows me to hide/show it as needed.
Next, I've defined two optional layout constraint, one ensuring that the tableview is aligned to the top of the safe area, priority 750; the other aligning the top of the search bar to the top of the safe area; priority lower than 750 to hide it below the nav bar or priority higher than 750 to reveal it and push the table view down.
In code, I created a #IBOutlet to the layout constraint for the search bar to the top of the safe area, and I change its priority as needed:
#IBAction
func toggleSearchBar(_ sender: Any?) {
if searchBarVisibleLayoutConstraint.priority.rawValue > 750.0 {
searchBarVisibleLayoutConstraint.priority = UILayoutPriority(rawValue: 1.0)
searchBar?.endEditing(true)
} else {
searchBarVisibleLayoutConstraint.priority = UILayoutPriority(rawValue: 999.0)
}
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
In my case, the navigation bar is opaque and the search bar is not visible behind it. Your case may be different so you may also want to either clip the parent view or alpha fade the search bar when it is not visible.
Good luck!

Please check :
Created IBOutlet for my SearchBar.
#IBOutlet weak var testbar: UISearchBar!
And in my viewDidLoad :
override func viewDidLoad() {
var contentOffset = tableView.contentOffset
let showSearchBar = (results.count > 100)
self.tableView.tableHeaderView?.isHidden = !(showSearchBar)
if showSearchBar {
contentOffset.y -= testbar.frame.size.height
} else {
contentOffset.y += testbar.frame.size.height
}
tableView.contentOffset = contentOffset
}
Here is my tableview storyboard

Related

Bar section in iOS is extended unnecessarily

In the image shared, the orange section is the bar section , which is having unnecessary height, I am not able to resolve this issue by myself.
the views are like this
Parent Controller = View Controller
Child views = green view, black tableview
Please help to correct the height of the orange bar.
Seems like you have enabled prefersLargeTitles.
Make it false in your viewWillAppear()
self.navigationController?.navigationBar.prefersLargeTitles = false
You can also disable it from the storyboard.
Select your Navigation Controller -> Navigation Bar -> Uncheck prefers large titles
it seems like you're using the largeTitles on the navigationBar,
var prefersLargeTitles: Bool { get set }
When this property is set to true, the navigation bar allows the
title to be displayed out-of-line and using a larger font. The
navigation item used to build the bar must specify whether it wants
its title displayed in the large or small format. Use the
largeTitleDisplayMode property to configure the title's appearance.
When the property is set to false, the navigation bar displays the
title inline with the other bar button items.
try to disable it by:
navigationController?.navigationBar.prefersLargeTitles = false
or you can do this as well:
navigationItem.largeTitleDisplayMode = .never
hope this helps:)
https://developer.apple.com/documentation/uikit/uinavigationbar/2908999-preferslargetitles

iOS - hideable UIView at the top of the screen

I want to create an info view that will show at the top of the screen and disappear after some time, and later it can show again and so on.
I have created UIView and set constraints:
topInfoView.leadingAnchor.constraint(equalTo: mainView.leadingAnchor)
topInfoView.trailingAnchor.constraint(equalTo: smainView.trailingAnchor)
topInfoView.heightAnchor.constraint(equalToConstant: HEIGHT)
Closed state:
topInfoView.topAnchor.constraint(equalTo: mainView.topAnchor, constant: -HEIGHT)
Open state:
topInfoView.topAnchor.constraint(equalTo: mainView.topAnchor, constant: 0)
where mainView is main UIViewCcontroller view.
I set HEIGHT as my user height + "status bar height" (bar with battery, Wifi etc). Problem is, that sometimes status bar height is 0 and my topInfoView is incorrectly placed. I am obtaining "status bar height" via this:
func statusBarHeight() -> CGFloat {
let statusBarSize = UIApplication.shared.statusBarFrame.size
return Swift.min(statusBarSize.width, statusBarSize.height)
}
but it sometimes not works (views are not inited?) and I am also not sure about new iPhone X, where status bar is solved differently. Is there any other way, without calculating the height?
Use the vertical stack view. Put the tableView and then your view vertically one after the another. Set the height of the table view. Keep the distribution property of stack view to fill. Create an outlet of the tableview. With this arrangement when you will hide the tableview, your view will fill the whole area. When you again set isHidden property to false of table view your table view and view will appear as original arrangement. You can animate while hiding and showing table view to give a good user experience.

iOS - Moving search bar from center to below Navigation Bar by animation (Swift)

I have a search bar that was added to the center of my view controller via interface builder, and I even connected it with a IBOutlet. However, I had to place the search bar in the center of the view controller because there is important information above it.
What I want is that when the search bar is tapped, it should animate to the top, and fix itself below the navigation bar. The reason why I want it to go to the top is because I need more space for the results table View controller to show the results (which drops down when search bar is tapped).
I've looked everywhere but couldn't really find any information on how to fix the search bar below the navigation bar. Please do help!
P.S - similar problem link IOS Search bar that appears below navigation
First, add your constraints like the following pictures:
As you see, 2 of the constraints are drawn with dashes, these constraints have priorities less than 1000, and the reason is that we want the center vertically constraint and anchors to top constraint to be mutually exclusive:
One that anchors the search bar to the vertical center of the view.
One that anchors the search bar to the top of the view.
And because we want the search bar to be centered vertically initially, we assign a priority of 999 to that constraint (constraint number 1), and a priority of 1 to the other one.
You can set the priorities by clicking on the constraint and setting its priority from size inspector on the right, like in the following picture:
Second, connect these 2 constraints and your search bar to your view controller:
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var searchBarAnchorToTopConstraint: NSLayoutConstraint!
#IBOutlet weak var searchBarCenterVerticallyConstraint: NSLayoutConstraint!
Third, make your view controller conform to UISearchBarDelegate protocol and set it as the delegate of your search bar.
Forth, implement searchBarTextDidBeginEditing method in the following way:
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.searchBarCenterVerticallyConstraint.priority = 1
self.searchBarAnchorToTopConstraint.priority = 999
UIView.animate(withDuration: 1, delay: 0, options: [.curveEaseOut], animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
All we did here is that we gave searchBarCenterVerticallyConstraint a low priority and searchBarAnchorToTopConstraint a high priority (we switched their priorities).
Hope this helps!

How to swipe to view maintaining navigation bar items?

I'm trying to implement the swipe to view functionality just like Twitter's Moments:
If you take a look at the top you'll see a horizontal slider with the views. My requirement is tad bit different... On top of that horizontal slider I need my regular navigation bar with each page's custom items.
The swipe to view I implemented with some minor errors. Please take a look at this video (this is what I've done so far):
http://sendvid.com/5j50p73z
As you can see the swipe views functionality is working but I'm still missing some important things, namely:
When swiping to the next view it is scrolling up (seen on video)
My views are all contained in navigation controllers with their respective navbar items. The way I see it I'd need something like PushViewController without the back button but that would work both directions... I'm kinda lost here If I add the navigation controller instead of the view it shows the bar, but below the current existing one, not substituting it.
Any ideas on how to solve these?
I'm developing using Xamarin.iOS, but if you can provide an example using swift I guess I could try to translate that :)
This is what I have so far:
var viewController = Storyboard.InstantiateViewController("detailClaimViewController") as DetailClaimViewController;
viewController.ClaimId = ClaimId;
AddChildViewController(viewController);
ScrollView.AddSubview(viewController.View);
viewController.DidMoveToParentViewController(this);
var sumsInsController = Storyboard.InstantiateViewController("sumsInsuredListViewController")
as SumsInsuredListViewController;
var sumsInsuredFrame = sumsInsController.View.Frame;
sumsInsuredFrame.X = View.Frame.Size.Width;
sumsInsController.View.Frame = sumsInsuredFrame;
sumsInsController.ClaimId = ClaimId;
sumsInsController.Title = $"Sums insured for {Title}";
AddChildViewController(sumsInsController);
ScrollView.AddSubview(sumsInsController.View);
sumsInsController.DidMoveToParentViewController(this);
ScrollView.ContentSize = new CGSize(View.Frame.Size.Width * 2, View.Frame.Size.Height - 49);
This is the code I "need" to work, because it loads the navigation bar and that ViewController's custom navbar items (as I said this one "works" but it shows the correct navigation bar below the standard one, it doesn't substitute it):
var viewController = Storyboard.InstantiateViewController("detailClaimViewController") as DetailClaimViewController;
viewController.ClaimId = ClaimId;
AddChildViewController(viewController);
ScrollView.AddSubview(viewController.View);
viewController.DidMoveToParentViewController(this);
var navController = new UINavigationController();
var sumsInsController = Storyboard.InstantiateViewController("sumsInsuredListViewController")
as SumsInsuredListViewController;
var sumsInsuredFrame = sumsInsController.View.Frame;
sumsInsuredFrame.X = View.Frame.Size.Width;
sumsInsController.View.Frame = sumsInsuredFrame;
sumsInsController.ClaimId = ClaimId;
sumsInsController.Title = $"Sums insured for {Title}";
navController.AddChildViewController(sumsInsController);
AddChildViewController(navController);
ScrollView.AddSubview(navController.View);
navController.DidMoveToParentViewController(this);
ScrollView.ContentSize = new CGSize(View.Frame.Size.Width * 2, View.Frame.Size.Height - 49);
Thank you!
Navigation items are defined per contained view controller within a UINavigationController. You can work around that in different ways, but my recommendation would be to use a custom UIViewController that acts as the container for the other UIViewControllers you want to present.
For example, you could build a custom UIViewController that contains your custom navigation bar and a view for the content itself, to act as a custom UINavigationController. With custom transitions, you can mimic the behaviour of the original class.
Please refer to this document for a better explanation on container view controllers.

IOS:UITabbar item click again and again it is reducing the UITabbar button item size in IOS 7

I'm took the Tabbar viewcontroller in this ,I added the 5 item and .I given the image insects is (24,0,0,6).
All button images are added in xib [under the Bar item -->image]Please help.
Thanks.
Adding to a similar answer here:
iOS Tab Bar icons keep getting larger
Not sure if this is an iOS7 bug but I've noticed that image insets need to be balanced.
You have specified insets for top and right but:
if you set a top inset, in order to balance it, you need to set the negative of it to the bottom inset
if you set a right inset, in order to balance it, you need to set the negative of it to the left inset
So, instead of having image insets like (24,0,0,6), use balanced image insets such as UIEdgeInsetsMake(24,-6,-24,6)
Doing so should protect your tabBarItem image from getting whacked on every tap.
If this doesn't suit your requirements, then redesign your tabBarItem image so you can have balance insets or... no insets at all.
Here's the workaround for a bug I've encountered with UITabBarController's UITabBar. If I tap a UITabBarItem once after it's selected, the icon shrinks. What I'd like to do is disable touches. UITabBarItem only has a setting for isEnabled, which grays it out if I set it to false...not what I was looking for.
I used a derivative of this answer to figure it out. With a UITabBarController with 3 tabs, printing tabBarController.subviews, I saw 3 UITabBarButtons and a UIBarBackground. The origin of UIBarBackground's frame was always (0, 0), putting it at the front of the sorted array, so I really don't need to know what the subview is, just "where it is" and whether it will always be there. The UIBarBackground is always going to be at the front of an array of tabBarController.subviews sorted by frame.minX, so I just need to remove it from the front.
Solution
Here's what the extension looks like:
extension UITabBarController {
var buttonViews: [UIView] {
var tabBarButtons = tabBar.subviews.sorted(by: {$0.frame.minX < $1.frame.minX})
tabBarButtons.removeFirst()
return tabBarButtons
}
}
I also created a struct in my Constants file, so I don't have to remember tab names:
struct TabBarItem {
static let firstTab = 0
static let secondTab = 1
static let thirdTab = 2
}
...and finally, where to use it:
In viewDidAppear (NOT viewDidLoad), add the following line to disable the UITabBarItem that you don't want to disable, but not gray out:
tabBarController?.buttonViews[TabBarItem.firstTab].isUserInteractionEnabled = false
In viewWillDisappear, re-enable the tab, as follows:
tabBarController?.buttonViews[TabBarItem.firstTab].isUserInteractionEnabled = true

Resources