Xamarin iOS Table View Cells Intersecting Search Bar - ios

I'm writing an iOS app using Xamarin and am having a problem with a table view and search bar - when the search bar has been clicked and text entered, the search results view controller doesn't work properly - the cells, when scrolled, intersect the search bar.
For clarity, I've recorded the problem:
YouTube - iOS Problem
So far, I've worked-out that the problem isn't related to the number of sections, the section header, or the table header. Completely out of ideas now, though...
The following can be used as an example, as the same problem appears there:
GitHub - TableSearch
In this example, adding the following line of code to the end of the 'ViewDidLoad ()' method within the 'MainTableViewController.cs' file will make the problem more obvious:
searchController.SearchBar.SearchBarStyle = UISearchBarStyle.Minimal;
EDIT
Looking at the image below, I ideally need to remove or shrink the top region (what seems to be a space for the iOS navigation bar):

Have you had a look at the sample from Xamarin here which has the same layout you are using, just to compare how you set up the search bar.
EDIT
I now see what you mean, I think this is a bug in iOS as the background color is transparent on the search bar and you would never want that.
I just added another view to cover up the status bar and set the background color to white:
searchController.SearchBar.SearchBarStyle = UISearchBarStyle.Minimal;
searchController.SearchBar.BackgroundColor = UIColor.White;
var frame = searchController.SearchBar.Frame;
frame.Height = searchController.SearchBar.Frame.Height + 22;
frame.Y = searchController.SearchBar.Frame.Y - 22;
var bckGRound = new UIView (frame);
bckGRound.BackgroundColor = UIColor.White;
searchController.SearchBar.InsertSubview (bckGRound, 0);
UPDATE
I realised that for your scenario you can't just add a view to cover this up so i was looking into adding blurring to searchbar like so:
var frame = searchController.SearchBar.Frame;
frame.Height = searchController.SearchBar.Frame.Height + 44;
frame.Y = searchController.SearchBar.Frame.Y - 22;
var blurryBackGround = new UIView (frame);
if (!UIAccessibility.IsReduceTransparencyEnabled)
{
blurryBackGround.BackgroundColor = UIColor.Clear;
var blureffect = UIBlurEffect.FromStyle (UIBlurEffectStyle.Light);
var blureffectview = new UIVisualEffectView (blureffect);
blureffectview.Frame = frame;
blurryBackGround.AddSubview (blureffectview);
}
else
{
blurryBackGround.BackgroundColor = UIColor.Black;
}
searchController.SearchBar.InsertSubview (blurryBackGround, 0);
UPDATE 2
If your background doesnt move with the table then you might be able to get away with just cropping the background image section that the search bar covers then set the backgroundimage for the search bar with this code:
searchController.SearchBar.SetBackgroundImage (new UIImage ("image.jpg"), UIBarPosition.TopAttached, UIBarMetrics.Default);

That is the UISearchController's default behavior. You can change the background color so that the rows don't appear behind the searchBar but that doesn't appear to be the behavior you want. Another option is to implement the UISearchBar on your ViewController which is what I have and it does scroll with the rows which is the behavior you are looking for. Hope this helps.
See: https://github.com/xamarin/monotouch-samples/tree/master/SearchDemo/SearchDemo

Related

How to remove 1px bottom border from UINavigationBar *with* a UISearchController?

I have a navigation bar which includes a UISearchController, and I cannot find a way to get rid of the 1px bottom border below the navigation bar:
I am already using the tricks for removing the navigation bar bottom border as suggested in this answer and many others:
navigationBar.isTranslucent = false
navigationBar.setBackgroundImage(aTransparentImage, for: .default)
navigationBar.shadowImage = nil
If I don't set the searchController on the navigationItem of my view controller it's fine, there is no bottom border, but as soon as I set the searchController it appears.
Even the dirty hacks that look for a 1px UIImageView in the nav bar view hierarchy don't work, as it seems this view is in a separate tree of the hierarchy. It's the UIImageView highlighted in blue below:
I'm out of ideas 😕
Ok, a colleague of mine provided a solution. In viewWillAppear in the view controller which is showing the search bar do:
if let imageView = navigationItem.searchController?
.searchBar.superview?
.subviews.first?
.subviews.last as? UIImageView,
imageView.frame.height * UIScreen.main.scale == 1.0 {
imageView.isHidden = true
}
This is obviously highly dependent on the exact view hierarchy that UIKit is using for the search bar, and could stop working with any future release of iOS (it works on iOS 12). You could make it more resilient by searching the superview subviews for a 1px height UIImageView, but still, it's quite a hack.
But so far, it's the only solution I have found that works.
Try to add
self.extendedLayoutIncludesOpaqueBars = true
or
self.automaticallyAdjustsScrollViewInsets = false;
self.extendedLayoutIncludesOpaqueBars = true
in ViewDidLoad Method. It worked for me

Editing navigation bar's shadow line UIImageView having no effect

I'm attempting to alter the Navigation Bar's narrow shadow bar and am using the following code:
if let hairline = findNavigationBarHairline(navigationBar)
{
hairline.bounds.size.height = 5.0
hairline.backgroundColor = UIColor.blueColor()
}
and this:
func findNavigationBarHairline(view:UIView) -> UIImageView?
{
if let hairline = view as? UIImageView where hairline.bounds.size.height <= 1.0
{
return hairline
}
for subview in view.subviews
{
if let imageView = findNavigationBarHairline(subview)
{
return imageView
}
}
return nil
}
This sucessfully finds the UIImageView which is the shadow line but if I try and change anything here it has no effect. Here's a po of the Image View at that point in the code just after its size/color has been set:
(lldb) po hairline
<UIImageView: 0x126d21030; frame = (0 61.75; 320 5); userInteractionEnabled = NO; layer = <CALayer: 0x126d0b470>>
Here it can be seen the height is 5, however it is still displayed with its original size and color. If I use XCode's view hieararchy display and dump the image view from there this is the result:
> Printing description of $124: <UIImageView: 0x126d21030; frame = (0
> 64; 320 0.5); userInteractionEnabled = NO; layer = <CALayer:
> 0x126d0b470>
As can be seen it is the same object, however its height is 0.5 and not 5.
Why is the change to the size and color having no effect? (I have also changed the UIImage, but that is not having any effect either).
First - You should do this by setting an image to the shadowImage property of UINavigationBar. That's what that property is for. Note that you have to set a custom background image via setBackgroundImage(_:forBarMetrics:) for this to work. Using the code below I was able to create a white translucent navbar with no shadow. Note that the white image is just a white pixel, which you could easily enough create in code.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
navigationController!.navigationBar.setBackgroundImage(UIImage(named: "white"), forBarMetrics: .Default)
navigationController!.navigationBar.shadowImage = UIImage()
}
The result was:
Second - Spelunking into the view hierarchy of components provided by the SDK is generally not the best idea. You've got no guarantees that the view hierarchy won't change in future releases (or that what you've got works on older iOS version, for that matter).
Having said, what you are doing is not working most likely because setting a backgroundColor on an image view isn't going to change the image being rendered by that image view. Second, it's very likely that Apple uses Auto Layout to organize the subviews of UINavigationBar, so the frame/bounds is essentially going to be derived data and Auto Layout will just reset it if you change it.

Change UISearchBar magnify icon color and position

I have a UISearchBar and I would like to change the position of the initial magnify icon (the one that appears in the middle of the UISearchBar) as well as the color or icon.
So far I changed the tint and the icon image.
However, the new icon shows up only if I test the app on a simulator but on an actual device(both run iOS 9.3) it still shows the default icon.
UISearchBar.appearance().setImage(UIImage(named: "SearchbarIcon"), forSearchBarIcon: UISearchBarIcon.Search, state: UIControlState.Normal)
As for the magnify icon position, I want it in the left side, where it shows up if I activate the UISearchBar.
I found quite a lot of answers around here many of the provided solutions don't work on iOS 8.0+ or are in Objective-C and I am having some problems understanding them.
I tried to add a custom background containing the icon but it shows up at the bottom of the search bar while the icon is still there:
The background shows up OK if I change the background offset for Y to -44 (the height of the UISearchBar) but I can no longer type since it seems the entire text field is pushed up. I also tried to change the vertical offset for the SearchText to 44 to compensate but no luck. To be honest, I am not sure what Search Text and the Background offsets are supposed to do but I decided to give them a try.
Is there any way to accomplish this? Or maybe a different approach?
You can adjust the position of the search bar icon using
func positionAdjustmentForSearchBarIcon(_ icon: UISearchBarIcon) -> UIOffset
See https://developer.apple.com/library/ios/documentation/UIKit/Reference/UISearchBar_Class/#//apple_ref/occ/instm/UISearchBar/positionAdjustmentForSearchBarIcon:
You can use:
uiSearchBar.setPositionAdjustment(UIOffset, for: UISearchBar.Icon)
replace UIOffset with your desired offset value UIOffset(horizontal: CGFloatvertical: CGFloat) and UISearchBar.Icon with .search
#Michael - Thanks for all the help.
I managed to grab the UISearchBar's UITextField:
func customizeSearchBar()
{
for subview in srcRegimenSearchBar.subviews
{
for view in subview.subviews
{
if let searchField = view as? UITextField
{
let imageView = UIImageView()
let image = UIImage(named: "SearchBarIcon.png")
imageView.image = image;
imageView.frame = CGRectMake(0, 0, 0, 0)
/*imageView.frame = CGRectMake(100, 0, 20, 19)*/
searchField.leftView = imageView
searchField.leftViewMode = UITextFieldViewMode.Always
}
}
}
}
I wanted to change the position since I have access to the frame but it seems only the the top and height can be modified, at least the way I tried so I set the height and width to 0 (I couldn't find a way to make it nil or remove it completely) and I added an UIImageView with the new icon over in the left side of the UISearchbar and added a custom horizontal offset for the tint.
Not the best solution out there, I'm sure of it, but for now it works.

Xamarin iOS Navigation Bar 100% Transparency

i´m developing an iOS-Application with VisualStudio/Xamarin. I have to set the transparency on the navigationbar to 100%. But let me explain the whole thing:
On the first view the navigationbar have a background image set by this code:
var navigationImage = UIImage.FromFile("gradient.jpg");
UINavigationBar.Appearance.SetBackgroundImage(navigationImage, UIBarMetrics.Default);
The first view got several tablecell items, if clicked, a detail view shows up.
On that detail view the navigationbar should be completely transparent! Only the back button and a title should be leftover.
I tried everything from translucent = yes to this solution which i also found here on stackoverflow.
I also tried to set a color to the first navigationbar and then change it on the next view to another color which works, but if i get back to the firstview the navigationbar color stays the same, even if i override the ViewWillAppear-method from the first view where the BarTintColor is set.
Thanks for your help!
greetings
Well, for what it's worth, I actually followed your solution link and translated it to Xamarin. If I put the following code in ViewDidLoad on my VC, the Navigation Bar is completely transparant ;)
this.NavigationController.NavigationBar.SetBackgroundImage (new UIImage (), UIBarMetrics.Default);
this.NavigationController.View.BackgroundColor = UIColor.Clear;
this.NavigationController.NavigationBar.BackgroundColor = UIColor.Clear;
this.NavigationController.NavigationBar.ShadowImage = new UIImage ();

How to create a Tab Bar appear on the left instead of the Bottom/Top?

Hey guys here is my dilemma. I am trying to create a tab bar that spans top to bottom anchored at the left side instead of left to right anchored at the bottom. I created a toolbar item that places the bar exactly where I want it but I want the tab bar to be the same, with the same functionality except of course with the hairline in place, and the bar items lining up top to bottom.
This is my code for the tool bar, I know the tab bar will be coded similarly, I just hit a slump.
UIToolbar *toolBarLeft = [[UIToolbar alloc] init];
toolBarLeft.frame = CGRectMake(0, 20, 50, 568);
toolBarLeft.layer.borderColor = [UIColor lightGrayColor].CGColor;
toolBarLeft.layer.borderWidth = 0.5f;
[self.view addSubview:toolBarLeft];
I appreciate the help guys!
The gist of what you need to do is this:
Subclass UITabBarController.
Make sure the default tabBar property's hidden property gets set to YES (so its hidden) and stays that way.
Add any custom view you want to use as the tabbar to this subclass's view property (just as you'd add a view as a subview to a UIViewController).
The subview you add in step 3 should respond to touches and have a delegate property. The UITabBarController subclass should delegate the view so it can respond to different tabs being selected (as well as many other things).
As long as the navigation is logical and easy to understand, your app won't be rejected simply for modifying how a tab bar works.
ADDENDUM:
For step 3, given you want tabs stacked vertically, I'd actually recommend a UITableView subclass where the value returned from tableView:heightForRowAtIndexPath: is calculated something like this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
CGFloat totalHeight = tableView.frame.size.height;
CGFloat totalTabs = (CGFloat)[tableView numberOfRowsInSection:0];
return totalHeight/totalTabs;
}
And scrolling is disabled.
Because now when tableView:didSelectRowAtIndexPath: is fired, we can tell the tab bar controller: tabBarController.selectedIndex = indexPath.row;

Resources