How to center a SF Symbols image vertically in UITabBarItem? - ios

I am using SF Symbols images as tab images in my iOS app by assigning them as follows:
self.tabBarItem.image = UIImage(systemName: "ellipsis")
This results in all images being top-aligned, but I would like to have them centered vertically.
What do I have to do for this?

Apparently SF symbols are rendered with system font size by default. So if you add a baseline offset of half that size to the ellipsis symbol you could almost perfectly center it vertically that way.
It's only almost perfect because ellipsis symbol has a height of its own which is not accounted for by this solution, even if it is not much.
self.tabBarItem.image = UIImage(systemName: "ellipsis")!.withBaselineOffset(fromBottom: UIFont.systemFontSize / 2)

The best solution, which will make your button identical to "tabBarSystemItem: .more", but with the possibility of removing the title and applying Configuration is the following:
self.tabBarItem.image = UIImage(systemName: "ellipsis", withConfiguration:
UIImage.SymbolConfiguration(weight: .black))!.imageWithoutBaseline()

You have to set the image insets on the UITabBarItem to shift your icons down 6 or 7px (depending on your icon size).
In code:
I've done this by creating a subclass of UITabBarController and adding this code to the bottom of my viewDidLoad method:
tabBar.items?.forEach({
$0.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0)
})
(You could also do this in your ViewController classes, if that's where you configure each of their tab bar items.)
In storyboards:
You can also do it using storyboards by selecting your TabBarItem in the storyboard and adjusting the insets in the info panel:

Related

How do you make a UIButton with no text be the size of its image?

I created a UIButton in Interface Builder that consists of only an SF Symbol and no text. The button draws with insets around the image, which affects how it's positioned with constraints. How do I remove that extra space, so that the button view is just the size of the SF Symbol image?
Button with the intrinsic size of the Image
A button will take the size of the image by default. but since SF-Symbols are vectors, they can be scaled to any size. Each symbol has a few predefined sizes that you can choose:
Also, you can set your own size in the code:
let config = UIImage.SymbolConfiguration(pointSize: 160, weight: .bold, scale: .large)
let largeChevronImage = UIImage(systemName: "chevron.right.circle.fill", withConfiguration: config)
button.setImage(largeChevronImage, for: .normal)
Add or Remove Extra space around the image
Some images and SF-Symbols have some paddings around their content. You can control the size of the padding by setting the ContentEdgeInsets
You can clip the bounds to hide the out of frame content
All SF-Symbols have same size

How to vertically center a font glyph?

I have a UIButton with title "⟳". The title does not appear to be vertically centered due to the position of "⟳".
I understand that offsets of the UIButton can be changed to solve the problem in this instance.
Can anyone point out if there is any other way to vertically center the "⟳" glyph?
In this image, all 4 green buttons are using 64-pt System font, with the .titleLabel background set to yellow:
As you can see with the top button, an upper-case "O" is centered vertically and horizontally.
The "⟳" unicode symbol you are using is more like a lower-case character - as seen in the 2nd button.
By itself, in the 3rd button, we see it appears "shifted" down and to the left.
The symbol in the bottom button is center-aligned by adjusting the Title Edge Insets:
.titleEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 14, right: 0)

UITabBarItem - Position image separately from title text

I have a UITabBar with 5 UITabBarItems, each containing an image and a title. Currently, the images are positioned centered above the title text. When an item is selected I bold the text, however this causes the positioning of the image to change slightly since the text now takes up more space. How can I divorce the positioning of these two elements in a UITabBarItem?
Try adjusting the image insets to get your desired look.
For example, you could try:
tabBarItem.imageInsets = UIEdgeInsets(top: -1, left: 0, bottom: 1, right: 0)

UISegmentedControl maintain aspect ratio on image

I'm having a hard time making images on a UISegmentedControl keep their aspect ratio and not scale to all sides.
Here's what it looks like:
The images are 100X100(except nr 6 gonna replace soon) and I want them to maintain the aspect ratio.
I have tried:
self.segment.contentMode = .ScaleAspectFit
//and:
self.segment.contentMode = UIViewContentMode.Center
Are there a way I can target the UIImageView in the segment..that way I can set the contentMode..right? Or is there another approach?
Thanks
segmentedControl.subviews.flatMap{$0.subviews}.forEach { subview in
if let imageView = subview as? UIImageView, let image = imageView.image, image.size.width > 5 {
// The imageView which isn't separator
imageView.contentMode = .scaleAspectFit
}
}
Actually, there's a great, general purpose solution for this:
UIImageView.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).contentMode = .scaleAspectFit
This uses the approach described here: UIImageView.appearance is overriding UISegmentedControl.appearance
In my case, I constrained it to a subclass of UISegmentedControl (in case I want the default aspectFill for other situations).
I didn't find how to set the contentMode to ScaleAspectFit but you can use the following code to set a margin around your image when you are setting the image :
yourSegmentedControl.setImage(yourImage.resizableImage(withCapInsets: .init(top: 0, left: 10, bottom: 0, right: 10), resizingMode: .stretch), forSegmentAt: 0)
You can change the values of "top", "left", "bottom" and "right" as you want.
This worked for me, I hope it will help!
It is probably late for this, but Im sure it will help someone.
My Problem #1:
Images in the segmented control are distorted in ratio.
My Problem #2:
You can't even change the colour of the image. It remains black. Even if you use .alwaysTemplate and imageview tint colour. It wont budge.
Solution:
Forget trying to hack the SDK, or achieving the goal through unofficial means. Apple can easily change the SegmentedControl and all your work becomes redundant.
Use this instead: BetterSegmentedControl. Happy coding.
It is highly customisable and easy to use, plus it supports images.

Maximize Size of UITabBarItem image

I would like to create a custom UITabBarItem with a Icon-image thats size is a little bit bigger than usual. The thing is I don't want to use a full replace of the background image because i would like to have the translucent effect of the TabBar.
So i would like to know 2 things:
What sizes are now correct for the new iOS7 UITabBarItems and their icons
How do I modify the size of the icon to display a bigger icon, because i dont want to show a title. Without the title its kinda small. In mind to keep the translucent effect displaying.
Any help or suggestions would be great!
Regardless of the icon’s visual style, create a toolbar or navigation bar icon in the following sizes:
About 44 x 44 pixels
About 22 x 22 pixels (standard resolution)
Regardless of the icon’s visual style, create a tab bar icon in the following sizes:
About 50 x 50 pixels (96 x 64 pixels maximum)
About 25 x 25 pixels (48 x 32 pixels maximum) for standard resolution
Have a look at these Developers guide for bar & buttons
Bar icons in Human interface guidelines
To increase the size, try below code,
NSArray *items = self.tabBarController.tabBar.items;
for (UITabBarItem *b in items)
b.imageInsets = UIEdgeInsetsMake(-5, -5, -5, -5);
If you want to decrease, try passing positive values to UIEdgeInsetsMake(top,left,bottom,right)
Swift 4.2,
let array = tabBarController?.tabBar.items
for controller in array! {
controller.tabBarItem.imageInsets = UIEdgeInsets(top: 5, left: -5, bottom: -5, right: -5)
}

Resources