UISegmentedControl maintain aspect ratio on image - ios

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.

Related

How to center a SF Symbols image vertically in UITabBarItem?

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:

How can I bring a UIView's border behind a UIImage?

I'm new to Swift and I'm facing an issue while trying to develop a small application and I really hope someone will help me out.
Basically, I have a UIImage inside a UIView, and I want to send the UIView's border to the back (See picture below)
So, I'm giving the UIView a border, and it goes through my image. My question is:
How do I bring the border of the UIView behind the UIImage?
Note: I apologize if this is a repeated question, I was looking for answers for hours but couldn't find what I need.
Best regards!
Here is my code for the Image:
speakerImage.layer.cornerRadius = speakerImage.frame.size.width / 2;
speakerImage.clipsToBounds = true;
speakerImage.layer.zPosition = 1
And here is my code for the View:
speakerContentView.layer.cornerRadius = 5
speakerContentView.layer.borderWidth = 1
speakerContentView.layer.borderColor = UIColor.gray.cgColor
speakerContentView.layer.shadowColor = UIColor.gray.cgColor
speakerContentView.layer.shadowOpacity = 0.7
speakerContentView.layer.shadowOffset = CGSize(width: 0, height: 3)
speakerContentView.layer.zPosition = -1
This may help you!!
Move your image outside current (speakerContentView) view and set it in higher hierarchy so that it can get front position.
Set vertical center Y of image equal to current (speakerContentView) view Y
Look at this image:
May be not a standard way but will solve your problem.
You should add a subview with the same size of the superview below the image, and assign the border/shadow to it instead of its superview.

Custom UISlider using UIEdgedInset does not render well

I'm trying to do a custom uislider using images (without a visible knob, i hide it when user can't edit and show it when he can) The problem is that the the side render perfectly but the right part is cute and doesn't seems to use the edges...
Any idea how i can edit it ?
Actual code :
let capLeft:CGFloat = 9
let capRight:CGFloat = 9
imageMin = imageMinimum?.resizableImage(withCapInsets: UIEdgeInsets(top: 0, left: capLeft, bottom: 0, right: capRight), resizingMode: .stretch)
imageMax = imageMaximum
slider.setMaximumTrackImage(imageMax, for: UIControlState())
slider.setMinimumTrackImage(imageMin, for: UIControlState())
How it's rendering :
How it should render :
Minimum track image :
Maximum Tracking Image :
Do you have any idea ?
I think there is a bit of confusion about Min and Max images with UISlider.
The Min image is drawn (and stretched) on the Left side of the Thumb. The Max image is drawn (and stretched) on the Right side of the Thumb.
Create a small, square solid red image - such as 16x16 - and assign it (without insets) to .setMaximumTrackImage. See how that ends up looking, as you go from low to high values.
Edit: I used NO insets on the Min image for this example...
Note: I used a 20x20 clear image for the Thumb in these caps.

How to make UIButton a circle?

I have been trying to make the UIButton in the cells a perfect circle. Unfortunately the circle has been formed based on the background image rather than the UIButton frame.
The code I have for creating a circle:
cell.StoryViewButton.setImage(image, forState: .Normal)
cell.StoryViewButton.frame = CGRectMake(50, 8, 100, 100)
cell.StoryViewButton.layer.masksToBounds = false
cell.StoryViewButton.layer.cornerRadius = cell.StoryViewButton.frame.width/2
cell.StoryViewButton.clipsToBounds = true
The output looks like this:
What can I do to get the perfect circle button frames that I want?
Try something like this
cell.StoryViewButton.layer.masksToBounds = true
cell.StoryViewButton.layer.cornerRadius = cell.StoryViewButton.frame.width/2
If you need to create a circle of view you have to set masksToBounds to true, do not set clipsToBounds
Hope this will help you.
Swift 4
You could apply the following function to any view, including buttons.
func makeViewCircular(view: UIView) {
view.layer.cornerRadius = view.bounds.size.width / 2.0
view.clipsToBounds = true
}
Great.
That didn't work for me at first as I applied it in the viewDidLoad, though. At this point, constraints are still playing with the size of your buttons and the corner radius is applied to a button it thinks is twice the size, resulting in the odd shapes you have. To apply the right values to the right measurements, place the code in override func viewDidLayoutSubviews().
I know this may be a more specific case within my personal process, yet I'm sure it'll help somebody.
There is the working code.I test it. Hope it helps.
I am not sure why but I check that by changing height and width of the frame in here "CGRectMake(50, 8, 120, 120)" that the height and width of the frame and height and width of a button should be same to get the perfect circle.
cell.StoryViewButton.setImage(image, forState: .Normal)
cell.StoryViewButton.frame = CGRectMake(50, 8, 120, 120)
cell.StoryViewButton.layer.cornerRadius = self.btn.frame.width/2;
cell.StoryViewButton.layer.masksToBounds = true
Hope it helps.

How add background image to UIControl

I create 3rd party keyboard and i try add background to my keys. I use UIControl for my keys, without storyboard.
I have several types of buttons and try to add background UIView for my characters.
let img = UIImage(named:"KeyBackground")
var bgImage: UIImageView?
bgImage = UIImageView(image: img)
bgImage!.frame = keyboardKey.frame
keyboardKey.addSubview(bgImage!)
keyboardKey.sendSubviewToBack(bgImage!)
keyboardKey.backgroundColor = UIColor.clearColor()
But is don't work.
I try to add background image like this:
keyboardKey.backgroundColor = UIColor(patternImage: UIImage(named:"KeyBackground")!)
But is looks bad...
What am i doing wrong?
The background looks like that because the size of your image is a little smaller than the size of each key, and the image is being tiled (repeated to fill the space - so each key contains the background image and pieces of the surrounding tiles to the right, bottom, and bottom-right).
The UIColor(patternImage:) docs say that
During drawing, the image in the pattern color is tiled as necessary to cover the given area.
Your first solution probably didn't work because you inserted your UIImageView as the bottom-most subview - I assume another (opaque) view was on top of it. What type of UIControl are you using? UIButton, for example, already provides some "background image" support out of the box.
Oh, it's so easy. My keyboardKey.frame, at the time of the call this method, have frame = 0, 0, 0, 0.
Night a bad time for work:)

Resources