Make circular photos downloaded from google (google places, swift) - ios

I'm working with google places and i have a VC with a tableView where i downloaded nearby places from the user position and in each cell of the tableView i add the information of the place and the photo of it. I created a custom class to make the photo circular
import UIKit
#IBDesignable
class RoundImage: UIImageView {
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
self.layer.cornerRadius = cornerRadius
}
}
#IBInspectable var borderWidth: CGFloat = 0 {
didSet {
self.layer.borderWidth = borderWidth
}
}
#IBInspectable var borderColor: UIColor = UIColor.clear {
didSet {
self.layer.borderColor = borderColor.cgColor
}
}
}
but the problem is that i download the photos of the places with this class
import UIKit
private let widthKey = "width"
private let heightKey = "height"
private let photoReferenceKey = "photo_reference"
class QPhoto: NSObject {
var width: Int?
var height: Int?
var photoRef: String?
init(photoInfo: [String:Any]) {
height = photoInfo[heightKey] as? Int
width = photoInfo[widthKey] as? Int
photoRef = photoInfo[photoReferenceKey] as? String
}
func getPhotoURL(maxWidth:Int) -> URL? {
if let ref = self.photoRef {
return NearbyPlaces.googlePhotoURL(photoReference: ref, maxWidth: maxWidth)
}
return nil
}
}
and i would like to know how can i adjust it, because with this class the photos that i download even though i put the RoundImage class at the imageview in the storyboard are always square

You need to set clipsToBounds to true. You can do that when you set the cornerRadius:
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
self.layer.cornerRadius = cornerRadius
self.clipsToBounds = true
}
}

Related

Kingfisher load image from url and set corner radius

I layout imageView with SnapKit and load image from url by Kingfisher, I also want to set corner radius by Kingfisher (use RoundCornerImageProcessor), if I set targetSize, picture is distorted, if not set, just corner radius, i can't get the results I want.
What should I do?
You can set image easily like this for kingFisher:
import UIKit
import Kingfisher
class ViewController: UIViewController {
#IBOutlet weak var image:UIImageView!
let rawstring = "https://apis.baytelhekma.com/zinzo/public/storage/products/November2020/eUWwRjNCYCdHUjGIQiJk.png"
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: rawstring)
image.kf.setImage(with: url)
}
}
Then you can make corner radius by adding this to your project:
import Foundation
import UIKit
extension UIView {
#IBInspectable
var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
#IBInspectable
var borderWidth: CGFloat {
get {
return layer.borderWidth
}
set {
layer.borderWidth = newValue
}
}
#IBInspectable
var borderColor: UIColor? {
get {
let color = UIColor(cgColor: layer.borderColor!)
return color
}
set {
layer.borderColor = newValue?.cgColor
}
}
}
after that all you need to do is this in your ViewController:
image.cornerRadius = 15 // you can set it with the number fits your app

how to set gradient layer width to be the same as button width?

I am new in iOS Development, I want to make gradient rounded button by using this designable class
#IBDesignable
class GradientButton: UIButton {
let gradientLayer = CAGradientLayer()
#IBInspectable
var topGradientColor: UIColor? {
didSet {
setGradient(topGradientColor: topGradientColor, bottomGradientColor: bottomGradientColor)
}
}
#IBInspectable
var bottomGradientColor: UIColor? {
didSet {
setGradient(topGradientColor: topGradientColor, bottomGradientColor: bottomGradientColor)
}
}
override func layoutSubviews() {
super.layoutSubviews()
updateCornerRadius()
}
#IBInspectable var fullRounded: Bool = false {
didSet {
updateCornerRadius()
}
}
#IBInspectable var cornerRadiusOfButton : CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadiusOfButton
}
}
func updateCornerRadius() {
layer.cornerRadius = fullRounded ? (frame.size.height / 2) : cornerRadiusOfButton
}
#IBInspectable var borderWidth: CGFloat {
set {
layer.borderWidth = newValue
}
get {
return layer.borderWidth
}
}
#IBInspectable var borderColor: UIColor? {
set {
guard let uiColor = newValue else { return }
layer.borderColor = uiColor.cgColor
}
get {
guard let color = layer.borderColor else { return nil }
return UIColor(cgColor: color)
}
}
private func setGradient(topGradientColor: UIColor?, bottomGradientColor: UIColor?) {
if let topGradientColor = topGradientColor, let bottomGradientColor = bottomGradientColor {
gradientLayer.frame = bounds
gradientLayer.colors = [topGradientColor.cgColor, bottomGradientColor.cgColor]
gradientLayer.borderColor = layer.borderColor
gradientLayer.borderWidth = layer.borderWidth
gradientLayer.cornerRadius = layer.cornerRadius
layer.insertSublayer(gradientLayer, at: 0)
} else {
gradientLayer.removeFromSuperlayer()
}
}
}
but here is the result:
as you can see the width of the gradient layer button is incorret.
here is the constraint layout I use:
I want that gradient layer to have the same width as the original button, I suspect that the problem is in this line
gradientLayer.frame = bounds
but unfortunately I don't know how to set the gradient layer width to be the same size as the original button programmatically in #IBDesignable class
could you please help me to solve this issue ? thanks in advance
Override layoutSubviews inside GradientButton and update the gradientLayer frame as,
override func layoutSubviews() {
super.layoutSubviews()
self.gradientLayer.frame = bounds
}

How to make different drawed views out of one UIView Class?

im making a iOS app/game that is like the game "Set".
for that I need to make multiple views so I made this class:
class CardSubview: UIView {
private let partsOfSpace:CGFloat = 12
private let occurenceOfForms: CGFloat = 3
private let color1:UIColor = someColor1
private let color2:UIColor = someColor2
private let color3:UIColor = somecolor3
private let attributeIdentifiers = [1,2,3]
private var openCardUp = false
public var isSelceted = false {
didSet {
if isSelceted == true {
self.backgroundColor = #colorLiteral(red: 0.5791940689, green: 0.1280144453, blue: 0.5726861358, alpha: 0.52734375)
self.layer.borderWidth = 5.0
self.layer.borderColor = #colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1)
}
else {
self.backgroundColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1)
self.layer.cornerRadius = 0
self.layer.borderWidth = 0
}
}
}
public func makePath() {
openCardUp = true
let path = coloreAndFill(path: self.occurenceOfForm(form: **index1**, occurence: **index2**, viewWidth: self.bounds.width, viewHeigth: self.bounds.height), chosenColor:**index3**, fillIdentifier: **index4**)
path.stroke()
}
override func draw(_ rect: CGRect) {
if openCardUp == true {
makePath()
}
}
....
so all you need to know that this makes an View with an rectangle or triangle or circle etc etc...
now I want to put 80 different of them into the CardBoardView
this is my CardBoardView
import UIKit
#IBDesignable
class CardBoardView: UIView {
static var index1 = 1
static var index2 = 1
static var index3 = 1
static var index4 = 3
public var cells = 12
let values = Values()
var card: CardSubview = CardSubview() {
didSet {
let tabRecognizer = UITapGestureRecognizer(target: self, action: #selector(tab))
card.addGestureRecognizer(tabRecognizer)
}
}
struct Values {
public let ratio:CGFloat = 2.0
public let insetByX:CGFloat = 3.0
public let insetByY:CGFloat = 3.0
public let allAvailableCards = 81
}
#objc private func tab (recognizer: UITapGestureRecognizer) {
switch recognizer.state {
case .ended:
card.isSelceted = !card.isSelceted
default: break
}
}
override func layoutSubviews() {
super.layoutSubviews()
var grid = Grid(layout: .aspectRatio(values.ratio), frame: self.bounds)
grid.cellCount = 12
for index in 0..<12 {
card = CardSubview(frame: grid[index]!.insetBy(dx: values.insetByX, dy: values.insetByY))
card.makePath()
addSubview(card)
}
}
}
so if I change one of the static indexes the drawing in the CardSubview will change.
thats my idea but it doesn't work because every time I change the index every card will get changed and draws the new form not only one.
how would you do that can anybody give me some thoughts to my code and some tipps?
There's no need for your card property in CardBoardView. You are creating a whole set of CardSubview instances so it makes no sense to have a property that only stores the last one.
You need to make several changes to your code.
Completely remove your card property and its didSet block.
Put the creation of the tap gesture in the loop that creates each CardSubview instance.
Use a local variable in the loop.
Update the tab method to get the card view from the gesture recognizer.
Here's the updated code:
class CardBoardView: UIView {
static var index1 = 1
static var index2 = 1
static var index3 = 1
static var index4 = 3
public var cells = 12
let values = Values()
struct Values {
public let ratio:CGFloat = 2.0
public let insetByX:CGFloat = 3.0
public let insetByY:CGFloat = 3.0
public let allAvailableCards = 81
}
#objc private func tab (recognizer: UITapGestureRecognizer) {
if recognizer.state == .ended {
if let card = recognizer.view as? CardBoardView {
card.isSelected = !card.isSelected
}
}
}
override func layoutSubviews() {
super.layoutSubviews()
var grid = Grid(layout: .aspectRatio(values.ratio), frame: self.bounds)
grid.cellCount = 12
for index in 0..<12 {
let card = CardSubview(frame: grid[index]!.insetBy(dx: values.insetByX, dy: values.insetByY))
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(tab))
card.addGestureRecognizer(tapRecognizer)
card.makePath()
addSubview(card)
}
}
}
It's possible that you may need to access each of the CardBoardView instances through some other code you haven't posted. So you may need a property to store all of the cards.
var cards = [CardBoardView]()
Then in the loop that creates each card, add:
cards.append(card)

ios- UIButton not work in the custom view(UIViewX)

I am searching for a long time on net. But no use. Please help or try to give some ideas how to achieve this.
create a UIViewX in the View Controller or
add UIButton on custom view(UIViewX). And IBAction is print(" test ")
Everything work good.
But...
When add UIButton on custom view(UIViewX) and add animation code with UIViewX, button does't work if I press it
how to fix it that can response print(" test ")?
Thanks in advance.
Here is animation code :
var currentColorArrayIndex = -1
var colorArray:[(color1: UIColor, color2: UIColor)] = []
override func viewDidLoad() {
super.viewDidLoad()
colorArrayFunction()
backgroundAnimate()
}
colorArrayFunction & backgroundAnimate
Here is UIViewX code :
import UIKit
#IBDesignable
class UIViewXXXXX: UIView {
// MARK: - Gradient
#IBInspectable var firstColor: UIColor = UIColor.white {
didSet {
updateView()}}
#IBInspectable var secondColor: UIColor = UIColor.white {
didSet {
updateView()}}
#IBInspectable var horizontalGradient: Bool = false {
didSet {
updateView()}}
override class var layerClass: AnyClass {
get {
return CAGradientLayer.self}}
func updateView() {
let layer = self.layer as! CAGradientLayer
layer.colors = [ firstColor.cgColor, secondColor.cgColor ]
if (horizontalGradient) {
layer.startPoint = CGPoint(x: 0.0, y: 0.5)
layer.endPoint = CGPoint(x: 1.0, y: 0.5)
} else {
layer.startPoint = CGPoint(x: 0, y: 0)
layer.endPoint = CGPoint(x: 0, y: 1)
}}
// MARK: - Border
#IBInspectable public var borderColor: UIColor = UIColor.clear {
didSet {
layer.borderColor = borderColor.cgColor}}
#IBInspectable public var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth}}
#IBInspectable public var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
// MARK: - Shadow
#IBInspectable public var shadowOpacity: CGFloat = 0 {
didSet {
layer.shadowOpacity = Float(shadowOpacity)}}
#IBInspectable public var shadowColor: UIColor = UIColor.clear {
didSet {
layer.shadowColor = shadowColor.cgColor}}
#IBInspectable public var shadowRadius: CGFloat = 0 {
didSet {
layer.shadowRadius = shadowRadius}}
#IBInspectable public var shadowOffsetY: CGFloat = 0 {
didSet {
layer.shadowOffset.height = shadowOffsetY}}}

ImageView doesn't change to rounded shape

My goal is to make my the ImageView rounded and I already created a custom IBDesignable class
Code
import UIKit
#IBDesignable class MyImageView: UIImageView {
#IBInspectable var borderColor: UIColor = UIColor.clear {
didSet {
layer.borderColor = borderColor.cgColor
}
}
#IBInspectable var borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
}
}
}
Everything works fine already, but why is the image didn't change to rounded?
Result:
Set the clipToBounds property of UIImageView to true.
#IBInspectable var cornerRadius: CGFloat = 0 {
didSet {
layer.cornerRadius = cornerRadius
self.clipsToBounds = true
}
}

Resources