简体   繁体   English

我可以向 UICollectionView 中的 customCell 添加操作吗?

[英]Can I add an action to a customCell in a UICollectionView?

First I had a couple of UIButtons with a @IBAction to play a sound when tapped.首先,我有几个带有 @IBAction 的 UIButtons 来在点击时播放声音。 Because I had some problems with constraints on different iPhones I decided to go for a UICollectionView with CustomCells.因为我在不同的 iPhone 上遇到了一些限制问题,所以我决定使用带有 CustomCells 的 UICollectionView。 Now I got this working I want to setup the CustomCells to play a sound when tapped.现在我开始工作了,我想设置 CustomCells 以在点击时播放声音。 So I think I will have to setup something like an 'Action' on the custom cells for playing a sound.所以我想我必须在自定义单元格上设置类似“动作”的东西来播放声音。 I do have a 'sort of action' that prints out that the user tapped a custom cell like;我确实有一种“某种动作”可以打印出用户点击了一个自定义单元格;

print("tapped tag > ", self.tag)

The original @IBAction I used on a UIButton was:我在 UIButton 上使用的原始 @IBAction 是:

@IBAction func sound2(_ sender: UIButton) {
sound2.play()

Again, I 'think' I need to setup a sort of action to the CustomCell for playing a sound?同样,我“认为”我需要为 CustomCell 设置一种操作来播放声音? And I 'think' I need to declare somewhere what sound to play along with the self.tag?而且我“认为”我需要在某个地方声明什么声音可以与 self.tag 一起播放? So each customCell will play a different sound..所以每个 customCell 都会播放不同的声音..

The only problem, (rookieAlert) I don't know where to start :( But I want to learn! Can somebody point me into the right direction or provide me with some information?唯一的问题,(rookieAlert) 我不知道从哪里开始:( 但我想学习!有人能指出我正确的方向或提供一些信息吗?

Here is the full code of the project to make things more clear:这是项目的完整代码,使事情更清楚:

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")
    }
}

This is for same sound in all cell: try to delete gesture from your centerImage in custom cell, after that add the gesture in cellForItemAt and call the function like this:这是所有单元格中相同的声音:尝试从自定义单元格中的 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
}

after that write the func below cellForItemAt:之后写在cellForItemAt下面的函数:

@objc func playCellSound() {
    sound2.play()
    print("play sound...")
}

FOR DIFFERENT SOUND IN CELLS:对于细胞中的不同声音:

the number of sounds must be equal the number of countries:声音的数量必须等于国家的数量:

let sounds = ["sound1", "sound2", "sound3", "sound4", "sound5", "sound6", "sound7", "sound8", "sound9", "sound10"]

after that declare your sounds like this:之后声明你的声音是这样的:

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()

set the other sound like sound 1 and sound 2设置其他声音,如声音 1 和声音 2

now this is your cellForItemAt:现在这是你的 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
}

set numberOfItemsInSection like this:像这样设置 numberOfItemsInSection:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return countries.count // dynamic number of items based on your countries array
}

implement the method didiSelectItemAt实现方法 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
    }
}

in your custom cell delete tap gesture for centerImageView:在您的自定义单元格中删除 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")
 }
}

FOR SYSTEM SOUNDS:对于系统声音:

replace your var declaration like this:像这样替换你的 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

deleting setting up sound 1, 2 etc. and replace the switch case in didSelectItemAt with this:删除设置声音 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
    }
  }
}

this is not the best way but it work fine, it will make you understand how it works and help you to learn这不是最好的方法,但它工作得很好,它会让你了解它是如何工作的并帮助你学习

I believe what you are looking for is implementation of the didSelectItemAt function.我相信您正在寻找的是didSelectItemAt函数的实现。 You can implement like so by putting with your other collection view functions like cellForItemAt .您可以通过将其他集合视图函数(如cellForItemAt放在一起来cellForItemAt Then, make sure the required sound is closely linked with your data source.然后,确保所需的声音与您的数据源密切相关。 Meaning you can access the sound you want via indexPath.item , which is a way of identifying the specific cell that got tapped.这意味着您可以通过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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM