簡體   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