I want to push a UICollectionViewController when i press a uibutton. I have test some and when i press the button it navigates to a blank ViewController.
Root View Controller (CategoryViewController)
class CategoryViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//UIButton
let image = UIImage(named: "menudo") as UIImage?
let button = UIButton(type: UIButtonType.Custom) as UIButton
button.frame = CGRectMake(100, 100, 100, 100)
button.setImage(image, forState: .Normal)
button.addTarget(self, action: #selector(CategoryViewController.action(_:)), forControlEvents:.TouchUpInside)
self.view.addSubview(button)
}
func action(sender: UIButton!) {
let layout = UICollectionViewLayout()
let collectionViewController = MealCollectionViewController(collectionViewLayout: layout)
navigationController?.pushViewController(collectionViewController, animated: true)
}
I want to show this ViewController when i press the uibutton (MealCollectionViewController)
import Foundation
import UIKit
class MealCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
//Creating the CellId for reusable cell
private let cellId = "cellId"
override func viewDidLoad() {
super.viewDidLoad()
//Creating CollectionView
collectionView?.backgroundColor = UIColor.whiteColor()
//setting the cellId reusable to show on screen USE CATEGORY CELL BECAUSE MEALCOLLECTION VIEW IS NOT A CELL
collectionView?.registerClass(CategoryCell.self, forCellWithReuseIdentifier: cellId)
}
//Creating the layout for the cell
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellId, forIndexPath: indexPath) as! CategoryCell
return cell
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(view.frame.width, view.frame.height)
}
}
If you are Using storyboard then use this code...
let meal: MealCollectionViewController = (self.storyboard?.instantiateViewControllerWithIdentifier("STORYBIARD_CONTROLLER_IDEBTIFIER_NAME"))! as! MealCollectionViewController
self.navigationController?.pushViewController(meal, animated: true)
Use this code -
let mealController = self.storyboard?.instantiateViewControllerWithIdentifier("your controller identifier name here") as MealCollectionViewController
self.navigationController?.pushViewController(mealController, animated: true)
Related
I'm working with a UITableViewController and when clicking a cell i would like to have a UICollectionViewController be popped up.
I've been successful in presenting the UICollectionViewController from a UITableViewController. However, I'm not able to figure out on how to present it like a pop-up only taking portion of the screen. It currently feels the entire view.
I searched on stackoverflow but couldn't find a working solution.
UITableViewController
class SearchViewController: UITableViewController, UISearchBarDelegate {
let cellId = "cellId"
var filteredArray = [String]()
let books = Model().books
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
navigationItem.titleView = navSearchBar
setupView()
}
// Views.
let navSearchBar = NavSearchBar()
func setupView() {
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
tableView.delegate = self
tableView.dataSource = self
navSearchBar.delegate = self
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { // Cancel button is touched.
self.dismiss(animated: true, completion: nil)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return books.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
book = books[indexPath.row]
}
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
cell.textLabel?.text = book
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
let cellLabelContent = cell!.textLabel!.text // Gets cell name.
let cellLabelIndex = bibleBooks.firstIndex(of: cellLabelContent!) // searches books array to get correct index of cell name.
print("Book name:", cellLabelContent!+",", "index:", cellLabelIndex!)
let notificName = Notification.Name(rawValue: searchedBookIndex)
NotificationCenter.default.post(name: notificName, object: cellLabelIndex)
dismiss(animated: true, completion: nil)
**HERE is where i present the collectionView**
let layout = UICollectionViewFlowLayout()
var topVC = UIApplication.shared.keyWindow?.rootViewController
while((topVC!.presentedViewController) != nil) {
topVC = topVC!.presentedViewController
let navController = UINavigationController(rootViewController: ChapterNumbersCollectionView(collectionViewLayout: layout))
topVC?.present(navController, animated: true, completion: nil)
}
}
UICollectionViewController
class ChapterNumbersCollectionView: UICollectionViewController {
let reuseIdentifier = "CellId"
override func viewDidLoad() {
super.viewDidLoad()
setupCollectionView()
setupNavigationItem()
}
private func setupCollectionView() {
collectionView.backgroundColor = .yellow
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}
private func setupNavigationItem() {
let button = UIButton(type: .system)
button.setTitle("cancel", for: [])
button.addTarget(self, action: #selector(handleDismiss), for: .touchUpInside)
button.frame = CGRect(x: 0, y: 0, width: 34, height: 34)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button)
}
#objc func handleDismiss() {
dismiss(animated: true, completion: nil)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 200
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath)
cell.backgroundColor = .red
return cell
}
One approach would be to use view controller containment. You'd instantiate ChapterNumbersCollectionView in didSelectRow, but instead of presenting, add it as a child view controller.
Then, having added its view as a subview, animate it in using animateWithDuration.
I got a HomeController of type UICollectionViewController which handles some PictureCells (contains a picture and a label).
Now I am sending one PictureCell to another ViewController to edit the label. This all works perfectly. I could send it back to the HVC using a protocol but instead of going back I want to go one step further and Display the edited PictureCell in a new ViewController.
Instead of creating a completely new one, I am subclassing the existing HomeController to reuse his CollectionView. All works fine and the view shows up but the edited PictureCell is not showing up at all, even tho I can show it's layer, the Cell itself with its content doesn't show up.
(Messy) Class-Diagram looks like this:
ClassDiagram
class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout, MyProtocol {
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.black
collectionView?.register(PictureCell.self, forCellWithReuseIdentifier: Constants.cellId)
}
//MARK: Get value from second VC
var valueSentFromSecondViewController: String?
var cellSentFromSecondViewController: PictureCell?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
//Acting with Protocol here
}
//HERE ARE THE COLLECTIONVIEWFUNCTIONS
}
class PictureEditViewController: UIViewController, UITextFieldDelegate {
var delegate:MyProtocol?
var myCell: PictureCell?
let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = UIColor.white
return cv
}()
init(pictureCellInit: PictureCell?) {
self.myCell = pictureCellInit
super.init(nibName: nil, bundle: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
showThings()
}
#objc func showNextVC() {
let newViewController = PictureShowViewController(withCell: self.myCell)
newViewController.modalPresentationStyle = .overCurrentContext
present(newViewController, animated: true) //with dismiss
}
#objc func showThings() {
view.addSubview(collectionView)
self.collectionView.frame = CGRect(x: x, y: y, width: width, height: height)
self.setupViews()
}
func setupViews() {
//ADDING THE SUBVIEWS
}
func confBounds() {
//LAYOUT
}
#objc func handleDismiss() {
self.dismiss(animated: true, completion: nil)
}
class PictureShowViewController: HomeController {
//MARK: Variable/Constant declaration
var myCellToShow: PictureCell?
init(withCell: PictureCell?) {
let layoutUsing = UICollectionViewFlowLayout()
myCellToShow = withCell
super.init(collectionViewLayout: layoutUsing)
}
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = .white
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
collectionView?.addSubview(myCellToShow!)
self.collectionView?.reloadData()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = myCellToShow {
cell.layer.borderColor = UIColor.red.cgColor
cell.layer.borderWidth = 2
return cell
}
else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.cellId, for: indexPath) as! PictureCell
return cell
}
}
//Size of Cell
override func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cellSize = CGFloat(view.frame.width)
return CGSize(width: cellSize, height: cellSize)
}
}
Does anyone have an idea where I went wrong?
It is a bad idea to use PictureCell to move your data around view controllers. UICollectionView reuses instances of cells so the content of the cell is bound to change anytime.
So instead of using your cell, hand over the underlying data and insert the data in to the newly dequeued collection view cell.
In the end,
var cellSentFromSecondViewController: PictureCell?
should be var pictureFromSecondViewController: YourPictureData
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Constants.cellId, for: indexPath) as! PictureCell
//Set your data
cell.picture = pictureFromSecondViewController
return cell
}
Hey i'm new to programming and my problem is, i have a UICollectionViewController with 4 cells that are horizontal scrollable. Inside of the 4th cell i have a UIButton(optionsButton) on top of a UIView (ProfileContainerView).
The UIViewController I want to present is called ProfileEditViewController and is set up in Main.storyboard.
How can i present a UIViewController after pressing this button?
ProfileCell:
class ProfileCell: UICollectionViewCell {
let profileContainerView: UIView = {
let view = UIView()
return view
}()
lazy var optionsButton: UIButton = {
let btn = UIButton(type: .custom)
btn.setImage(#imageLiteral(resourceName: "Settings"), for: UIControlState.normal)
btn.addTarget(self, action: #selector(handleOptionsButton), for: UIControlEvents.touchUpInside)
return btn
}()
#objc func handleOptionsButton() {
print("Button pressed")
}
}
HomeViewController:
class HomeViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
let profileCelId = "profileCell"
override func viewDidLoad() {
super.viewDidLoad()
setupSwipeView()
}
func setupSwipeView() {
collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cell)
collectionView?.register(ProfileCell.self, forCellWithReuseIdentifier: profileCelId)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 3 {
return collectionView.dequeueReusableCell(withReuseIdentifier: profileCelId, for: indexPath)
}
return cell
}
}
You can use delegates to implement this.
Below is the code to implement this
protocol ProfileCollectionViewCellDelegate {
func buttonPressedAtIndexPath(inCell: ProfileCell)
}
class ProfileCell: UICollectionViewCell {
var delegate : ProfileCollectionViewCellDelegate?
let profileContainerView: UIView = {
let view = UIView()
return view
}()
lazy var optionsButton: UIButton = {
let btn = UIButton(type: .custom)
btn.setImage(#imageLiteral(resourceName: "Settings"), for: UIControlState.normal)
btn.addTarget(self, action: #selector(handleOptionsButton), for: UIControlEvents.touchUpInside)
return btn
}()
#objc func handleOptionsButton() {
if self.delegate != nil {
self.delegate?.buttonPressedAtIndexPath(self)
}
}
}
For your HomeViewController
class HomeViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, ProfileCollectionViewCellDelegate {
let profileCelId = "profileCell"
override func viewDidLoad() {
super.viewDidLoad()
setupSwipeView()
}
func setupSwipeView() {
collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cell)
collectionView?.register(ProfileCell.self, forCellWithReuseIdentifier: profileCelId)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: profileCelId, for: indexPath)
cell.delegate = self
return cell
}
fun buttonPressedAtIndexPath(inCell: ProfileCell) {
let indexOfCell = self.collectionView.indexPath(for: cell)
if indexOfCell.row == 3 {
//Do your work here
}
}
}
You can present your ProfileEditViewController, which is styled in your Main.storyboard the following way:
1) Give your ProfileEditViewController a StoryBoard ID. E.g. "ProfileEditViewController" - Some question regarding this is here: What is a StoryBoard ID and how can i use this?
2) Register the UIViewController for the action on the UIButton or offer an appropriate callback functionality.
As your HomeViewController is also your Collection View's datasource, you can easily extend your DataSource method
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell`
Implementation could look like:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 3 {
let profileCell = collectionView.dequeueReusableCell(withReuseIdentifier: profileCelId, for: indexPath)
if let _cell = cell as? ProfileCell,
let button = _cell.optionsButton as? UIButton {
button.addTarget(self, action: #selector(handleOptionsButton), forControlEvents: UIControlEvents.TouchUpInside)
}
return profileCell;
}
return cell
}
Make sure that your buttons Action is now also being implemented by your HomeViewController
#objc func handleOptionsButton() {
print("Button pressed")
}
3) Now in HomeViewController.handleOptionsButton you need to provide a functionality to support the transition to that specific Controller with the desired StoryboardID:
let storyboard = UIStoryboard(name: "Main", bundle:Bundle.main)
let controller = storyboard.instantiateViewController(withIdentifier: "ProfileEditViewController")
self.present(controller, animated: true, completion: nil)
let proCell = ProfileCell()
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.cell, for: indexPath)
if indexPath.item == 3 {
let profileCell = collectionView.dequeueReusableCell(withReuseIdentifier: profileCelId, for: indexPath)
let button = proCell.optionsButton
button.addTarget(self, action: #selector(handleOptionsButton), for: UIControlEvents.touchUpInside)
return profileCell;
}
return cell
}
I created a UICollectionView as a major UICollectionView and each collectionViewCell has another UICollectionView "B" as it's subview
Then I add a tapGesture in "B". but "B" can't trigger this gesture.
Following is my main code:
Main UICollectionView
import Foundation
import UIKit
class mainViewController :UIViewController,UICollectionViewDataSource,UICollectionViewDelegate {
#IBOutlet weak var mainCollectionView: UICollectionView!
override func viewDidLoad() {
self.mainCollectionView.registerNib(UINib(nibName: "OuterCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "OuterCollectionViewCell")
self.mainCollectionView.delegate = self
self.mainCollectionView.dataSource = self
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 1
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("OuterCollectionViewCell", forIndexPath: indexPath) as! OuterCollectionViewCell
return cell
}
}
UICollectionView B:
class OuterCollectionViewCell: UICollectionViewCell,UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet weak var InnerCollectionView: UICollectionView!
override func awakeFromNib() {
super.awakeFromNib()
InnerCollectionView.registerNib(UINib(nibName: "InnerCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CellInner")
}
func handleTapGesture(sender: UITapGestureRecognizer) {
print("tapguesture")
}
override func didMoveToWindow(){
let tapGesture = UITapGestureRecognizer(target: self, action: "handleTapGesture:")
InnerCollectionView.backgroundColor = UIColor.redColor()
InnerCollectionView.addGestureRecognizer(tapGesture)
InnerCollectionView.delegate = self
InnerCollectionView.dataSource = self
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CellInner", forIndexPath: indexPath) as! InnerCollectionViewCell
return cell
}
}
This issue is bugging me an whole day. Is there anyone who has any ideas about how to fix this issue?
I have uploaded the project into github: https://github.com/dengchicheng/Test2
update------------------------------
today I init the innerCollectionView by code programmably instead of init by NIB. and it works
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = UICollectionViewScrollDirection.Horizontal
let InnerCollectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: 800, height: 600), collectionViewLayout: flowLayout)
I don't know what the NIB did to the UIcollectionview
I did set the userInteractive to be true in the interface builder
I would like to add a UIImageView animated inside an UICollectionViewCell so I came up with this code:
import UIKit
class MainViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
var items:[String] = ["one", "two", "three", "four"]
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 220/255, green: 220/255, blue: 220/255, alpha: 1.0)
self.view.addSubview(self.collectionView)
}
lazy var collectionView:UICollectionView = {
var cv = UICollectionView(frame: self.view.bounds, collectionViewLayout: self.flowLayout)
cv.delegate = self
cv.dataSource = self
cv.bounces = true
cv.alwaysBounceVertical = true
cv.autoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth
cv.registerClass(CustomCell.self, forCellWithReuseIdentifier: "cell")
cv.backgroundColor = UIColor(red: 220/255, green: 220/255, blue: 220/255, alpha: 1.0)
return cv
}()
lazy var flowLayout:UICollectionViewFlowLayout = {
var flow = UICollectionViewFlowLayout()
flow.sectionInset = UIEdgeInsetsMake(2.0, 2.0, 2.0, 2.0)
return flow
}()
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize{
let width:CGFloat = self.view.bounds.size.width*0.98;
let height:CGFloat = 150.0;
return CGSizeMake(width, height)
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
return self.items.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CustomCell
cell.layer.cornerRadius = 4
cell.backgroundColor = UIColor.whiteColor()
cell.imgView.animationImages = ["1","2","3","4","5", "6","7","8"].map{UIImage(named: $0)!}
cell.imgView.animationDuration = NSTimeInterval(0.8)
cell.imgView.startAnimating()
return cell
}
func collectionView(collectionView: UICollectionView, shouldHighlightItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
var alert = UIAlertController(title: "Alert!", message: "Cell tapped", preferredStyle: UIAlertControllerStyle.Alert)
var action = UIAlertAction(title: "ok", style: UIAlertActionStyle.Cancel) { (dd) -> Void in }
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
}
}
This is my MainViewController with a CollectionView added programmatically.
import UIKit
class CustomCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(self.imgView)
}
lazy var imgView:UIImageView = {
var iv = UIImageView()
iv.contentMode = UIViewContentMode.ScaleAspectFill
return iv
}()
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
self.imgView.frame = CGRectMake(6,15,self.frame.width*0.2, self.frame.height*0.8)
}
}
And this is my custom UICollectionViewCell with an UIImageView
My problem is when you tap a cell the UIImageView disappears. Trying to solve the problem I started to look another UICoolectionView delegate methods. Then I tried to use shouldHighlightItemAtIndexPath, But If I use this method returning false the animation works fine but the collection view stops responding to didSelectItemAtIndexPath.
This is a github repository with a code that shows the issue: https://github.com/gazolla/ImageAnimation (updated with solution)
SOLUTION:
With matt's help, I made the following changes in my code:
1) add images array to highlightedAnimationImages property
let animationArray = ["1","2","3","4","5", "6","7","8"].map{UIImage(named: $0)!}
cell.imgView.highlightedAnimationImages = animationArray
2) Restart animation when cells are deselected
func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? CustomCell{
cell.imgView.startAnimating()
}
}
3) Restart animation when cells are selected
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! CustomCell
cell.imgView.startAnimating()
//...
}
SOLUTION 2:
After some tests, I found out that when you tap and hold a cell UIImageView disappears again, So we have to restart animation in another two methods:
1) didHighlightItemAtIndexPath
func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath) {
if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? CustomCell{
cell.imgView.startAnimating()
}
}
2) didUnhighlightItemAtIndexPath
func collectionView(collectionView: UICollectionView, didUnhighlightItemAtIndexPath indexPath: NSIndexPath) {
if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? CustomCell{
cell.imgView.startAnimating()
}
}
When you select the cell, the image view looks to its highlightedAnimationImages, not its animationImages. You didn't set the highlightedAnimationImages so you see nothing.
Here's a screencast showing that this can work. The cell is selected when the background is gray (that is its selectedBackgroundView) but the animation continues:
In case anyone else encounters this nasty bug and the above solutions don't help – try calling imageView.stopAnimating() in your cell's prepareForReuse() function.
Swift 4 version of Solution 2 from #Sebastian.
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) as? CustomCell {
cell.imgView.startAnimating()
}
}
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) as? CustomCell {
cell.imgView.startAnimating()
}
}
I had the same problem, but i did not get the "didDeselectItemAtIndexPath" to work, so my solution to the problem was just to add a button with no function over the picture.
So when you touch the picture, you will touch the button instead.
The solution 1 and 2 based on Sebastian gives me an inspiration. When UITableViewCell isSelected or isHighlighted status changes, it will call setSelected:animated: or setHighlighted:animated method. So, I override the methods of custom UITableViewCell.
class DCFWFailReasonCell: UITableViewCell {
// Local flag for UIImageView animation.
fileprivate var isAnimation: Bool = false
// Setup animation images
func configure(animateImage: [UIImage], duration: TimeInterval) {
imgView.animationImages = animateImage
imgView.highlightedAnimationImages = animateImage
imgView.animationDuration = duration
imgView.animationRepeatCount = 0 //< 0 infinite
imgView.startAnimating()
// imgView has animation.
isAnimation = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
//
if (self.isAnimation) {
imgView.startAnimating()
}
}
override func setHighlighted(_ highlighted: Bool, animated: Bool) {
super.setHighlighted(highlighted, animated: animated)
if (self.isAnimation) {
imgView.startAnimating()
}
}
}
Here is my solution, works well
class MyImageView: UIImageView {
override func stopAnimating() {
super.stopAnimating()
startAnimating()
}
}