UIImageView tintColor wrong on device - ios

I have a UIImage and a UILabel next to one another, and set the label textColor and the imageView tintColor UIColor.purple.
However, on the device, the purple on the image is darker, it looks fine in the simulator though. I checked in the view hierarchy debug, and indeed the label has 0.5, 0, 0.5 as textColor, but the imageView has 0.4, 0, 0.4 as tintColor for some reason.
I tried setting 0.6, 0, 0.6 on the imageView, and it resulted in the tintColor being 0.48, 0, 0.48.
Any idea why that is ? I don't want the SDK to adjust my colour in any way, I just need the tintColor to be what I set it to be.
The code is quite simple here:
titleLabel.textColor = .purple
imageView.tintColor = .purple
I also noticed that setting the tintColor to .purple on the UILabel also results in it having 0.4, 0, 0.4 as tintColor rather than 0.5, 0, 0.5 as with textColor. For some reason the tintColor property edits the color it's given.

Related

How to set opacity of ImageView layer border

How to set profile Border opacity ?
How to set transparent for having opacity of border color with .white of 50% opacity.
profileView.layer.borderWidth = 3.0
profileView.layer.borderColor = UIColor.white.cgColor
Use withAlphaComponent:
profileView.layer.borderColor = UIColor.white.withAlphaComponent(0.5).cgColor
or:
profileView.layer.borderColor = UIColor.white.cgColor.copy(alpha: 0.5)
Obviously you can choose whatever alpha value you want in the range 0.0 to 1.0.
Or in this case you can use:
profileView.layer.borderColor = UIColor(white: 1.0, alpha: 0.5).cgColor
for alternative you can add UIView behind and set it as border of you ImageView, it's easier to set the oppacity

How do I get the grey color/translucency I see on UIPickerDate default view on my own custom Picker?

I have created a UI Picker but the default is just it being transparent. I would like to use/be given the RGB + translucency values that makes the grey color that is commonly used on picker views.
It is the same grey like the defualt color for a programmatic UI Date Picker. Thank you! I need this to be in alignment with Apple's Human Interface Guidelines.
Added a picture of the background color/translucency I need below:
iPhone SDK has two types of gray color both have opacity 1.
iOS 13 also introduces a range of six opaque gray colors you can use in rare cases where translucency doesn't work well.
https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/color/
And for changing the background color.
light gray color:
picker.backgroundColor = UIColor.lightGray
dark gray color:
picker.backgroundColor = UIColor.darkGray
if you want some transparency on the picker view. You can add Gradient on it.
let view = UIView(frame: CGRect(x: 0, y: 0, width: picker.frame.width, height: picker.frame.height))
let gradient = CAGradientLayer()
gradient.frame = view.bounds
gradient.colors = [UIColor.white.cgColor, UIColor.lightGray.cgColor]
picker.layer.insertSublayer(gradient, at: 0)
find the image as it looks with gradient and light gray color.
picker view with gradient
Hex color - #e8e9ed
RGB color - UIColor(red: 232/255, green: 233/255, blue: 237/255, alpha: 1)
or you can use #f7f7f7
I hope it works.

Custom Color with cgColor

It might be the stupidest question you saw all day but i couldn't find a solution. i have a rounded image view with borders and i want the borders to be the the same blue as the default tint color in Xcode so if you could help that would be great . and sorry for the noonish question ;)
Now i have this:
self.imageView.layer.borderColor = UIColor.gray.cgColor
and i need to change
UIColor.gray.cgColor
to be the same blue as the default tint color without causing a crash or an error ... how can it be done?
thanks for your help.
just create the new color with blue color properties and apply to imageView
let color = UIColor(colorLiteralRed: 0, green: 122/255, blue: 1, alpha: 1.0)
self.imageView.layer.borderColor = color.cgColor
alertnatively you can use tintColor property of imageView like
imageView.layer.borderColor = imageView.tintColor.cgColor
Just drag and drop whatever color you want such as:

Fix UIVisualEffectView extra light blur being gray on white background

Apple provides this live blurring view class UIVisualEffectView and you use it with a UIBlurEffect which takes one of three available UIBlurEffectStyles:
enum UIBlurEffectStyle : Int {
case ExtraLight
case Light
case Dark
}
Now for demo purposes I set up two effect views with the styles Light and ExtraLight:
let lightBlur = UIBlurEffect(style: UIBlurEffectStyle.Light)
let extraLightBlur = UIBlurEffect(style: UIBlurEffectStyle.ExtraLight)
let lightView = UIVisualEffectView(effect: lightBlur)
lightView.frame = CGRectMake(10, 30, 150, 150)
self.view.addSubview(lightView)
let extraLightView = UIVisualEffectView(effect: extraLightBlur)
extraLightView.frame = CGRectMake(160, 30, 150, 150)
self.view.addSubview(extraLightView)
So far so good, everything works as expected, they blur images:
and kind of work on colors, too:
but when it comes to a white background this happens:
The Light effect on the left works as expected, but the ExtraLight effect on the right leaves some kind of gray square behind.
Now the question: Is there any kind of trick or method that would enable me to use an extra light blur effect on white background (with live blurring support) AND remove that ugly gray shadow?
As far as I know the additional tint is a built-in feature of the UIVisualEffectView class. If you examine the view hierarchy with Xcode, you can see that there are two default subviews in the visual effect view instance: UIVisualEffectBackdropView and UIVisualEffectSubview. (I assume that these are private classes.) If you inspect UIVisualEffectSubview you can see that it has a background color which causes the unwanted tint that you've noticed.
I am not sure if there's an officially supported way to remove it, but you can modify this background color by filtering to the name of the private subview:
if let vfxSubView = visualEffectView.subviews.first(where: {
String(describing: type(of: $0)) == "_UIVisualEffectSubview"
}) {
vfxSubView.backgroundColor = UIColor.white.withAlphaComponent(0.7)
}
(Swift 5 compatible)
The default tint is around 70% opacity, so the easiest is to use the target background color with 0.7 alpha component.
I've also noticed that this might reset to the default value if the visual effect contains a custom subview. If I add this same snippet to the viewDidLayoutSubviews function of the view's controller, then it will keep the custom background color even after the built-in subview is updated.
Here's an example with a dark blur effect style. The top part shows the default tint and the bottom version has a custom black background color with 70% opacity.
If you just want the blur and your blurred view is gonna be stationary, you could use the UIImageEffects class and change the tintColor to a "full" white:
- (UIImage *)applyExtraLightEffect
{
UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
}
As far as I know you can't change it in the UIVisualEffectView.
You can try :
var visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .Light))
visualEffectView.frame = imageView.bounds
imageView.addSubview(visualEffectView)
Simple Solution
I could find a simple solution inspired by Shannon Hughes' Blog Post. Just add a white background color with transparency to the effect view. I don't know if it is exactly like extraLight but for me it is close enough.
let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
visualEffectView.frame = sectionHeaderView.bounds
visualEffectView.backgroundColor = UIColor(white: 1.0, alpha: 0.9)
sectionHeaderView.addSubview(visualEffectView)
The following code should do the trick to give it a the desired tint:
let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .regular))
visualEffectView.subviews.forEach { subview in
subview.backgroundColor = UIColor.blue.withAlphaComponent(0.2)
}
Important Note:
I wouldn't recommend adding a check for "_UIVisualEffectSubview" since this class can change on subsequent iOS updates.
Also, there is a possibility of app getting rejected because of this.
iOS 15 has the nice
.background(.ultraThinMaterial)
but it still suffers from the nasty grey tint. Wish there was an option to blur background views without any tint.
I tried a simple color-correct hack which worked for my background color but only in light mode! For dark mode I just made the background solid black (no translucent blur)
.background(
// negate the slight grey tint of ultrathinmaterial
Color("materialTintColorCorrect")
.background(.ultraThinMaterial)
)
My "materialTintColorCorrect" color asset was #F0F8FF 27% opacity for light mode and #000000 100% opacity for dark.
let vc = UIViewController()
vc.view.frame = self.view!.frame
let efv = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.light))
efv.frame = vc.view.frame
vc.view.addSubview(efv)
self.addChildViewController(vc)
self.view.addSubview(vc.view)
// below method has a bug
// self.present(vc, animated: true, completion:nil)
I would recommend adding your extraLightView to a view of UIColor(white: 1.0, alpha: 0.x), where x can be modified based on the scroll view's contentOffset. When there's nothing behind the view, your extraLightView will be white when x is 1. When you scroll and modify x, you won't be modifying the UIVisualEffectView (which is highly discouraged), but rather its parent view, which is perfectly safe.
Works with Swift 5
My way of making the visual effect view completely white when the background view is white.
let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
blurView.backgroundColor = UIColor.white.withAlphaComponent(0.7)

Frame.size.width Not Returning Correct UIButton Width

I am trying to add a top and right border to my button but not the bottom or left. I looked it up and found a suggestion to do so by adding views to look like borders.
//Add borders
let topBorder = UIView(frame: CGRectMake(0, 0, editorBox.frame.size.width/3, 1))
let rightBorder = UIView(frame: CGRectMake(cancel.frame.size.width, 0, 1, cancel.frame.size.height))
topBorder.backgroundColor = UIColor(red: 220/255.0, green: 220/255.0, blue: 220/255.0, alpha: 1.0)
rightBorder.backgroundColor = UIColor(red: 220/255.0, green: 220/255.0, blue: 220/255.0, alpha: 1.0)
cancel.addSubview(topBorder)
cancel.addSubview(rightBorder)
But the resulting Simulator test looks like:
However, the button is definitely not that big because you can't click on the far right side of it. The auto layout constraints confirm that the button is not that big.
I just want each button to have a border around it's actual 1/3 width size, as set in the constraints. Can anyone tell me what's happening and how to fix it?
Looks to me to be an autolayout issue - your button is being generated before the layout changes its width. Your border views, on the other hand, do not get their width changed because they're outside of the constraint hierarchy.
For something this simple though, I think UIViews are a bit too much. I would add a few CALayers to the Button in question.
Here's a stack overflow question directly relating to the CALayer solution:
CALayer: add a border only at one side
It turns out that the other answer didn't solve my border problem by itself. Here's the code I'm using, based on the #tbondwilkinson answer:
//Add borders
let borderColor = UIColor(red: 200/255.0, green: 200/255.0, blue: 200/255.0, alpha: 1.0).CGColor
func formatTopBorder (buttonToFormat: UIButton,borderToFormat: CALayer) {
buttonToFormat.clipsToBounds = true
borderToFormat.borderColor = borderColor
borderToFormat.borderWidth = 2
borderToFormat.frame = CGRectMake(0, 0, CGRectGetWidth(cancel.frame), 2)
}
let topBorder: CALayer = CALayer()
let topBorder2: CALayer = CALayer()
let topBorder3: CALayer = CALayer()
let rightBorder: CALayer = CALayer()
let leftBorder: CALayer = CALayer()
formatTopBorder(cancel, borderToFormat: topBorder)
formatTopBorder(action, borderToFormat: topBorder2)
formatTopBorder(addSave, borderToFormat: topBorder3)
rightBorder.borderColor = borderColor
rightBorder.borderWidth = 2
rightBorder.frame = CGRectMake(CGRectGetWidth(cancel.frame)-2, 0, 2, CGRectGetHeight(cancel.frame))
leftBorder.borderColor = borderColor
leftBorder.borderWidth = 1
leftBorder.frame = CGRectMake(0, 0, 2, CGRectGetHeight(cancel.frame))
cancel.layer.addSublayer(topBorder)
cancel.layer.addSublayer(rightBorder)
action.layer.addSublayer(topBorder2)
addSave.layer.addSublayer(topBorder3)
addSave.layer.addSublayer(leftBorder)
But if placed in the viewDidLoad, it doesn't work perfectly. The top borders work and so does the left border. However, it was still prematurely getting the UIButton width, resulting in the right border not working:
rightBorder.frame = CGRectMake(CGRectGetWidth(cancel.frame)-2, 0, 2, CGRectGetHeight(cancel.frame))
The CGRectGetWidth(cancel.frame)-2 gets the correct right edge and gives space for the border, but it gets the width before the button has sized itself.
The solution:
Use the method and then put that code in the viewDidAppear. Unfortunately, the borders appear a fraction of a second after your view appears, but all the borders will be correct.
If anyone can post code that works for a right-edge border, that runs in the viewDidLoad, please post it and I'll mark it correct.

Resources