如何根据设备主题更改collectionview单元格颜色(按照我的配色方案)

Posted

技术标签:

【中文标题】如何根据设备主题更改collectionview单元格颜色(按照我的配色方案)【英文标题】:How to change collectionview cells color based on device theme (following my color scheme) 【发布时间】:2020-10-28 15:27:08 【问题描述】:

概述:

我正在使用集合视图构建键盘扩展。我希望单元格根据设备主题(亮/暗)更改颜色。目前,当我为我的 collectionview 单元格设置配色方案时,它们不起作用。我正在用“///”注释标记我的代码有问题的部分。

资源:

我找到了this RayWenderlich project,我喜欢他们处理颜色变化的方式,所以我复制了它。

我的代码:

我有 3 个课程:

    键盘视图控制器 包含键盘按钮的自定义视图 自定义 collectionview 单元格

CollectionView 单元格

class KeyboardKeys: UICollectionViewCell 
    
    var defaultColor = UIColor.white
    var highlighColor = UIColor.lightGray.withAlphaComponent(0.6)
    
    let label: UILabel = 
        let iv = UILabel()
        iv.translatesAutoresizingMaskIntoConstraints = false
        iv.contentMode =  .scaleAspectFit
        iv.font = UIFont.systemFont(ofSize: 20)
        iv.clipsToBounds = true
        iv.numberOfLines = 1
        iv.textAlignment = .center
        
        return iv
    ()

    override init(frame: CGRect) 
        super.init(frame: .zero)
        commonInit()
    
    
    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        commonInit()
    
    
    func commonInit() 
        contentView.addSubview(label)
        label.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
        label.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
        label.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
        label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true   
    
    
    override func layoutSubviews() 
        super.layoutSubviews()
            backgroundColor = isHighlighted ? highlighColor : defaultColor  
       

自定义视图

class lettersKeyboard: UIView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
var keyView: UICollectionView!
 let letters = ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"]
 override init(frame: CGRect) 
        super.init(frame: frame)
        commonInit()
    
    
    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        commonInit()
        
    
    
    private func commonInit()
//If you find some errors it's because this is way different in my code. This is just a regulare  collection view anyway

    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical
        
    keyView = UICollectionView(frame: CGRect(x: 0.0, y: 0.0 , width: frame.width, height: 280), collectionViewLayout: layout)
    keyView.setCollectionViewLayout(layout, animated: true)
    keyView.isScrollEnabled = false
    keyView.register(KeyboardKeys.self, forCellWithReuseIdentifier: "collectionCellId")
    keyView.delegate = self
    keyView.dataSource = self
    addSubview(keyView)


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        10
    
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = keyView.dequeueReusableCell(withReuseIdentifier: "collectionCellId", for: indexPath) as! KeyboardKeys
        cell.label.text = letters[indexPath.row]
        return cell
    
    ///I guess something is wrong here 
    func setColorScheme(_ colorScheme: ColorScheme) 
      let colorScheme = CColors(colorScheme: colorScheme)
     
      for view in subviews 
        if let cell = view as? KeyboardKeys 
            cell.tintColor = colorScheme.buttonTextColor
            cell.defaultColor = colorScheme.keysDefaultColor
            cell.highlighColor = colorScheme.keysHighlightColor
      
      
    
    


配色方案结构

enum ColorScheme 
    case dark
    case light


struct CColors 
    
    let keysDefaultColor: UIColor
    let keysHighlightColor: UIColor
    
    let buttonTextColor: UIColor
   
    
    init(colorScheme: ColorScheme) 
        switch colorScheme 
        case .light:
           
            keysDefaultColor = .systemRed
                //UIColor.white
            keysHighlightColor = UIColor.lightGray.withAlphaComponent(0.6)
         
            buttonTextColor = .black
           
        case .dark:
            
            keysDefaultColor = .systemBlue
                // UIColor.gray.withAlphaComponent(0.5)
            keysHighlightColor = UIColor.lightGray.withAlphaComponent(0.5)
            
            buttonTextColor = .white  
        
    

键盘视图控制器

class KeyboardViewController: UIInputViewController 
var letters : lettersKeyboard = 
      
        let m = lettersKeyboard(frame: .zero)
            m.translatesAutoresizingMaskIntoConstraints = false

            m.backgroundColor = .clear
            return m
        
()
override func viewDidLoad() 
        super.viewDidLoad()
 
        view.addSubview(letters)
   
        letters.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        letters.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        letters.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        letters.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

//The rest is the default inputvc stuff 

    ///Or here
    override func textDidChange(_ textInput: UITextInput?) 
        // The app has just changed the document's contents, the document context has been updated.
       
        let colorScheme:  ColorScheme
        let proxy = self.textDocumentProxy
        if proxy.keyboardAppearance == UIKeyboardAppearance.dark 
            colorScheme = .dark
         else 
            colorScheme = .light
        
        letters.setColorScheme(colorScheme)
    

问题:

我不知道我做错了什么,因为我的代码适用于除了 collectionview 单元格之外的所有内容。我想存在另一种做这些事情的方法。那么如何根据我的配色方案根据设备的主题更改我的 collectionView 单元格的颜色?

【问题讨论】:

【参考方案1】:

您确实应该重新加载集合视图,而不是试图找到作为键的子视图并更新它们。

将 colorScheme 模型传递给每个单元格,并在重新加载时设置颜色。

【讨论】:

是的,我认为@Jay 是对的。您需要重新加载集合视图(您的自定义键盘),并为简单起见将颜色作为计算属性,通过检查主题来给出结果。【参考方案2】:

一个非常善良的人帮助我找到了这个解决方案。这里的问题是我忘记了视图的层次结构。

CollectionView 单元格

 override func layoutSubviews() 
        super.layoutSubviews()
           setupBackGround()
     
func setupBackGround()
backgroundColor = isHighlighted ? highlighColor : defaultColor

键盘视图控制器


func setColorScheme(_ colorScheme: ColorScheme) 
      let colorScheme = CColors(colorScheme: colorScheme)
     
      for view in subviews 
         func setToRootView(view: UIView) 
                if let cell = view as? KeyboardKeys 
                    cell.tintColor = colorScheme.buttonTextColor
                    cell.defaultColor = colorScheme.keysDefaultColor
                    cell.highlighColor = colorScheme.keysHighlightColor
                    cell.setBackground()
                    return
                
                guard view.subviews.count > 0 else 
                    return
                
                view.subviews.forEach(setToRootView(view:))
            
            setToRootView(view: self)
        

【讨论】:

以上是关于如何根据设备主题更改collectionview单元格颜色(按照我的配色方案)的主要内容,如果未能解决你的问题,请参考以下文章

当设备旋转而不将设备锁定为纵向模式时,如何将 collectionView 的所有项目保持在适当的位置?

如何在 Flutter 中通过更改主题来更改文本颜色

CollectionView -> 根据是不是登录更改流程

根据 CollectionView 中的选择更改 ImageView

设备方向更改时如何更改 UiCollectionView 单元格大小?

如何根据主题更改状态栏/导航栏颜色/亮度?