[英]Can I add an action to a customCell in a UICollectionView?
首先,我有幾個帶有 @IBAction 的 UIButtons 來在點擊時播放聲音。 因為我在不同的 iPhone 上遇到了一些限制問題,所以我決定使用帶有 CustomCells 的 UICollectionView。 現在我開始工作了,我想設置 CustomCells 以在點擊時播放聲音。 所以我想我必須在自定義單元格上設置類似“動作”的東西來播放聲音。 我確實有一種“某種動作”可以打印出用戶點擊了一個自定義單元格;
print("tapped tag > ", self.tag)
我在 UIButton 上使用的原始 @IBAction 是:
@IBAction func sound2(_ sender: UIButton) {
sound2.play()
同樣,我“認為”我需要為 CustomCell 設置一種操作來播放聲音? 而且我“認為”我需要在某個地方聲明什么聲音可以與 self.tag 一起播放? 所以每個 customCell 都會播放不同的聲音..
唯一的問題,(rookieAlert) 我不知道從哪里開始:( 但我想學習!有人能指出我正確的方向或提供一些信息嗎?
這是項目的完整代碼,使事情更清楚:
import UIKit
import AVFoundation
class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
var countries = [UIImage(named:"c1"),UIImage(named:"c2"),UIImage(named:"c3"),UIImage(named:"c4"),UIImage(named:"c5"),UIImage(named:"c6"),UIImage(named:"c7"),UIImage(named:"c8"),UIImage(named:"c9"),UIImage(named:"c10")]
@IBOutlet weak var soundsCollectionView: UICollectionView!
lazy var cv: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 100, height: 100)
var cc = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
cc.translatesAutoresizingMaskIntoConstraints = false
cc.register(CustomCell.self, forCellWithReuseIdentifier: "CustomCell")
cc.delegate = self
cc.dataSource = self
cc.backgroundColor = .black
return cc
}()
let sounds = ["sound1", "sound2", "sound3", "sound4", "sound5"]
var sound1 = AVAudioPlayer()
var sound2 = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(cv)
cv.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
cv.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
cv.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
cv.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
// Setting up sound1
do {
sound1 = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "sound1", ofType: "mp3")!))
sound1.prepareToPlay()
} catch {
print(error)
}
// Setting up sound2
do {
sound2 = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "sound2", ofType: "mp3")!))
sound2.prepareToPlay()
} catch {
print(error)
}
}
@IBAction func sound2(_ sender: UIButton) {
if sound2.isPlaying {
sound2.stop()
sound1.stop()
sender.setImage(UIImage(named: "sound1_off.jpg"), for: .normal)
} else {
sound2.play()
sender.setImage(UIImage(named: "sound1_on.jpg"), for: .normal)
}
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.centerImageView.image = countries[indexPath.row]
cell.tag = indexPath.row
cell.backgroundColor = UIColor.green
return cell
}
//define constant value as per your requirement and declare this variables globally
let inset: CGFloat = 10 //define as per your requirement
let minimumInteritemSpacing: CGFloat = 10 //define as per your requirement
let cellsPerRow = 3
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let marginsAndInsets = inset * 2 + collectionView.safeAreaInsets.left + collectionView.safeAreaInsets.right + minimumInteritemSpacing * CGFloat(cellsPerRow - 1)
let itemWidth = ((collectionView.bounds.size.width - marginsAndInsets) / CGFloat(cellsPerRow)).rounded(.down)
return .init(width: itemWidth, height: itemWidth)
}
}
class CustomCell: UICollectionViewCell {
lazy var centerImageView: UIImageView = {
var img = UIImageView()
img.translatesAutoresizingMaskIntoConstraints = false
img.clipsToBounds = true
img.isUserInteractionEnabled = true
img.contentMode = .scaleAspectFill
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handler(_:)))
tapGesture.numberOfTapsRequired = 1
img.addGestureRecognizer(tapGesture)
return img
}()
@objc private func handler(_ sender: UITapGestureRecognizer) {
print("tapped tag > ", self.tag)
}
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(centerImageView)
centerImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
centerImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
centerImageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
centerImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
這是所有單元格中相同的聲音:嘗試從自定義單元格中的 centerImage 中刪除手勢,然后在 cellForItemAt 中添加手勢並調用如下函數:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.centerImageView.image = countries[indexPath.row]
cell.backgroundColor = UIColor.green
let gesture = UITapGestureRecognizer(target: self, action: #selector(playCellSound))
cell.centerImageView.addGestureRecognizer(gesture)
return cell
}
之后寫在cellForItemAt下面的函數:
@objc func playCellSound() {
sound2.play()
print("play sound...")
}
對於細胞中的不同聲音:
聲音的數量必須等於國家的數量:
let sounds = ["sound1", "sound2", "sound3", "sound4", "sound5", "sound6", "sound7", "sound8", "sound9", "sound10"]
之后聲明你的聲音是這樣的:
var sound1 = AVAudioPlayer()
var sound2 = AVAudioPlayer()
var sound3 = AVAudioPlayer()
var sound4 = AVAudioPlayer()
var sound5 = AVAudioPlayer()
var sound6 = AVAudioPlayer()
var sound7 = AVAudioPlayer()
var sound8 = AVAudioPlayer()
var sound9 = AVAudioPlayer()
var sound10 = AVAudioPlayer()
設置其他聲音,如聲音 1 和聲音 2
現在這是你的 cellForItemAt:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.centerImageView.image = countries[indexPath.row]
cell.backgroundColor = UIColor.green
return cell
}
像這樣設置 numberOfItemsInSection:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return countries.count // dynamic number of items based on your countries array
}
實現方法 didiSelectItemAt
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let s = sounds[indexPath.item]
switch s {
case "sound1":
sound1.play()
print("s1")
case "sound2":
sound2.play()
print("s2")
case "sound3":
sound3.play()
print("s3")
case "sound4":
sound4.play()
print("s4")
case "sound5":
sound5.play()
print("s5")
case "sound6":
sound6.play()
print("s6")
case "sound7":
sound7.play()
print("s7")
case "sound8":
sound8.play()
print("s8")
case "sound9":
sound9.play()
print("s9")
case "sound10":
sound10.play()
print("s10")
default:
break
}
}
在您的自定義單元格中刪除 centerImageView 的點擊手勢:
class CustomCell: UICollectionViewCell {
lazy var centerImageView: UIImageView = {
var img = UIImageView()
img.contentMode = .scaleAspectFill
img.clipsToBounds = true
img.isUserInteractionEnabled = true
img.translatesAutoresizingMaskIntoConstraints = false
return img
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(centerImageView)
centerImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
centerImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
centerImageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
centerImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
對於系統聲音:
像這樣替換你的 var 聲明:
var sound1: SystemSoundID = 1016
var sound2: SystemSoundID = 1322
var sound3: SystemSoundID = 1110
var sound4: SystemSoundID = 1070
var sound5: SystemSoundID = 1109
var sound6: SystemSoundID = 1117
var sound7: SystemSoundID = 1106
var sound8: SystemSoundID = 1118
var sound9: SystemSoundID = 1256
var sound10: SystemSoundID = 1116
刪除設置聲音 1、2 等,並將 didSelectItemAt 中的開關盒替換為:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let s = sounds[indexPath.item]
switch s {
case "sound1":
AudioServicesPlaySystemSound (sound1)
print("s1")
case "sound2":
AudioServicesPlaySystemSound(sound2)
print("s2")
case "sound3":
AudioServicesPlaySystemSound(sound3)
print("s3")
case "sound4":
AudioServicesPlaySystemSound(sound4)
print("s4")
case "sound5":
AudioServicesPlaySystemSound(sound5)
print("s5")
case "sound6":
AudioServicesPlaySystemSound(sound6)
print("s6")
case "sound7":
AudioServicesPlaySystemSound(sound7)
print("s7")
case "sound8":
AudioServicesPlaySystemSound(sound8)
print("s8")
case "sound9":
AudioServicesPlaySystemSound(sound9)
print("s9")
case "sound10":
AudioServicesPlaySystemSound(sound10)
print("s10")
default:
break
}
}
}
這不是最好的方法,但它工作得很好,它會讓你了解它是如何工作的並幫助你學習
我相信您正在尋找的是didSelectItemAt
函數的實現。 您可以通過將其他集合視圖函數(如cellForItemAt
放在一起來cellForItemAt
。 然后,確保所需的聲音與您的數據源密切相關。 這意味着您可以通過indexPath.item
訪問您想要的聲音,這是一種識別被點擊的特定單元格的方法。
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// Use indexPath.item to determine what sound to play
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.