Swift 3 UICollectionView reusable section header will not display - swift3

In swift 3 with Xcode 8.2 I can't get a reusableHeaderView to display with UICollectionView. I placed breakpoints at various points in my header view file and they are never tripped. Here is my code.
import UIKit
class WishListViewController: UIViewController,
UICollectionViewDelegateFlowLayout,
UICollectionViewDataSource {
var collectionView: UICollectionView!
var wishListItems = [[String:Any]]()
var shops = [[String: Any]]()
let cellId = "WishListCell"
let headerId = "WishListHeaderView"
var screenSize: CGRect!
var screenWidth: CGFloat!
var screenHeight: CGFloat!
let imageAspectRatio: CGFloat = 1.2
override func viewDidLoad() {
super.viewDidLoad()
screenSize = UIScreen.main.bounds
screenWidth = screenSize.width
screenHeight = screenSize.height
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: screenWidth, height: ((screenWidth / 3) * imageAspectRatio) + 20)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.estimatedItemSize.height = ((screenWidth / 3) * imageAspectRatio) + 20
layout.estimatedItemSize.width = screenWidth
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(WishListCell.self, forCellWithReuseIdentifier: cellId)
collectionView.register(WishListHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerId)
collectionView.backgroundColor = UIColor.white
self.view.addSubview(collectionView)
// Do any additional setup after loading the view.
}
func collectionView(_ collectionView: UICollectionView,
viewForSupplementaryElementOfKind kind: String,
at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind,
withReuseIdentifier: headerId,
for: indexPath) as! WishListHeaderView
headerView.textLabel.text = shops[indexPath.section]["shop_name"] as? String
return headerView
default:
assert(false, "Unexpected element kind")
}
}
Here is my header view file.
import UIKit
class WishListHeaderView: UICollectionReusableView {
var textLabel: UILabel
let screenWidth = UIScreen.main.bounds.width
override init(frame: CGRect) {
textLabel = UILabel()
super.init(frame: frame)
self.addSubview(textLabel)
textLabel.font = UIFont.systemFont(ofSize: UIFont.smallSystemFontSize)
textLabel.textAlignment = .left
textLabel.numberOfLines = 0
textLabel.lineBreakMode = NSLineBreakMode.byWordWrapping
textLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
NSLayoutConstraint(item: textLabel, attribute: .leading, relatedBy: .equal,
toItem: self, attribute: .leadingMargin,
multiplier: 1.0, constant: 0.0),
NSLayoutConstraint(item: textLabel, attribute: .trailing, relatedBy: .equal,
toItem: self, attribute: .trailingMargin,
multiplier: 1.0, constant: 0.0),
])
self.backgroundColor = .white
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

You need to implement height for header function for your collection view.
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
referenceSizeForHeaderInSection section: Int) -> CGSize
then return the height you want it to be.

Related

Using SwiftUI View for UICollectionViewCell

I made UICollectionView that accept (Item) -> Content (where Content:View) as init parameter to pass this SwiftUI View to cell content view using UIHostController. But by some reason my screen is empty, however if I pass some View instead of Content directly to UIHosting controller everything works fine.
Code:
Cell
final class SnapCarouselCell<Content:View>: UICollectionViewCell{
var cellContent: Content?
override init(frame: CGRect) {
super.init(frame: frame)
let vc = UIHostingController(rootView: cellContent)
contentView.addSubview(vc.view)
vc.view.translatesAutoresizingMaskIntoConstraints = false
vc.view.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
vc.view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
vc.view.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
vc.view.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Controller
class SnapCarouselViewController<Item: Equatable, Content: View>: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource{
lazy var snapCarouselView: UICollectionView = {
let collectionView = setUpCollectionView()
self.view.addSubview(collectionView)
return collectionView
}()
private let flowLayout: UICollectionViewFlowLayout
private let cellHeight: CGFloat
private let cellWidth: CGFloat
private var centerCell: UICollectionViewCell?
private let items: [Item]
private let cellContent: (Item) -> Content
init(
cellHeight: CGFloat,
cellWidth: CGFloat,
items: [Item],
#ViewBuilder cellContent: #escaping (Item) -> Content
){
self.cellHeight = cellHeight
self.cellWidth = cellWidth
self.flowLayout = SnapCarouselViewFlowLayout(cellWidth: cellWidth, cellHeight: cellHeight)
self.items = items
self.cellContent = cellContent
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
snapCarouselView.dataSource = self
snapCarouselView.delegate = self
let indexPath = IndexPath(row: 9999999999, section: 0)
snapCarouselView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: false)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return Int.max
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SnapCarouselCell", for: indexPath) as! SnapCarouselCell<Content>
cell.cellContent = cellContent(items[indexPath.row % items.count])
return cell
}
private func setUpCollectionView() -> UICollectionView{
let collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: flowLayout)
collectionView.backgroundColor = .white
collectionView.showsHorizontalScrollIndicator = false
collectionView.frame = CGRect(x: 0, y: 100, width: view.frame.size.width, height: cellHeight)
collectionView.decelerationRate = .fast
collectionView.register(SnapCarouselCell<Content>.self, forCellWithReuseIdentifier: "SnapCarouselCell")
return collectionView
}
}
View
struct SnapCarouselView<Content: View, Item: Equatable>: UIViewControllerRepresentable {
private let cellContent: (Item) -> Content
private let cellHeight: CGFloat
private let cellWidth: CGFloat
private let items: [Item]
init(
cellHeight: CGFloat,
cellWidth: CGFloat,
items: [Item],
#ViewBuilder cellContent: #escaping (Item) -> Content
) {
self.cellHeight = cellHeight
self.cellWidth = cellWidth
self.cellContent = cellContent
self.items = items
}
func makeUIViewController(context: Context) -> SnapCarouselViewController<Item,Content> {
let vc = SnapCarouselViewController(
cellHeight: cellHeight,
cellWidth: cellWidth,
items: items,
cellContent: cellContent)
return vc
}
func updateUIViewController(_ uiViewController: SnapCarouselViewController<Item,Content>, context: Context) {
}
typealias UIViewControllerType = SnapCarouselViewController
}
struct TestUICollectionView_Previews: PreviewProvider {
static var previews: some View {
SnapCarouselView(cellHeight: 200, cellWidth: 200, items: test) { item in
Text(item.name)
}
}
}
struct Test: Equatable{
var id = UUID()
let name : String
}
let test = [
Test(name: "1"),
Test(name: "2"),
Test(name: "3"),
Test(name: "4"),
Test(name: "5"),
Test(name: "6"),
Test(name: "7"),
Test(name: "8"),
Test(name: "9"),
Test(name: "10"),
Test(name: "12"),
Test(name: "12"),
Test(name: "13"),
Test(name: "14"),
Test(name: "15"),
]

Building a page that shows a photo like photo app (zoom and pan)

How to build a page that works exactly like the Photo Apps of the iOS that can zoom into a photo using MagnificationGesture() and can pan after zoom using Pure SwiftUI?
I have tried to look for solutions in the forum, yet, none of question has a solution yet. Any advise?
Here is my code:
let magnificationGesture = MagnificationGesture()
.onChanged { amount in
self.currentAmount = amount - 1
}
.onEnded { amount in
self.finalAmount += self.currentAmount
self.currentAmount = 0
}
let tapGesture = TapGesture()
.onEnded {
self.currentAmount = 0
self.finalAmount = 1
}
Image("Cat")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width:UIScreen.main.bounds.width,height: UIScreen.main.bounds.height)
.scaleEffect(finalAmount + currentAmount)
.simultaneousGesture(magnificationGesture)
.simultaneousGesture(tapGesture)
Originally, I tried to add 1 more simultaneousGesture, dragGesture() which adjust the offset, but it fails to work.
The current code zoom the image well, but after zoom in, I want it to be allowed to pan. I have tried to add UIScrollView it also fails.
Here is my thought:
let dragGesture = DragGesture()
.onChanged { value in self.offset = value.translation }
and to add .offset() to the image.
However, it fails to work and the simulator is out of memory.
Any advise?
Use DragGesture() with position.
Tested Xcode 12.1 with iOS 14.2 (No Memory issues.)
struct ContentView: View {
#State private var currentAmount: CGFloat = 0
#State private var finalAmount: CGFloat = 1
#State private var location: CGPoint = CGPoint(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2)
#GestureState private var startLocation: CGPoint? = nil
var body: some View {
let magnificationGesture = MagnificationGesture()
.onChanged { amount in
self.currentAmount = amount - 1
}
.onEnded { amount in
self.finalAmount += self.currentAmount
self.currentAmount = 0
}
// Here is create DragGesture and handel jump when you again start the dragging/
let dragGesture = DragGesture()
.onChanged { value in
var newLocation = startLocation ?? location
newLocation.x += value.translation.width
newLocation.y += value.translation.height
self.location = newLocation
}.updating($startLocation) { (value, startLocation, transaction) in
startLocation = startLocation ?? location
}
return Image("temp_1")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width:UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
.scaleEffect(finalAmount + currentAmount)
.position(location)
.gesture(
dragGesture.simultaneously(with: magnificationGesture)
)
}
}
I finally managed to solve the issue with UIViewRepresentable.
struct ImageScrollView: UIViewRepresentable {
private var contentSizeWidth: CGFloat = 0
private var contentSizeHeight: CGFloat = 0
private var imageView = UIImageView()
private var scrollView = UIScrollView()
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: UIViewRepresentableContext<ImageScrollView>) -> UIScrollView {
let image = UIImage(named: "Dummy")
let width = image?.size.width
let height = image?.size.height
imageView.image = image
imageView.frame = CGRect(x: 0, y: 0, width: width ?? 0, height: height ?? 0)
imageView.contentMode = UIView.ContentMode.scaleAspectFit
imageView.isUserInteractionEnabled = true
scrollView.delegate = context.coordinator
scrollView.isScrollEnabled = true
scrollView.clipsToBounds = true
scrollView.bouncesZoom = true
scrollView.isUserInteractionEnabled = true
scrollView.minimumZoomScale = 0.5 //scrollView.frame.size.width / (width ?? 1)
scrollView.maximumZoomScale = 2
scrollView.zoomScale = 1
scrollView.contentSize = imageView.frame.size
scrollView.addSubview(imageView)
let doubleTapGestureRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap(sender:)))
doubleTapGestureRecognizer.numberOfTapsRequired = 2;
doubleTapGestureRecognizer.numberOfTouchesRequired=1;
scrollView.addGestureRecognizer(doubleTapGestureRecognizer)
imageView.addGestureRecognizer(doubleTapGestureRecognizer)
return scrollView
}
func updateUIView(_ uiView: UIScrollView,
context: UIViewRepresentableContext<ImageScrollView>) {
}
class Coordinator: NSObject, UIScrollViewDelegate {
var control: ImageScrollView
init(_ control: ImageScrollView) {
self.control = control
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("scrollViewDidScroll")
centerImage()
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView,
with view: UIView?,
atScale scale: CGFloat) {
print("scrollViewDidEndZooming")
print(scale, scrollView.minimumZoomScale, scrollView.maximumZoomScale)
scrollView.setZoomScale(scale, animated: true)
centerImage()
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.control.imageView
}
func centerImage() {
let boundSize = self.control.scrollView.frame.size
var frameToCenter = self.control.imageView.frame
frameToCenter.origin.x = 0
frameToCenter.origin.y = 0
if (frameToCenter.size.width<boundSize.width) {
frameToCenter.origin.x = (boundSize.width-frameToCenter.size.width)/2;
}
if (frameToCenter.size.height<boundSize.height) {
frameToCenter.origin.y = (boundSize.height-frameToCenter.size.height)/2;
}
self.control.imageView.frame = frameToCenter
}
#objc func handleTap(sender: UITapGestureRecognizer) {
if (self.control.scrollView.zoomScale==self.control.scrollView.minimumZoomScale) {
self.control.scrollView.zoomScale = self.control.scrollView.maximumZoomScale/2;
} else {
self.control.scrollView.zoomScale = self.control.scrollView.minimumZoomScale;
}
print("tap")
}
}
}

How to move scrollview with buttons only in SwiftUI

Previously I did with Swift4 UIScrollView which scrolled with buttons and x offset.
In Swift4 I have:
Set Scrolling Enabled and Paging Enabled to false.
Created the margins, offsets for each frame in UIScrollView and changed the position with buttons Back and Next.
Here is the code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var buttonSound: UIButton!
#IBOutlet weak var buttonPrev: UIButton!
#IBOutlet weak var buttonNext: UIButton!
#IBOutlet weak var scrollView: UIScrollView!
var levels = ["level1", "level2", "level3", "level4"]
let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
var currentLevel = 1
var previousLevel: Int? = nil
override func viewDidLoad() {
super.viewDidLoad()
//Defining the Various Swipe directions (left, right, up, down)
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(self.handleGesture(gesture:)))
swipeLeft.direction = .left
self.view.addGestureRecognizer(swipeLeft)
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.handleGesture(gesture:)))
swipeRight.direction = .right
self.view.addGestureRecognizer(swipeRight)
addHorizontalLevelsList()
customizeButtons()
resizeSelected()
}
func addHorizontalLevelsList() {
var frame : CGRect?
for i in 0..<levels.count {
let button = UIButton(type: .custom)
let buttonW = screenWidth/3
let buttonH = screenHeight/2
frame = CGRect(x: CGFloat(i+1) * (screenWidth/2) - (buttonW/2),
y: buttonH - 100,
width: buttonW,
height: buttonH)
button.frame = frame!
button.tag = i+1
button.backgroundColor = .lightGray
button.addTarget(self, action: #selector(selectTeam), for: .touchUpInside)
button.setTitle(levels[i], for: .normal)
scrollView.addSubview(button)
}
scrollView.contentSize = CGSize(width: (screenWidth/2 * CGFloat(levels.count)),
height: screenHeight)
scrollView.backgroundColor = .clear
self.view.addSubview(scrollView)
}
func customizeButtons(){
buttonPrev.frame = CGRect(x: 0,
y: (screenHeight/2) - 40,
width: 80, height: 80)
buttonNext.frame = CGRect(x: screenWidth - 80,
y: (screenHeight/2) - 40,
width: 80, height: 80)
buttonPrev.superview?.bringSubviewToFront(buttonPrev)
buttonNext.superview?.bringSubviewToFront(buttonNext)
}
#objc func selectTeam(button: UIButton) {
button.transform = CGAffineTransform(scaleX: 0.6, y: 0.6)
UIView.animate(withDuration: 1.0,
delay: 0,
usingSpringWithDamping: CGFloat(0.20),
initialSpringVelocity: CGFloat(6.0),
options: UIView.AnimationOptions.allowUserInteraction,
animations: {
button.transform = CGAffineTransform.identity
},
completion: { Void in() }
)
print(levels[button.tag])
let vc = PopTypeVC(nibName: "PopTypeVC", bundle: nil)
vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
self.present(vc, animated: true)
}
#IBAction func prevLevel(_ sender: Any) {
if currentLevel > 0 {
currentLevel -= 1
scroll()
}
}
#IBAction func nextLevel(_ sender: Any) {
if currentLevel < levels.count {
currentLevel += 1
scroll()
}
}
func scroll(){
print(currentLevel)
print(previousLevel as Any)
scrollView.setContentOffset(CGPoint(x: currentLevel * Int(screenWidth/2), y: 0), animated: true)
resizeSelected()
}
// The #objc before func is a must, since we are using #selector (above)
#objc func handleGesture(gesture: UISwipeGestureRecognizer) -> Void {
if gesture.direction == UISwipeGestureRecognizer.Direction.right {
prevLevel(self)
}
else if gesture.direction == UISwipeGestureRecognizer.Direction.left {
nextLevel(self)
}
}
func resizeSelected(){
if previousLevel != nil {
let previousFrame = CGRect(x:CGFloat(previousLevel!) * (screenWidth/2) - (screenWidth/3)/2,
y: (screenHeight/2) - 100,
width: screenWidth/3,
height: screenHeight/2)
scrollView.viewWithTag(previousLevel!)?.frame = previousFrame
}
let currentFrame = CGRect(x: CGFloat(currentLevel) * (screenWidth/2) - (screenWidth/3)/2 - 10,
y: (screenHeight/2) - 110,
width: screenWidth/3 + 20,
height: screenHeight/2 + 20)
scrollView.viewWithTag(currentLevel)?.frame = currentFrame
previousLevel = currentLevel
}
}
The problem is I can't do this with SwiftUI:
struct ContentView: View {
static var levels = ["level1",
"level2",
"level3",
"level4"]
var currentLevel = 1
var previousLevel: Int? = nil
let screenW = UIScreen.main.bounds.width
let screenH = UIScreen.main.bounds.height
let margin1 = 50
let margin2 = 100
let margin3 = 20
let sceneButtonW = 100
let buttonPadding = 40
var body: some View {
ZStack {
// Horizontal list
VStack {
Spacer()
.frame(height: margin2)
ScrollView(.horizontal, showsIndicators: false) {
HStack{
Spacer()
.frame(width: buttonPadding + sceneButtonW/2)
ForEach(0..<ContentView.levels.count) { i in
cardView(i: i).tag(i+1)
}
Spacer()
.frame(width: buttonPadding + sceneButtonW/2)
}
}
Spacer()
.frame(height: margin3)
}
}
.background(Image("bg")
.resizable()
.edgesIgnoringSafeArea(.all)
.aspectRatio(contentMode: .fill))
}
}
Question: Are there any methods to disable automatic scrolling at all and use offsets at ScrollView with SwiftUI?
This already built solution for SwiftUI
https://github.com/fermoya/SwiftUIPager
However, there is no real example.

Image Slider with UIScrollView

I am making an image slider that slides automatically every 2 seconds. The code I have wrote moves immediately to the next image without the slide animation, I want to fix it somehow by showing the scrollview scrolling, this is my code:
var imagesArray = [UIImage]()
static var i = 0
override func viewDidLoad() {
super.viewDidLoad()
imagesArray = [image1, image2, image3, image4]
for i in 0..<imagesArray.count{
let imageview = UIImageView()
imageview.image = imagesArray[i]
imageview.contentMode = .scaleAspectFit
let xPosition = self.view.frame.width * CGFloat(i)
imageview.frame = CGRect(x: xPosition, y: 0, width: self.imagesScrollView.frame.width, height: self.imagesScrollView.frame.height)
imagesScrollView.contentSize.width = imagesScrollView.frame.width * CGFloat(i+1)
imagesScrollView.addSubview(imageview)
}
}
override func viewDidAppear(_ animated: Bool) {
let scrollingTimer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(MenuViewController.newStartScrolling), userInfo: nil, repeats: true)
scrollingTimer.fire()
func newStartScrolling()
{
if MenuViewController.i == imagesArray.count {
MenuViewController.i = 0
}
let x = CGFloat(MenuViewController.i) * imagesScrollView.frame.size.width
imagesScrollView.contentOffset = CGPoint(x: x, y: 0)
MenuViewController.i += 1
}
Thank you.
Please try this code.
override func viewDidAppear(_ animated: Bool) {
imagesArray = [UIImage(named: "apple.jpg")!, UIImage(named: "empire.jpg")!, UIImage(named: "ottawa.jpg")!]
imagesScrollView.contentSize = CGSize(width: imagesScrollView.frame.width * CGFloat(imagesArray.count), height: imagesScrollView.frame.height)
for i in 0..<imagesArray.count{
let imageview = UIImageView()
imageview.image = imagesArray[i]
imageview.contentMode = .scaleAspectFill
imageview.clipsToBounds = true
let xPosition = self.imagesScrollView.frame.width * CGFloat(i)
imageview.frame = CGRect(x: xPosition, y: 0, width: self.imagesScrollView.frame.width, height: self.imagesScrollView.frame.height)
print(imageview)
imagesScrollView.addSubview(imageview)
}
let scrollingTimer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(ViewController.newStartScrolling), userInfo: nil, repeats: true)
scrollingTimer.fire()
}
func newStartScrolling()
{
if ViewController.i == imagesArray.count {
ViewController.i = 0
}
let x = CGFloat(ViewController.i) * imagesScrollView.frame.size.width
imagesScrollView.setContentOffset(CGPoint(x: x, y: 0), animated: true)
ViewController.i += 1
}
you have to use func setContentOffset(_ contentOffset: CGPoint, animated: Bool) method to change content offset using animation.
#IBOutlet weak var imageView:UIImageView!
var i=Int()
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(imageChange), userInfo: nil, repeats: true)
// Do any additional setup after loading the view.
}
#objc func imageChange(){
self.imageView.image=images[i]
if i<images.count-1{
i+=1
}
else{
i=0
}
}

UICollectionViewCell - Change ImageViewImage on tap

I have a UIImageView called "icon" inside a UICollectionViewCell. I would like to change the image in the UIImageView when I tap on the UICollectionViewCell.
How do I do that? I have the following code so far.
import UIKit
class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
let icons = [UIImage(named: "pa-w"),UIImage(named: "pi-w"),UIImage(named: "po-w"),UIImage(named: "r-w")]
let iconsHovered = [UIImage(named: "pa-b"),UIImage(named: "pi-b"),UIImage(named: "po-b"),UIImage(named: "r-b")]
let names = ["ABC", "DEF", "GHI", "JKL"]
let colors = ["#cccccc", "#eeeeee", "#dddddd","#aaaaaa"]
var screenSize: CGRect!
var screenWidth: CGFloat!
var screenHeight: CGFloat!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
collectionView.delegate = self
collectionView.dataSource = self
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
let width = UIScreen.main.bounds.width
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: width / 2, height: width / 2)
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
collectionView!.collectionViewLayout = layout
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return icons.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.icon.image = icons[indexPath.row]
cell.name.text = " " + names[indexPath.row]
cell.backgroundColor = UIColor().HexToColor(hexString: colors[indexPath.row], alpha: 1.0)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath as IndexPath)! as UICollectionViewCell
//This line gives an error saying no ImageView called icon exists.
cell.icon.image = iconsHovered[indexPath.row]
}
}
extension UIColor{
func HexToColor(hexString: String, alpha:CGFloat? = 1.0) -> UIColor {
// Convert hex string to an integer
let hexint = Int(self.intFromHexString(hexStr: hexString))
let red = CGFloat((hexint & 0xff0000) >> 16) / 255.0
let green = CGFloat((hexint & 0xff00) >> 8) / 255.0
let blue = CGFloat((hexint & 0xff) >> 0) / 255.0
let alpha = alpha!
// Create color object, specifying alpha as well
let color = UIColor(red: red, green: green, blue: blue, alpha: alpha)
return color
}
func intFromHexString(hexStr: String) -> UInt32 {
var hexInt: UInt32 = 0
// Create scanner
let scanner: Scanner = Scanner(string: hexStr)
// Tell scanner to skip the # character
scanner.charactersToBeSkipped = NSCharacterSet(charactersIn: "#") as CharacterSet
// Scan hex value
scanner.scanHexInt32(&hexInt)
return hexInt
}
}
Try let cell = collectionView.cellForItem(at: indexPath as IndexPath)! as CollectionViewCell instead of let cell = collectionView.cellForItem(at: indexPath as IndexPath)! as UICollectionViewCell. Then you should have your cell as CollectionViewCell, which, according to your code, has a icon-property.