Change UISearchBar magnify icon color and position - ios

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.

Related

What are the correct dimensions for a custom tab bar item background image?

So I have a .png that's 428x176 px:
I want to use it as a tab bar background image for when an item is in the selected state. The problem is that the image is too big. So now, I'm exploring the different resolution suffixes: #1x, #2x, #3x. But regardless of which I append to the image filename, the image remains too big for the tab bar item's background, although it does get smaller as I increase the resolution factor. How do I determine what the correct dimensions for this image should be?
Keep in mind that this is a background image for when any particular UITabBarItem is in the selected state. It is meant to be the entire width and height of the UITabBarItem. My tab bar will have three items laid across the width of the screen.
Update:
A lot of answers are providing swift based solutions, but what I'm asking for is what dimensions my image should be in pixels, in other words, what sized images should I be including in my bundle, so that the image will fit in the tab bar at all screen sizes. I imagine that since a UITabBar by default expects a UIImage for its selectionIndicatorImage field and not a UIImageView that there must be a solution that doesn't involve hacking around the UITabBar and adding a UIImageView as a subview of it and managing what position the image view should be in, manually, based on which UITabBarItem is currently selected.
Making my answer for this question how to make UITabBar selection indicator image fill the whole space? as reference:
Subclass the UITabBarController
It works for multiple devices even with rotation.
Notes:
Make your images' rendering mode as Original.
Assign this class below to your UITabBarController in your Storyboard or as your base class if you're doing your screen programmatically.
//
// BaseTabBarController.swift
// MyApp
//
// Created by DRC on 1/27/17.
// Copyright © 2017 PrettyITGirl. All rights reserved.
//
import UIKit
class BaseTabBarController: UITabBarController {
let numberOfTabs: CGFloat = 4
let tabBarHeight: CGFloat = 60
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateSelectionIndicatorImage()
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
updateSelectionIndicatorImage()
}
func updateSelectionIndicatorImage() {
let width = tabBar.bounds.width
var selectionImage = UIImage(named:"myimage.png")
let tabSize = CGSize(width: width/numberOfTabs, height: tabBarHeight)
UIGraphicsBeginImageContext(tabSize)
selectionImage?.draw(in: CGRect(x: 0, y: 0, width: tabSize.width, height: tabSize.height))
selectionImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
tabBar.selectionIndicatorImage = selectionImage
}
}
There's no clear cut answer for this as the tab bar itself isn't of fixed size on various iOS versions and various iOS devices.
Starting iOS 11, tab bar will have smaller height and titles will move to right in landscape mode.
So the idea is to have a stretchable image that can be stretched along all all edges - top/leading/bottom/trailing.
For your reference -
http://macoscope.com/blog/stretchable-images-using-interface-builder/
Here are few images from above blog post to help make it clear -
Hope this helps.
Use the below two lines.
self.tabBarController.tabBar.autoresizesSubviews = NO;
self.tabBarController.tabBar.clipsToBounds = YES;
Xcode works with point, not pixels, so the width will always be 320. In the case of retina display one point is 2x2 pixels and in normal mode it is 1x1.
I think the height for the tab bar should be 320x49 for normal and 640x98 for retina.
the retina image should have the same name as the normal one with the #2x at the end.
Rename your image to tabbarBack#2x.png. This is called pixel doubling for the Retina Display.
Without the #2x iOS doesn't know that it should apply a scale factor and it will be used as it is and though it should be halved.
tabbarBack.png (45 px or so)
tabbarBack#2x.png
[[[self tabBarController] tabBar] setBackgroundImage:[UIImage imageNamed:#"tabbarBack.png"]];
Have you tried with adding imageView as subview of tabbar
var bgView: UIImageView = UIImageView(image: UIImage(named: "background.png"))
bgView.frame = CGRectMake(0, 420, 320, 60)//you might need to modify this frame to your tabbar frame
self.view.addSubview(bgView)
If we talk about height & width of tabbar ,it is 320*49 / 640*98 #2x for standard tabbar. so if you want to keep same dimension try with these width/height ratio.
To add to Tarun Tyagi's answer:
If you add the image to the asset store you can also do visual slicing with the system tools.
Create an asset catalog
Drag & Drop your image into the asset catalog.
Select that image in the asset catalog and click on the "Show Slicing" button on the bottom right
Click on "Start Slicing" and slice that image
Try resizing the image to the tab bar size. Or Add an imageView to the tabBar as subview, and then use the image in that imageView.
Subclass the TabBarController and add imageview there:
class YourTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
let backgroundImage = UIImageView(image: UIImage(named: "gray background"))
backgroundImage.frame = backgroundImage.bounds
self.view.addSubview(backgroundImage)
}

Xamarin iOS Table View Cells Intersecting Search Bar

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

How to set the leftview location on UITextfield to be close to the placehoder text

I am using UITextfield as a search field to allow users filtering the content. When a user open the UI, the UITextField will show a placeholder message "search" in the center of the textfield. I want to add a leftview icon right before the placeholder text(see below code). The leftwiew icon will be shown on the very left of the text field. I want to place it right before the text. How can I find the right position for it?
searchText.placeholder = "Search"
searchText.leftView = UIImageView(image: UIImage(named: "cion_03.png"))
searchText.leftView?.contentMode = .ScaleAspectFit
searchText.leftViewMode = .Always
You forgot to set frame for view. Try to set proper x position to your'e image.
let icon = UIImageView(image: UIImage(named: "cion_03"))
icon.frame = CGRectMake(0.0, 0.0, icon.image.size.width+10.0, icon.image.size.height);
icon.contentMode = UIViewContentMode.Center
self.textField.leftView = icon;
self.textField.leftViewMode = UITextFieldViewMode.Always
Your best bet, for this level of customization, is to subclass UITextField. You will be able to modify the frame of the placeholder text, to modify its position.
You should override placeholderRectForBounds:. Once that is changed, you might find that you will need to override textRectForBounds: to match the placeholder text position.
I've seen this approach used successfully, to accommodate certain fonts.
I spent a day trying to do this using the UITextField subclass. Got it mostly working but I also needed to change the text alignment from centered to left-aligned when editing. I ended up solving this by constraining an image view to the front of the text field and it worked great. I was even able to animate them back and forth and everything.

Avoid status bar transparency while animating

I got the viewController with 2 elements:
view with labels and buttons
tableView
I'm getting the following animation by changing view's height constraint from 170 to 0 and than animating view.layoutIfNeeded() and tableView.layoutIfNeeded().
My goal is to hide menu when content offset of the tableView reaches some value.
This works fine, except I got an overlay of status bar over the moving content from my view. Are there any options to add a sublayer to status bar not to be transparent? Or any other suggestions?
Thanks!
Create a view, put it where the status bar will be, and set its background color to which ever color you require. For example:
let statusBarView = UIView(frame: UIApplication.sharedApplication().statusBarFrame)
statusBarView.backgroundColor = UIColor.blackColor()
view.addSubview(statusBarView)
Or, set the content edge inset by (20.0, 0.0, 0.0, 0.0), which I would agree is a much more elegant solution, as suggested by #holex in the comments

Monotouch UIView Appearance changing UITextField background colors, UIButton background colors, etc

I am trying to implement a custom appearance for UIView when contained in UIViewController.
var viewStyle = UIView.AppearanceWhenContainedIn(typeof(UIViewController));
viewStyle.BackgroundColor = UIColor.Blue;
The result I get from doing this is something ugly, like this:
I tried adding code to change the UITextField/UIButton background by doing:
var txtBoxStyle = UITextField.AppearanceWhenContainedIn(typeof(UIViewController));
txtBoxStyle.BackgroundColor = UIColor.White;
var btnStyle = UIButton.AppearanceWhenContainedIn(typeof(UIViewController));
btnStyle.SetTitleShadowColor(UIColor.White, UIControlState.Normal);
btnStyle.SetTitleColor(UIColor.Black, UIControlState.Normal);
but that doesn't help my result at all (the above image isn't updated from when I changed the button title color from white to black, you'll have to imagine the button's text as black instead of white). Anyone know how to get rid of that ugly blue in the (foreground or background?) of the UITextFields and UIButtons? Bonus if you can figure out why the Title's background is blue as well and how to fix that!

Resources