繁体   English   中英

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

[英]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.

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