5

enter image description here

Here i am trying highlight the UICollectionViewCell on selection as shown in the image.I tried adding the border to the selected cell and the border comes inside the cell content view. Here is my try:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let cell = priorityCollectionView.cellForItem(at: indexPath)  as? BCPriorityListCollectionViewCell
    let borderWidth: CGFloat = 6
    cell?.contentView.frame = (cell?.labelBackground.frame.insetBy(dx: +borderWidth, dy: +borderWidth))!
    cell?.contentView.layer.borderColor = cell?.backgroundColor?.cgColor
    cell?.contentView.layer.borderWidth = borderWidth
}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    let cell = priorityCollectionView.cellForItem(at: indexPath)  as? BCPriorityListCollectionViewCell
    let borderWidth: CGFloat = 0
    cell?.contentView.frame = (cell?.labelBackground.frame.insetBy(dx: +borderWidth, dy: +borderWidth))!
    cell?.contentView.layer.borderColor = UIColor.clear.cgColor
    cell?.contentView.layer.borderWidth = borderWidth

}

How to do this?

Shibili k.p
  • 573
  • 5
  • 13

3 Answers3

7

Instead of adding the border width for the selected cell, just use transformation scale for zooming the selected cell. Write this code in didSelect:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let selectedCell = priorityCollectionView.cellForItem(at: indexPath)  as? BCPriorityListCollectionViewCell
    priorityCollectionView.bringSubview(toFront: selectedCell!)

    UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 5, initialSpringVelocity: 0, options: [], animations: { 
        selectedCell?.transform = CGAffineTransform(scaleX: 1.2, y: 2)
        })  
}

And in didDeselect:

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    let unselectedCell = priorityCollectionView.cellForItem(at: indexPath)  as? BCPriorityListCollectionViewCell
    UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 5, initialSpringVelocity: 0, options: [], animations: {
        unselectedCell?.transform = .identity
    })
}

Result:enter image description here

Shibili k.p
  • 573
  • 5
  • 13
  • There is a problem, If i had selected first cell ,when i scroll to the end and selected last cell, the first cell which i had selected already is not unselected. Please help its urgent. Thanks in advance – Arshad Shaik Jun 13 '18 at 08:19
  • add a `selectedCellIndex` which should be as `var selectedCellIndex: Int = 0` and store your selected cell index in it then in `cellForItemAtIndexPath` add if/else statement, should check the following `if (indexPath == selectedCellIndex)` then do the animation as in `didSelectItemAt`, and in the else do the animation as in `didDeselectItemAt`. That should work just fine in your case! @ArshadShaik – JihadiOS Jan 24 '19 at 14:12
  • @F.Jihad, i am already doing it by storing selected cell index, even it was selected when it is scrolled, it is not being highlighted. I fixed this issue by reloading the collection view as suggested by many, i already fixed that issue. – Arshad Shaik Jan 28 '19 at 05:08
0

If you want to track the selection you need to do the following:

modify your cell class BCPriorityListCollectionViewCell and add a selection property:

var isSelected: Bool = false

Then in cellForItemAtIndexPath add if statement to detect whether the cell is selected or not as follow:

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
if (cell.isSelected) {
    priorityCollectionView.bringSubview(toFront: cell)

    UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 5, initialSpringVelocity: 0, options: [], animations: { 
        cell.transform = CGAffineTransform(scaleX: 1.2, y: 2)
    })  
}

And in didSelectItemAt add one line to set the selection property:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let selectedCell = priorityCollectionView.cellForItem(at: indexPath)  as? BCPriorityListCollectionViewCell
    priorityCollectionView.bringSubview(toFront: selectedCell!)

    UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 5, initialSpringVelocity: 0, options: [], animations: { 
        selectedCell?.transform = CGAffineTransform(scaleX: 1.2, y: 2)
    })  
    selectedCell?.isSelected = true
}

Also in didDeselectItemAt add the exact line but with false value:

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    let unselectedCell = priorityCollectionView.cellForItem(at: indexPath)  as? BCPriorityListCollectionViewCell
    UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 5, initialSpringVelocity: 0, options: [], animations: {
        unselectedCell?.transform = .identity
})
    unselectedCell?.isSelected = false
}

That way if you scrolled to the end of the collection view you will not lose the selected cell status!

JihadiOS
  • 381
  • 2
  • 13
0

You can use scroll view for zooming in and zooming out of Image in collectionView

Add scroll view in your collectoinview cell and ADD image view IN the scrollview..

Then in the collectioncell file (which is type of cell file and which is called in main viewcontroller) Declare the outlets of the scrollview and image view which is I've declared in my cellfile as scr(scrollview) and zoomedImage(ImageView)....

class FinalImageCollectionViewCell: UICollectionViewCell , UIScrollViewDelegate {

@IBOutlet weak var zoomedImage: UIImageView!
@IBOutlet weak var scr: UIScrollView!  

override func awakeFromNib() {
    self.scr.delegate = self

    let doubleTapGest = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTapScrollView(recognizer:)))
    doubleTapGest.numberOfTapsRequired = 2
    scr.addGestureRecognizer(doubleTapGest)
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return zoomedImage!
}
@objc func handleDoubleTapScrollView(recognizer: UITapGestureRecognizer) {
    if scr.zoomScale == 1 {
        scr.zoom(to: zoomRectForScale(scale: scr.maximumZoomScale, center: recognizer.location(in: recognizer.view)), animated: true)
    }
    else {
        scr.setZoomScale(1, animated: true)
    }
}
func zoomRectForScale(scale: CGFloat, center: CGPoint) -> CGRect {
    var zoomRect = CGRect.zero
    zoomRect.size.height = zoomedImage.frame.size.height / scale
    zoomRect.size.width  = zoomedImage.frame.size.width  / scale
    let newCenter = zoomedImage.convert(center, from: scr)
    zoomRect.origin.x = newCenter.x - (zoomRect.size.width / 2.0)
    zoomRect.origin.y = newCenter.y - (zoomRect.size.height / 2.0)
    return zoomRect
}}

From this code you can zoom in and zoom out with pinch(without gesture) and Double tap too.

If error occurs ..Make sure you've connected delegate of scrollview to the ViewController

You can use the same code for Single ViewController(Single Image) just paste the code of override func awakeFromNib() in your viewDidLoad() and rest are the same.