簡體   English   中英

如何使用自定義 UIViews(和內部轉換)重新加載自定義 UICollectionViewCell

[英]How to reload custom UICollectionViewCell`s with custom UIViews (and transitions inside)

大家好,大家好

我正在根據 indexPath 行在我的自定義單元格中重新加載數據方面尋找一些提示。

上下文:

  • 我有一個教程幻燈片,我正在使用UICollectionView 在這個視圖中,我插入自定義UICollectionViewCell s,對於每個indexPath.row不同的自定義一個(所以我為UICollectionView注冊了多個筆尖)。

  • 在基於cellForItemAt indexPath委托方法cellForItemAt indexPath我出列我想要的特定自定義單元格

  • 教程幻燈片有一些按鈕,您可以使用這些按鈕在特定單元格之間導航(順便說一下,單元格占據了用戶屏幕的大部分),因此您可以像 Next 或 Back 一樣導航。

  • 自定義類中的每個單元格都定義了一些轉換。 因此,例如,單元格編號 1 以一些自定義元素開頭,然后在大約一秒后轉換為另一組元素。 所以我正在創建類似動畫的東西。 這些轉換是通過DispatchQueue.main.asyncAfter執行的,所以我讓用戶閱讀我想要的第一個屏幕,然后是第二個。 然后用戶單擊 Next 按鈕並轉到另一個indexPath.row有時在下一個“屏幕”中進行另一個轉換

  • 所以我的目的是當用戶例如通過單擊 Next/Back 在單元格 ( indexPath.row /s) 之間導航時擁有“清晰”的默認視圖,所以當他從 Screen2 轉到 Screen1 時,我希望他從開始並再次看到過渡。 現在它在我過渡到的最后一個屏幕結束。

我的實際問題:

那么有什么方法可以使用當前設計刷新單元格,還是應該更改我構建集合視圖的方式?

請參閱下面的一些示例代碼片段。

1. VC 與我的 UICollectionView

class IncomingInstructionsVC: UIViewController {

@IBOutlet weak var btnBack: UIButton!
@IBOutlet weak var btnNext: UIButton!
@IBOutlet weak var collectionView: UICollectionView!


override func viewDidLoad() {
    super.viewDidLoad()
    collectionView.register(Screen1.nib, forCellWithReuseIdentifier: "Screen1ID")
    collectionView.register(Screen2.nib, forCellWithReuseIdentifier: "Screen2ID")
    collectionView.register(Screen3.nib, forCellWithReuseIdentifier: "Screen3ID")
    collectionView.register(Screen4.nib, forCellWithReuseIdentifier: "Screen4ID")
    collectionView.register(Screen5.nib, forCellWithReuseIdentifier: "Screen5ID")
    collectionView.register(Screen6.nib, forCellWithReuseIdentifier: "Screen6ID")
    collectionView.dataSource = self
    collectionView.delegate = self
    collectionView.isPagingEnabled = false

}

2. 用於 UICollectionViewCell/s 之間導航的 IBActions

@IBAction func btnNextTapped(_ sender: UIButton) {
    let visibleItems: NSArray = self.collectionView.indexPathsForVisibleItems as NSArray
    
    var minItem: NSIndexPath = visibleItems.object(at: 0) as! NSIndexPath
    for itr in visibleItems {
        if minItem.row > (itr as AnyObject).row {
            minItem = itr as! NSIndexPath
        }
    }
    let nextItem = IndexPath(row: minItem.row + 1, section: 0)
    self.collectionView.scrollToItem(at: nextItem as IndexPath, at: .left, animated: false)

}
@IBAction func btnBackTapped(_ sender: UIButton) {
    let visibleItems: NSArray = self.collectionView.indexPathsForVisibleItems as NSArray
    
    var minItem: NSIndexPath = visibleItems.object(at: 0) as! NSIndexPath
    for itr in visibleItems {
        
        if minItem.row > (itr as AnyObject).row {
            minItem = itr as! NSIndexPath
        }
    }
    let nextItem = IndexPath(row: minItem.row - 1, section: 0)
    self.collectionView.scrollToItem(at: nextItem as IndexPath, at: .left, animated: false)
}

3.委托方法cellForItemAt indexPath:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    var cell = UICollectionViewCell()
    self.pageControl.currentPage = indexPath.row
    
    switch indexPath.row {
    case 0:
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Screen1ID", for: indexPath) as! Screen1
    case 1:
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Screen2ID", for: indexPath) as! Screen2
    case 2:
        cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Screen3ID", for: indexPath) as! Screen3
.
.
.
continues to the end of my tutorial
.
.
.
    }
    return cell
}

4. 自定義 Cell Class 與DispatchQueue.main.asyncAfter邏輯

.
.
.
Some IBOutlets here....
.
.
.

override func awakeFromNib() {
        super.awakeFromNib()
        commonInit()
    }
    
    func commonInit() {
        greyBackground.layer.cornerRadius = 10
        transition1.layer.cornerRadius = 10
        transition2.layer.cornerRadius = 10
        
        self.nameIncomingLabel.text = NSLocalizedString("name_inc_head", comment: "")
        self.mobileLabel.text = NSLocalizedString("mobile", comment: "")
        self.declineImageView.image = UIImage(named: "Reject")
        self.declineLabel.text = NSLocalizedString("Decline", comment: "")
        
        self.acceptImageView.image = UIImage(named: "Accept")
        self.acceptLabel.text = NSLocalizedString("accept", comment: "")
        
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [self] in
            //transition to "Accept Call" command
            UIView.transition(with: transition1, duration: 1, options: .transitionCrossDissolve, animations: {
                transition1.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.9)
                
                transition1AcceptImage.image = UIImage(named: "Accept")
                transition1Label.font = UIFont.systemFont(ofSize: 21, weight: .semibold)
                transition1Label.text = NSLocalizedString("answer_incoming_call", comment: "")
                
                //transition to calling screen with icons
                DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [self] in
                    UIView.transition(with: transition2, duration: 0.5, options: .transitionCrossDissolve, animations: {
                        transition2.backgroundColor = #colorLiteral(red: 0.3019607843, green: 0.3019607843, blue: 0.3019607843, alpha: 1)
                        nameIncomingLabelTransition2.text = NSLocalizedString("name_inc_head", comment: "")


....it is continuing with the closing curly braces down below...

出列可重用單元格的目的是避免多次創建可以由容器視圖(如表視圖或集合視圖)更快地重用的單元格。 容器視圖緩存了許多離開屏幕的單元格,因此一旦它再次可見,您就可以返回該單元格。 由於您的動畫是在commonInit中實現的——它只能由awakeFromNib調用——你只能看到它們一次,因為視圖只加載到內存中一次。

您需要在單元格出隊后手動調用commonInit ,而不是通過awakeFromNib調用它。 或者更好:將唯一一次的東西與動畫/內容初始化部分分開,並從awakeFromNib調用第一個,一旦視圖出列,則調用后者。

這甚至更好,因為甚至在視圖可見之前就調用了awakeFromNib ,因此您甚至不知道它何時顯示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM