ios swift create rounded profile image like twitter, instagram, - ios

I would like to create a very simple image editor, same as twitter (for the profile image)
I know how to pinch or move an image.
But i don’t know how to create the "circle layer" and just keep this part of the image, like this :

Make sure to import QuarzCore.
func maskRoundedImage(image: UIImage, radius: CGFloat) -> UIImage {
let imgView: UIImageView = UIImageView(image: image)
let layer = imgView.layer
layer.masksToBounds = true
layer.cornerRadius = radius
UIGraphicsBeginImageContext(imgView.bounds.size)
layer.render(in: UIGraphicsGetCurrentContext()!)
let roundedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return roundedImage!
}
https://github.com/andreaantonioni/AAPhotoCircleCrop

Each view has an underlying layer onto which you apply a corner radius. Then you must apply clipToBounds on that layer in order to apply that mask to the overlying UIView. The corner radius must be half the width of the view in order to get a circle effect. Otherwise the corners of the view will be rounded.
For example:
let square = UIView()
square.center = view.center
square.bounds.size = CGSize(width: 100, height: 100)
square.backgroundColor = .red
view.addSubview(square)
square.layer.cornerRadius = 50
square.clipsToBounds = true

Above mentioned ways are good, But you can not achieved exact output as in above image E.g You can not get alpha effect.
I suggest simple way to do it.
1) Add new image to project with transparent background with Opocity and circle.
2) Add new imageView above to mainview as below.
let image = UIImageView(frame: view.bounds)
mage.image = UIImage.init(named:"imageName")
view.addSubview(image)
Then output should be as per your requirement.

Related

Achieve exact control of scale and offset of UIImage in UIImageView

I currently have a UIImageView with an image loaded inside with the contentMode being set to scaleAspectFill. Is there a way to specify an exact section of the image to show instead of the default center, or am I approaching this the wrong way?
Swift Code:
basketballImage = UIImageView()
basketballImage.contentMode = .scaleAspectFill
basketballImage.clipsToBounds = true
basketballImage.image = UIImage(named: "Basketball")
Original Image
Desired Result
Failed Example 1: With contentMode = .scaleAspectFill
Failed Example 2: With contentMode = .top
There's no way for iOS to know what you really want since your scaling is arbitrary.
You can effectively crop (zoom-in) by setting the contentScaleFactor property. Aspect-fit is unrelated to your goal.
Now, the arbitrary vertical offset requires an affine transform, but only works with a container UIView to maintain the layout. You have to transform the entire UIImageView frame within its parent (unless you want to get very fancy and override the draw method or re-implement UIImageView with an affine-transform hook).
I achieved roughly what you want by installing that image at 2x resolution and using:
override func viewDidLoad() {
super.viewDidLoad()
let offset: CGFloat = 120.0
let scale: CGFloat = 3.0
/* imageView is a *child* of imageContainer and constrained to be exactly the same size and position */
imageContainer.clipsToBounds = true
imageView.image = UIImage(named: "basketball")
imageView.contentMode = .center
imageView.contentScaleFactor = scale
imageView.transform = CGAffineTransform(translationX: 0, y: offset)
}
It's harder than I'd like, what with another layer of nesting, but UIImageView is just not that sophisticated.

How to set half-round UIImage in Swift like this screenshot

https://www.dropbox.com/s/wlizis5zybsvnfz/File%202017-04-04%2C%201%2052%2024%20PM.jpeg?dl=0
Hello all Swifters,
Could anyone tell me how to set this kind of UI? Is there any half rounded image that they have set?
Or there are two images. One with the mountains in the background and anohter image made half rounded in white background and placed in on top?
Please advise
Draw an ellipse shape using UIBezier path.
Draw a rectangle path exactly similar to imageView which holds your image.
Transform the ellipse path with CGAffineTransform so that it will be in the center of the rect path.
Translate rect path with CGAffineTransform by 0.5 to create intersection between ellipse and the rect.
Mask the image using CAShapeLayer.
Additional: As Rob Mayoff stated in comments you'll probably need to calculate the mask size in viewDidLayoutSubviews. Don't forget to play with it, test different cases (different screen sizes, orientations) and adjust the implementation based on your needs.
Try the following code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
guard let image = imageView.image else {
return
}
let size = image.size
imageView.clipsToBounds = true
imageView.image = image
let curveRadius = size.width * 0.010 // Adjust curve of the image view here
let invertedRadius = 1.0 / curveRadius
let rect = CGRect(x: 0,
y: -40,
width: imageView.bounds.width + size.width * 2 * invertedRadius,
height: imageView.bounds.height)
let ellipsePath = UIBezierPath(ovalIn: rect)
let transform = CGAffineTransform(translationX: -size.width * invertedRadius, y: 0)
ellipsePath.apply(transform)
let rectanglePath = UIBezierPath(rect: imageView.bounds)
rectanglePath.apply(CGAffineTransform(translationX: 0, y: -size.height * 0.5))
ellipsePath.append(rectanglePath)
let maskShapeLayer = CAShapeLayer()
maskShapeLayer.frame = imageView.bounds
maskShapeLayer.path = ellipsePath.cgPath
imageView.layer.mask = maskShapeLayer
}
}
Result:
You can find an answer here:
https://stackoverflow.com/a/34983655/5479510
But generally, I wouldn't recommend using a white image overlay as it may appear distorted or pixelated on different devices. Using a masking UIView would do just great.
Why you could not just create (draw) rounded transparent image and add UIImageView() with UIImage() at the top of the view with required height and below this view add other views. I this this is the easiest way. I would write comment but I cant.

Drawing multiple UIImageViews with the same UIImage

I am trying to draw a line using multiple UIImageView of the same circle image.
I have tried the following:
let imageName = "circle.jpg"
let image = UIImage(named: imageName)
for var i in 0..<100 {
i += 1
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: i, y: 200, width: 25, height: 25)
view.addSubview(imageView)
}
This produces one circle at the position (100, 200). This happens because the same UIImageView is being added to the subview so it is only updating the position rather than adding a new UIImageView. If I create a new UIImageView named "imageView1" and add it to the subview, it will create a new circle.
For the purpose of forming a line by overlapping the UIImageViews of these circles, manually creating a UIImageView for each circle is obviously inefficient.
So, how can I use the same UIImage to draw multiple UIImageViews?
Any other suggestions on how I can get around accomplishing this?
You need a circle to form a line like this
Well here the code I used for this using While loop
let imageName = "synergy-many-people-turning-in-gears_gg55375354.jpg"
let image = UIImage(named: imageName)
var i = 0
while(i<100)
{
let imageView = UIImageView(image: image!)
imageView.frame = CGRect(x: i, y: 200, width: 25, height: 25)
view.addSubview(imageView)
i = i + 25//Here I set it to the width so that the images don't overlap
//you can use any value for the desired effect it just sets the location
//of X-Co-ordinate where the next image would be added
}
I would quickly try out something like this (didn't test it though):
var imageView = UIImageView(image: image!)
Creating multiple UIImageViews is the thing you need to do. If this will be to slow (btw you should place your image inside assets catalogue to allow caching and improve performance), you should switch to lower level api. Check iOS - An easy way to draw a circle using CAShapeLayer
And, btw, why do you change i variable inside loop, this is very bad practice

How can I change the color of the UITabBar top border by creating a UIImage programmatically?

From my understanding, the only way to change the color of the top border is to set the background image (320x49, with pixel line at top). It seems to me that this is the only way (please correct me if I'm wrong).
Is there a way to do this without using an image file? For example, someone helped me change the NavigationBar bottom border by creating a UIImage from code:
UINavigationBar.appearance().shadowImage = UIImage.colorForNavBar(UIColor.redColor())
extension UIImage {
class func colorForNavBar(color: UIColor) -> UIImage {
let rect = CGRectMake(0.0, 0.0, 1.0, 1.0)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
This solution actually works well; it changes the color of my bottom border.
I tried to apply this to the TabBar, but nothing changes at all.
UITabBar.appearance().shadowImage = UIImage.colorForNavBar(.redColor())
You've pretty much answered your own question. You can do the same thing with your UITabBar as you did with your UINavigationBar. If you want to change the shadow image (i.e. the "top border"), then you have to change the background image. Straight from Apple:
The custom shadow image for the tab bar. This attribute is ignored if the tab bar does not also have a custom background image. To set this attribute programmatically, use the shadowImage property.
In your own question you seem to be aware of this:
the only way to change the color of the top border is to set the background image (320x49, with pixel line at top)
Except that it's not the background image that has a line at the top. You just have to set the background image to anything, then you can set the shadow image to your preference.
If you open up the simple "tabbed application" template within Xcode, you'll find that adding these two lines of code (and your UIImage extension code) indeed work:
// White background with red border on top
UITabBar.appearance().backgroundImage = UIImage.colorForNavBar(.whiteColor())
UITabBar.appearance().shadowImage = UIImage.colorForNavBar(.redColor())
Here is the Swift 3 solution:
extension UIImage {
class func colorForNavBar(color: UIColor) -> UIImage {
let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0)
// Or if you need a thinner border :
// let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 0.5)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(color.cgColor)
context!.fill(rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}
used with the code above in the viewDidLoad of the UITabBarController
UITabBar.appearance().backgroundImage = UIImage.colorForNavBar(color: .white)
UITabBar.appearance().shadowImage = UIImage.colorForNavBar(color: .red)
You need to provide an different image for UINavigationBar.appearance().backgroundImage.
For example:
UINavigationBar.appearance().backgroundImage = UIImage.colorForNavBar(.blackColor())
UINavigationBar.appearance().shadowImage = UIImage.colorForNavBar(.redColor())
Normally, the other answers got it right - you have to set both a background image and a shadow image. However, doing so will cause the bar to drop its translucency (blur); even if you set a transparent image, the bar will be transparent, not translucent.
We also had a similar need, but we wanted to preserve the translucency of the bar. Instead of setting a shadow image, we subclassed the bar, and put a hairline subview with a color we want. When the bar lays out its subviews, we set the frame of the hairline to be the width of the bar, and a pixel exactly.
See my GitHub demo project.
Here is a screenshot of the result:
After you include my subview in your project, just use the following line to set the color:
if let tabBar = tabBarController?.tabBar as? ColoredHairlineTabBar {
tabBar.hairlineColor = ... //Your color
}
What about simply subclassing UITabBar and adding a new sublayer to the view in layoutSubviews.
Swift example:
override func layoutSubviews() {
super.layoutSubviews()
let topBorder = CALayer()
let borderHeight: CGFloat = 2
topBorder.borderWidth = borderHeight
topBorder.borderColor = UIColor.redColor().CGColor
topBorder.frame = CGRect(x: 0, y: -1, width: self.frame.width, height: borderHeight)
self.layer.addSublayer(topBorder)
}
You don't need an extension to create an image of a certain size, UIImage has a perfectly good constructor for that.
To prevent losing the translucent blur, you can set the bar tint color instead of a background image. You can also use the screen scale to make sure the border is one pixel, like the original border was:
let hairlineHeight = CGFloat(1) / UIScreen.main.scale
tabBar.barTintColor = .white
tabBar.shadowImage = UIImage(color: .black, size: CGSize(width: 1, height: hairlineHeight))

How can UIVisualEffectView be used inside of a circle?

I'm making a custom control circle. Part of the circle may be transparent. It would make more visual sense and look better if it was translucent instead of transparent.
Because views are rectangular, and I only want the circle to be translucent, not the rest of the rectangle, this is a problem.
The UIVisualEffectView is behind the custom control.
(Without anything rendered inside of the circle for debugging purposes)
As you can see, the view is blurring things outside of the circle.
I don't know how to blur inside only the view, and the prerelease documentation is practically empty. My only thought is to create many 1x1 views to cover the circle, but this seems like it would not really work, and even if it did it would be a slow and ugly solution. How can I blur the content inside the view, without blurring anything outside it?
Set the circle view's layer mask to a filled circle:
CircleControlView *circleView = yourCircleView();
CAShapeLayer *mask = [CAShapeLayer layer];
mask.path = [UIBezierPath bezierPathWithOvalInRect:circleView.bounds].CGPath;
circleView.layer.mask = mask;
UPDATE
Swift playground example:
import UIKit
import XCPlayground
import QuartzCore
UIGraphicsBeginImageContext(CGSize(width: 100, height: 100))
let viewPath = UIBezierPath(ovalInRect:CGRect(x:1,y:1,width:98,height:98))
viewPath.lineWidth = 2
viewPath.stroke()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let view = UIView(frame:CGRect(x:0,y:0,width:100,height:100))
XCPShowView("view", view)
let label = UILabel(frame:view.bounds)
label.text = "This is the text in the background behind the circle."
label.numberOfLines = 0
view.addSubview(label)
let effectView = UIVisualEffectView(effect:UIBlurEffect(style:.ExtraLight))
effectView.frame = view.bounds
view.addSubview(effectView)
let circleView = UIImageView(image:image)
effectView.addSubview(circleView)
let maskPath = UIBezierPath(ovalInRect:circleView.bounds)
let mask = CAShapeLayer()
mask.path = maskPath.CGPath
effectView.layer.mask = mask
Result:

Resources