UIImageView 动画在 UICollectionViewCell 中不能正常工作
UIImageView animated doesn't work properly inside UICollectionViewCell
我想在 UICollectionViewCell
中添加一个 UIImageView
动画,所以我想出了这个代码:
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: [=10=])!}
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)
}
}
这是我的 MainViewController,以编程方式添加了 CollectionView
。
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)
}
}
这是我的习惯 UICollectionViewCell
UIImageView
我的问题是当您点击一个单元格时 UIImageView
消失了。为了解决这个问题,我开始寻找另一种 UICoolectionView
delegate 方法。然后我尝试使用 shouldHighlightItemAtIndexPath
,但是如果我使用此方法返回 false 动画工作正常但集合视图停止响应 didSelectItemAtIndexPath
.
这是一个 github 存储库,其中包含显示问题的代码:https://github.com/gazolla/ImageAnimation(更新了解决方案)
解决方案:
在 matt 的帮助下,我对代码进行了以下更改:
1) 添加图像数组到 highlightedAnimationImages
属性
let animationArray = ["1","2","3","4","5", "6","7","8"].map{UIImage(named: [=12=])!}
cell.imgView.highlightedAnimationImages = animationArray
2) 取消选择单元格时重新启动动画
func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? CustomCell{
cell.imgView.startAnimating()
}
}
3) 选择单元格时重新启动动画
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! CustomCell
cell.imgView.startAnimating()
//...
}
解决方案 2:
经过一些测试,我发现当你点击并按住时,一个单元格UIImageView
又消失了,所以我们必须用另外两种方法重新启动动画:
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()
}
}
当您 select 单元格时,图像视图查看它的 highlightedAnimationImages
,而不是 animationImages
。您没有设置 highlightedAnimationImages
,所以您什么也看不到。
这是一个截屏视频,显示它可以工作。当背景为灰色(即它的 selectedBackgroundView
)时单元格被 select 编辑,但动画继续:
如果其他人遇到这个讨厌的错误并且上述解决方案没有帮助 - 尝试在您的单元格的 prepareForReuse()
函数中调用 imageView.stopAnimating()
。
Swift 来自@Sebastian 的解决方案 2 的 4 版本。
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()
}
}
我遇到了同样的问题,但是我没有让 "didDeselectItemAtIndexPath" 工作,所以我解决这个问题的方法只是在图片上添加一个没有功能的按钮。
所以当你触摸图片时,你会触摸到按钮。
给了我灵感。当 UITableViewCell isSelected
或 isHighlighted
状态改变时,它会调用 setSelected:animated:
或 setHighlighted:animated
方法。所以,我重写了自定义 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()
}
}
}
这是我的解决方案,效果很好
class MyImageView: UIImageView {
override func stopAnimating() {
super.stopAnimating()
startAnimating()
}
}
我想在 UICollectionViewCell
中添加一个 UIImageView
动画,所以我想出了这个代码:
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: [=10=])!}
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)
}
}
这是我的 MainViewController,以编程方式添加了 CollectionView
。
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)
}
}
这是我的习惯 UICollectionViewCell
UIImageView
我的问题是当您点击一个单元格时 UIImageView
消失了。为了解决这个问题,我开始寻找另一种 UICoolectionView
delegate 方法。然后我尝试使用 shouldHighlightItemAtIndexPath
,但是如果我使用此方法返回 false 动画工作正常但集合视图停止响应 didSelectItemAtIndexPath
.
这是一个 github 存储库,其中包含显示问题的代码:https://github.com/gazolla/ImageAnimation(更新了解决方案)
解决方案:
在 matt 的帮助下,我对代码进行了以下更改:
1) 添加图像数组到 highlightedAnimationImages
属性
let animationArray = ["1","2","3","4","5", "6","7","8"].map{UIImage(named: [=12=])!}
cell.imgView.highlightedAnimationImages = animationArray
2) 取消选择单元格时重新启动动画
func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? CustomCell{
cell.imgView.startAnimating()
}
}
3) 选择单元格时重新启动动画
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! CustomCell
cell.imgView.startAnimating()
//...
}
解决方案 2:
经过一些测试,我发现当你点击并按住时,一个单元格UIImageView
又消失了,所以我们必须用另外两种方法重新启动动画:
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()
}
}
当您 select 单元格时,图像视图查看它的 highlightedAnimationImages
,而不是 animationImages
。您没有设置 highlightedAnimationImages
,所以您什么也看不到。
这是一个截屏视频,显示它可以工作。当背景为灰色(即它的 selectedBackgroundView
)时单元格被 select 编辑,但动画继续:
如果其他人遇到这个讨厌的错误并且上述解决方案没有帮助 - 尝试在您的单元格的 prepareForReuse()
函数中调用 imageView.stopAnimating()
。
Swift 来自@Sebastian 的解决方案 2 的 4 版本。
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()
}
}
我遇到了同样的问题,但是我没有让 "didDeselectItemAtIndexPath" 工作,所以我解决这个问题的方法只是在图片上添加一个没有功能的按钮。
所以当你触摸图片时,你会触摸到按钮。
isSelected
或 isHighlighted
状态改变时,它会调用 setSelected:animated:
或 setHighlighted:animated
方法。所以,我重写了自定义 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()
}
}
}
这是我的解决方案,效果很好
class MyImageView: UIImageView {
override func stopAnimating() {
super.stopAnimating()
startAnimating()
}
}