Swift: Round UIButton with Blur background - swift

I am wanting to make a round UIButton but with a light blur effect with vibrancy as it's background
So far I've got a rounded UIButton, but the code I have found online (I'm new to iOS development so don't really understand how the blur etc works) to add a blur just puts it as the entire button's frame, essentially making the button appear square again.
I've also tried adding a view, then the UIButton and then the blur effect and applied the cornerRadius code to that view but it also didn't work.
Here is what I've tried:
shortcutButton.layer.cornerRadius = 0.5 * shortcutButton.bounds.size.width // add the round corners in proportion to the button size
let blur = UIVisualEffectView(effect: UIBlurEffect(style:
UIBlurEffectStyle.Light))
blur.frame = shortcutButton.bounds
blur.userInteractionEnabled = false //This allows touches to forward to the button.
shortcutButton.insertSubview(blur, atIndex: 0)

Add the following two lines of code to your project, before you add the subview:
blur.layer.cornerRadius = 0.5 * shortcutButton.bounds.size.width
blur.clipsToBounds = true
Enjoy! :)

Related

How to add red dot badge in table view cell?

Try to add red dot badge for every unread data in inbox tableviewcell.
I try using cell.accessoryview to add badge
let size: CGFloat = 9
let width = max(size, 0.7 * size * 1) // perfect circle is smallest allowed
let badge = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: size))
badge.layer.cornerRadius = size / 2
badge.layer.masksToBounds = true
badge.textAlignment = .center
badge.textColor = UIColor.white
badge.backgroundColor = UIColor.red
if viewModel.sortedInboxItems[indexPath.section].isRead {
cell.accessoryView = badge
}
But if using cell.accessoryview it will change the display like image below (TIME in the right corner of the cell is moving forward). How to make it not change the display?
EDIT
Try to create dot as uilabel in custom uitableview cell like image below
But the result show like this image below. The red dot shape is not good enough? Can someone help with this issue ?
The accessoryView is not part of the contentView of the cell. If you set the accessoryView it will push the contentView over to make room for itself. More information on that can be found here; this diagram is helpful:
If you don't want it to do this, put your red dot into the cell itself instead of using the accessoryView. It's unclear how you've built your cells, but it looks like you've created a custom UITableViewCell, so you should be able to do this without trouble.
Or as commented above, you could include your time label in your accessory view alongside the red dot if applicable.
Consider using a UIView with corner radius just like you did with the label. To make sure that the shape is right (sizes have initialised properly) change its corner radius in an overriden layoutSubviews.
override func layoutSubviews() {
super.layoutSubviews()
badgeInboxView.layer.cornerRadius = badgeInboxView.frame.height/2
}

Changing Label/Button Text colour dynamically based on the dynamically changing background

I know it may sound a little bit of a drag to ask this question but I am curious if anything like this is available.
I am building a app in which the background image (covers full view with a blur effect) of each view controller changes dynamically. This background image will be in all the view controllers, each one having a different set of UIControls (Labels, Buttons, Table Views, Collection Views, containers, tabs, etc).
Sometimes when the background image is very light, the foreground texts (labels, buttons) with white text colour are not visible at all. Also the vice versa is a problem too.
So I would like to know if there is any way to change the foreground text colour dynamically based on its background.
Recently I faced the same problem, And I think what you looking for is either image is bright or dark so that you can set property accordingly Hope this will help.
Create observer, everytime image change it will check if its a dark image or bright and based on that will call the function UIForDarkImage and UIForBrightImage
//ImageView observer to observe the image change and perform the UI action based on the image colour
//Your imageView you are using to set image
var imageView: UIImageView {
didSet {
if imageView.isDark(image.bounds) { //dont pass the full image bounds pass the rect where your buttons or label places it will save your hell lot of time
setUIForDarkImage() // here you set buttons and labels color to white or whatever changes you want to perform based dark image
}
else {
setUIForBrightImage() // here you set buttons and labels color to black or whatever changes you want to perform based bright image
}
}
}
UIImageViewExtension for checking if Image is a dark image or bright Image.
What happening is, It will go through image pixel-by-pixel and check if the pixel is bright or dark and if we get dark pixels more than the threshold we have set, we will assuming that its a dark image else it's a bright image.
PS: For better efficiency not checking the whole image (for a high-resolution image it will slow down if we will check all pixels) so only checking the part of the image in which we need our button or label, you can set rect based on your requirement. And also scaling by 0.45 to check few pixels in that rect(you can increase or decrease for more/less accuracy).
extension UIImageView {
func isDark(_ rect:CGRect)->Bool {
let s=image?.cgImage?.cropping(to: rect);
let data=s?.dataProvider?.data;
if data == nil {return false;}
guard let ptr = CFDataGetBytePtr(data) else {return false;}
let threshold = Int(Double(rect.width * rect.height) * 0.45);
var dark = 0,len=CFDataGetLength(data);
for i in stride(from: 0, to: len, by: 4) {
let r = ptr[i], g = ptr[i+1], b = ptr[i+2];
if (0.299 * Double(r) + 0.587 * Double(g) + 0.114 * Double(b)) < 100 {dark += 1;}
if dark > threshold {return true;}
}
return false;
}
}
PS: If you also like to know what I am doing in setUIForBrightImage() and setUIForDarkImage do let me know
Here's what I would do: Create a struct that contains the name of the image view and a tint color to use for your labels, buttons, etc.
Add a property to your view controllers using this new struct. Let's call it backgroundImageSettings.
Add a didSet method to the property that calls another method useBackgroundImageSettings() that installs the image into the background of the view controller's content view, sets the tint color for the view controller's content view, and calls setNeedsDisplay() on the content view.. Also call useBackgroundImageSettings() in your viewDidLoad so that setting your backgroundImageSettings still works even if you view controller's view hasn't been loaded yet.
I like Duncan's answer! An additional step you can take is to set a slight overlay onto your background image.
For example, if you have a background image with really dark colors and you can't see your black text very well, then you can add a layer with a background color of white and an opacity less than 1. That way there's a bit of white to make your text more readable, and you can still see the background image.
let overlay = UIView(frame: yourSuperView.bounds)
overlay.backgroundColor = UIColor.white
overlay.layer.opacity = 0.5
yourSuperView.addSubview(overlay)

How to obtain a screen flash effect like screen capture effect?

Is there any way to obtain a flash screen effect like the one produced when a screenshot is taken, on demand, for a certain NSView? My question is not a duplicate of flashing screen programatically with Swift (on 'screenshot taken') , since I need a solution for osx, not ios and the methods are different.
Something like this might work
func showScreenshotEffect() {
let snapshotView = UIView()
snapshotView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(snapshotView)
// Activate full screen constraints
let constraints:[NSLayoutConstraint] = [
snapshotView.topAnchor.constraint(equalTo: view.topAnchor),
snapshotView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
snapshotView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
snapshotView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
]
NSLayoutConstraint.activate(constraints)
// White because it's the brightest color
snapshotView.backgroundColor = UIColor.white
// Animate the alpha to 0 to simulate flash
UIView.animate(withDuration: 0.2, animations: {
snapshotView.alpha = 0
}) { _ in
// Once animation completed, remove it from view.
snapshotView.removeFromSuperview()
}
}
The way to achieve this is to create a new UIView that is the same size of the screen, and black in color, add it a subview of your view then animate the alpha to zero( play around with the duration to achieve the desired effect) after completion remove the view from superview.
I have used this technique in many of my projects and it works like a charm. You can play around with the background color of the view to customize the look of the flash.

Rounded Rect UIButton with outer border

i wants to make outer border for UIButton.
When i click on button add border width, not inside rounded button - outside of this button.
P.S. i use this code to make button round:
button.layer.cornerRadius = 0.5 * button.frame.size.width
button.clipsToBounds = true
And this for border:
self.button.layer.borderWidth = CGFloat(10)
Now i have this result:
But i need border outside of the button. if someone help me, it's will be amazing, thanx.
Just add alpha (transparency) and instead of adding the border, change its alpha value. set the border color as follow:
let borderColor = UIColor(red: 0.0/256.0, green: 0.0/256.0, blue: 0.0/256.0, alpha: 0.0)
and modify the alpha value. This way it will look like you are adding the frame on the outside of the button.
Now, you didn't specify if you wanted the animation as well. If you do want the animation, you should just draw the frame outside the button's boundary, it might be trickier to do, and the frame would not have the button's functionality.
Another option of keeping the button and the animation is to draw a circle with behind the button and set the border to transparent, then animate.
These are only three of your options, I'm sure there are more...

How to apply borders and corner radius to UIBarButtonItem?

I have programatically created a toolbar to which I have added a UIBarButtonItem.
This is what is currently looks like:
I want the the button to have a border and a corner radius(curved corners).
How will the same be implemented?
UIBarButtonItem Implementation code:
let okBarBtn = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: "donePressed:")
If you can find the UIView associated with the UIBarButtonItem, you can modify the UIView.layer. But, finding the UIView is not made easy. I used the technique from Figure out UIBarButtonItem frame in window? . Starting with the navigationController.navigationBar, which itself is a UIView, I recursed through the subviews, one of which will be the button I wanted. Which one? Pick your own criteria! Here's my code:
func recurseViews(view:UIView) {
print("recurseViews: \(view)") // helpful for sorting out which view is which
if view.frame.origin.x > 700 { // find _my_ button
view.layer.cornerRadius = 5
view.layer.borderColor = UIColor.redColor().CGColor
view.layer.borderWidth = 2
}
for v in view.subviews { recurseViews(v) }
}
then in viewDidAppear (or similar)
recurseViews((navigationController?.navigationBar)!)
which is a bit of a hack but does the job:
There's no built-in automatic way to do this, unfortunately. You have two choices:
You could make this a bar button item with a custom view, make that view a UIButton, and then do the usual stuff to that UIButton (which you can do because it's a view), by way of its layer (give it a border and corner radius).
You could just draw (in code) a background image with a curved border and use that as the bar button item's image.
I do it with a storyboard. Just add UIButton inside UiBarButtonItem. Like here
And after that added a border to the UIButton