Trying to put a badge on an UIImageView - swift

I built a UIImageView extension to use the image in it and add a badge to it. But i really cannot get it right because after that i'm rounding the UIImageView corners radius. What i want is to show the badge on top of the UIImageView corner of the image.
This is how i do it:
public extension UIImageView {
func addBadgeRightBottom (withBadge badge: UIImage) {
if self.image != nil {
UIGraphicsBeginImageContextWithOptions(self.frame.size, false, 0.0)
self.image?.draw(in: CGRect(x: 0, y: 0, width: (self.frame.size.width), height: (self.frame.size.height)))
badge.draw(in: CGRect(x: (self.frame.size.width) - badge.size.width, y: (self.frame.size.height) - badge.size.height, width: badge.size.width, height: badge.size.height))
let image = UIGraphicsGetImageFromCurrentImageContext()
DispatchQueue.main.async() { () -> Void in
self.image = image
}
UIGraphicsEndImageContext()
}
}
}
This is what i'm getting:
What i really want to have:

At last i did it by creating a new UIImageView of the badge UIImage size in the same position i wanted on the other circular UIImageView and added it as a subview to my UICollectionViewCell because these profile picture images are in a UICollectionViewCell
Unfortunately i didn't do it as an extension after all.
Here is how i did it.
After initializing a UIImageView in the CelebCollectionViewCell class
var celebBadgeImageView = UIImageView()
I initialized the CGRect of the badge and added it as a subview
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: CelebCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "celebCell", for: indexPath) as! CelebCollectionViewCell
cell.celebBadgeImageView.frame = CGRect(x: cell.celebImage.frame.size.width - (#imageLiteral(resourceName: "verifiedCelebrity").size.width/2), y: cell.celebImage.frame.size.height - #imageLiteral(resourceName: "verifiedCelebrity").size.height, width: #imageLiteral(resourceName: "verifiedCelebrity").size.width, height: #imageLiteral(resourceName: "verifiedCelebrity").size.height)
cell.celebBadgeImageView.image = #imageLiteral(resourceName: "verifiedCelebrity")
cell.addSubview(cell.celebBadgeImageView)
cell.celebImage.image = #imageLiteral(resourceName: "profile_user.jpg")
cell.celebImage.circularView()
return cell
}

Related

Access CollectionView Cell Content (change width of inner view)

I want to have a uiview as cell background with changing width. This should be used as a progress-/ statusbar.
The problem:
I can’t change the width of the statusbar from my collectionViewController (only from the CollectionViewCellController)....
I manually set the width to 5 in layoutSubviews(). Then I changed it to 80 in setStatusBar(...) which I called in the other class. The width stays at 5 :(
Here is my code
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var myLabel: UILabel!
#IBOutlet weak var statusbar: UIView!
override func layoutSubviews() {
// cell rounded section
self.layer.cornerRadius = 15.0
self.layer.masksToBounds = true
super.layoutSubviews()
statusbar.frame = CGRect(x: 0, y: 0, width: 5, height: self.frame.height)
}
}
extension MyCollectionViewCell{
func setStatusbar(completedTasks: Int, totalTasks: Int){
print(self.frame.width)
let newWidth = 80 //(self.frame.width * (CGFloat(completedTasks / totalTasks)))
statusbar.backgroundColor = .orange
statusbar.frame = CGRect(x: 0, y: 0, width: newWidth, height: Int(self.frame.height))
reloadInputViews()
}
}
And this is where I call the function setStatusbar(...) - where I want to change the width, but DOESNT work:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MyCollectionViewCell
// Use the outlet in our custom class to get a reference to the UILabel in the cell
cell.myLabel.text = self.items[indexPath.row] // The row value is the same as the index of the desired text within the array.
cell.backgroundColor = UIColor(rgb: 0xF444444)
cell.setStatusbar(completedTasks: 5, totalTasks: 25) //!!! HERE !!!
return cell
}
Can someone help me find the problem why the statusbar uiview doesn’t change its with from 5 to 80?
Thank you!

Adding images to table view cell problem using stack views

in my prototype cell I have a horizontal stack view and I connected that to my UITableViewCell and I defined an update function In my UITableViewCell that adds multiple images to the stack view and I called the function In TableViewController cellForRowAt but nothing nothing happens.
//inside UITableViewCell
#IBOutlet weak var lineStack: UIStackView!
func update(_ imageName: String){
let numberOfCopies = Int(deviceWidth/50)
let startX = (Int(deviceWidth) - (numberOfCopies*50))/2
xValue = xValue + startX
let image = UIImage(named: imageName)
for _ in 1...Int(numberOfCopies) {
xValue = xValue + heightValue
let imageView = UIImageView(image: image)
imageView.frame = CGRect(x: xValue , y: 0, width: widthValue, height: heightValue)
lineStack.addSubview(imageView)
}
}
//inside TableViewController
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Line", for: indexPath) as! LineTableViewCell
let imageName = imagesName[indexPath.row]
cell.update(imageName)
return cell
}
Your post indicates you want your images to be 50 x 50 points... use auto-layout constraints with .addArrangedSubview():
class TestCell: UITableViewCell {
#IBOutlet var lineStack: UIStackView!
func update(_ imageName: String) {
let numberOfCopies = Int(deviceWidth/50)
let image = UIImage(named: imageName)
for _ in 1...Int(numberOfCopies) {
let imageView = UIImageView(image: image)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.widthAnchor.constraint(equalToConstant: 50).isActive = true
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor).isActive = true
lineStack.addArrangedSubview(imageView)
}
}
}
EDIT Sample result, with stack view centered horizontally:
Stack view is set to:
Axis: Horizontal
Alignment: Fill
Distribution: Fill
Spacing: 0
and this is the layout with constraints:
Note that the stack view has a Width constraint of 10, but its Priority is 250 ... that allows the stack view to stretch horizontally, while keeping IB satisfied with the constraints.
For the line:
lineStack.addSubview(imageView)
Instead of addSubview() you need to do it with addArrangedSubview(). The former is the regular way of adding a subview to a view, whereas the latter is specifically for UIStackView and tells the view to insert it properly.

UICollectionViewCell dashed border for dynamic cell width swift issue

Using UICollectionView under the UITableViewCell
Using below extension for creating dashed border:
extension UIView {
func addDashedLineView(frame: CGRect) {
let border = CAShapeLayer()
border.strokeColor = UIColor.blue.cgColor
border.lineDashPattern = [6, 6]
border.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)//self.frame
border.fillColor = UIColor.clear.cgColor
border.lineJoin = kCALineJoinRound
//print("widht: \(frame.width) fraheight: \(UIScreen.main.bounds.width)")
border.fillColor = nil
border.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: frame.width, height: frame.height), cornerRadius: 6).cgPath
self.clipsToBounds = true
self.layer.addSublayer(border)
}
}
Below is my collection view method where i am calling above method (actually the cell width depending upon the content size so i am calculating the text width) the issue is when the cell are dequeue from the list the border get redraw from different width, also i am using custom cell "CollectionViewCell" class:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: CollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
let width = self.collectionData[indexPath.row].width(withConstraintedHeight: 14, font: .systemFont(ofSize: 17)) + Constant.cellPadding
cell.contentView.addDashedLineView(frame: CGRect(x: 0, y: 0, width: width, height: Constant.itemHeight))
cell.contentView.setNeedsLayout()
cell.contentView.layoutIfNeeded()
cell.layoutIfNeeded()
return cell
}
When first load drawing border correctly when scroll the view it has been redraw
How to resolve the issue

UIScrollView in UICollectionViewCell with Swift

I'm new in IOS. I try to create view images app that show fullscreen size images can zoom and when user zoom out images smaller than fullscreen size, image return fullscreen size and my idea is use UICollectionView set paging Enable , scrollDirection Horizontal. So my FlowLayout will be like this
var screenSize: CGRect!
override func viewDidLoad() {
super.viewDidLoad()
screenSize = UIScreen.mainScreen().bounds
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: screenSize.width, height: screenSize.height)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.scrollDirection = UICollectionViewScrollDirection.Horizontal
self.collectionView!.collectionViewLayout = layout
self.view.addSubview(collectionView!)
my CollectionViewCell identifier name "Cell" I drag ScrollView in it and drag image in that ScrollView
I outlet that two item in my CollectionViewCell Class like this
import UIKit
class MyCollectionCell: UICollectionViewCell, UIScrollViewDelegate{
#IBOutlet weak var scrollCell: UIScrollView!
#IBOutlet weak var imgTest: UIImageView!
}
next step in CollectionViewController set my dummy image something like this
var imageName:[String] = ["audi.png", "benz.png", "flok.png", "audi.png", "benz.png", "flok.png", "audi.png", "benz.png", "flok.png"]
and go to cellForItemAtIndexPath
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! MyCollectionCell
cell.layer.borderWidth = 0
cell.frame.size.width = screenSize.width
cell.frame.size.height = screenSize.height
// set cell size become fullscreen
cell.imgTest.image = UIImage(named: imageName[indexPath.row])
cell.imgTest.frame = CGRect(origin: CGPoint(x: 0, y: 0), size:cell.imgTest.image!.size)
//call my dummy image to cell
cell.scrollCell.addSubview(cell.imgTest)
cell.scrollCell.contentSize = cell.imgTest.image!.size
let scaleHeight = cell.scrollCell.frame.size.height / cell.scrollCell.contentSize.height
let scaleWidth = cell.scrollCell.frame.size.width / cell.scrollCell.contentSize.width
let minScale = min(scaleWidth, scaleHeight)
cell.scrollCell.minimumZoomScale = minScale
cell.scrollCell.maximumZoomScale = 1.0
cell.scrollCell.zoomScale = minScale
var doubleTapRecognizer = UITapGestureRecognizer(target: self, action: "scrollviewDoubleTapped")
doubleTapRecognizer.numberOfTapsRequired = 2
doubleTapRecognizer.numberOfTapsRequired = 1
cell.scrollCell.addGestureRecognizer(doubleTapRecognizer)
I run this project and the problem is
scroll size don't equal my image size but over
my image can't zoom (I already check "user interaction enabled")
I try using pinch gesture to solve it but I don't know how to set minimumzoomscale to it and the images can't scroll when zoom in
By this code I try using image from json with SDWebImage I change code in cellForItemAtIndexPath from call dummy image to this
cell.imgTest.sd_setImageWithURL(NSURL(string: dataArray[indexPath.row]), placeholderImage: UIImage(named: "loading.png"))
but this way Thread 1 : EXC_BAD_INSTRUCTION (code=EXC_1386_INVOP,subcode=0x0)
Where I go from here can anyone guide me in swift please
instead of a collection view use a scrollview, much easier, and more flexible. Check out this link very good tutorial.. You can merge the scrolled page and scroll zoom. UIScrollView Tutorial: Getting Started

UICollectionView cell views overlapping

I have cells overlapping like so:
my cellForItemAtIndexPath is as such:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as UICollectionViewCell
cell.backgroundColor = UIColor(red: 27.0/255.0, green: 38.0/255.0, blue: 52.0/255.0, alpha: 1.0)
let textFrame = CGRect(x: 0, y: cell.frame.height * 0.30, width: cell.frame.width, height: cell.frame.height)
var textLabel: UILabel! = UILabel(frame: textFrame)
textLabel.font = UIFont(name:"Helvetica-Light", size: 14.0)
textLabel.textAlignment = .Center
textLabel.textColor = UIColor.whiteColor()
println(categoryArray[indexPath.row].category)
textLabel.text = categoryArray[indexPath.row].category
var cellImage = UIImage(named: categoryArray[indexPath.row].catImage)//Array(Array(model.categories.values)[cellCount])[1]
let imageSize = cell.frame.height * 0.45
let imageView = UIImageView(image: cellImage as UIImage?)
imageView.frame = CGRect(x: (cell.frame.width / 2) - (imageSize / 2), y:cell.frame.height * 0.15, width: imageSize, height: imageSize)
var bottomBorder: UIView = UIView(frame:CGRectMake(0, cell.frame.height - 1.0, cell.frame.width, 5));
//bottomBorder.backgroundColor = UIColor(rgba: Array(Array(model.categories.values)[cellCount])[0] as String)
bottomBorder.backgroundColor = UIColor(rgba: "#A64259")
cell.addSubview(imageView)
cell.addSubview(bottomBorder)
cell.addSubview(textLabel)
cellCount++
return cell
}
I understand that it reuses the cells, great idea...except how do I prevent the cell text from overlapping?
EDIT - POTENTIAL SOLUTION #1
Since these subviews were continually being modified I figured, what if I just dumped them and created new ones so I used:
for view in cell.subviews {
view.removeFromSuperview()
}
And that seemed to do the trick. I suspect this has a little more overhead than just modifying the values of the specific elements in the subviews. Will investigate further.
The reason it's happening is because the cells are being reused and you end up adding the image as a subview multiple times to the same UICollectionViewCell object. You can make a custom class that extends UICollectionViewCell so that you can hold onto the imageView that you add.
class ImageCell : UICollectionViewCell {
private(set) var imageView : UIImageView?
private(set) var textLabel : UILabel?
func setImage(image: UIImage?) {
if self.imageView == nil {
let imageSize = cell.frame.height * 0.45
self.imageView = UIImageView()
self.imageView.frame = CGRect(x: (self.frame.width / 2) - (imageSize / 2), y:self.frame.height * 0.15, width: imageSize, height: imageSize)
self.addSubview(imageView!)
}
imageView!.image = image
}
func setLabel(text: String) {
if self.textLabel == nil {
let textFrame = CGRect(x: 0, y: self.frame.height * 0.30, width: self.frame.width, height: self.frame.height)
self.textLabel = UILabel(frame: textFrame)
textLabel.font = UIFont(name:"Helvetica-Light", size: 14.0)
textLabel.textAlignment = .Center
textLabel.textColor = UIColor.whiteColor()
}
textLabel.text = text
}
}
Then in your cellForItemAtIndexPath:
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as ImageCell
var cellImage = UIImage(named: categoryArray[indexPath.row].catImage)
cell.setImage(cellImage)
cell.setLabel(categoryArray[indexPath.row].category)
Obviously you would have to customize it to get the same layout, but that should get you started.
Well, since it reuses the cell, and since you are adding subviews to the cell on every call, you will end up with multiple overlapping views in the same cell!
Instead, you may want to add the subviews only once, tag them, then on getting called to provide a cell dequeue one, retrieve the subviews using their tags, and set their properties as needed.