如何以编程方式将垂直条添加到UITableViewCell

时间:2018-05-05 17:40:13

标签: ios swift uitableview

我正在尝试在UITableView中的每个项目旁边添加彩色竖条,但不确定是否有正确且最有效的方法来实现此目的。是否可以重复使用相同的UITableViewCell以不同方式为条形图着色?物品D有3个垂直条,物品F& G有2个垂直彩色条,我是否需要创建不同的自定义UITableViewCell?是否可以使用而不是UIImageView?使用仅用于纯色的图像效果似乎非常低效。如何使用Swift 4.0以编程方式完成此操作?我已经看过了这个:

但这并没有解决问题。

我也在寻找满足以下条件:

  1. 项目A,B,C,E& H的宽度为20,高度为UITableViewCell
  2. 项目D的宽度为20,高度为UITableViewCell。每个彩色垂直条都是4宽,包括每个彩色条之间的白条。
  3. 项目F& G的宽度为20,高度为UITableViewCell。每个彩色垂直条为8宽,中间有4个,背景为白色。
  4. 查看控制器

    import UIKit
    
    class MyViewController: UIViewController {
    
        let cellId = "cellId"
    
        lazy var tableView: UITableView = {
            let tableView = UITableView()
            tableView.delegate = self
            tableView.dataSource = self
            tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
            tableView.translatesAutoresizingMaskIntoConstraints = false
            return tableView
        }()
    
    
        var allItems = ["Item A", "Item B", "Item C", "Item D", "Item E", "Item F", "Item G", "Item H"]
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.title = "Hello World"
    
            self.tableView.register(CustomCell.self as AnyClass, forCellReuseIdentifier: "Cell")
    
    
            view.addSubview(tableView)
    
            let constraints = [
                tableView.topAnchor.constraint(equalTo: view.topAnchor),
                tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
            ]
    
            NSLayoutConstraint.activate(constraints)
        }
    }
    
    extension MyViewController: UITableViewDelegate, UITableViewDataSource {
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return allItems.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            var cell:CustomCell? = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? CustomCell
    
            if cell == nil {
                cell = CustomCell(style: UITableViewCellStyle.default, reuseIdentifier: "Cell")
            }
    
            cell?.textLabel?.text = allItems[indexPath.row]
    
            return cell!
        }
    }
    

    自定义UITableViewCell

    import Foundation
    import UIKit
    
    class CustomCell: UITableViewCell {
        enum BarStyle {
            case single
            case double
            case triple
        }
    
        var barStyle: BarStyle = .single {
            didSet {
                switch barStyle {
                case .single:
                    bar.style = .single
                case .double:
                    bar.style = .double
                case .triple:
                    bar.style = .triple
                }
            }
        }
        var barColor = UIColor.black {
            didSet {
                bar.color = barColor
            }
        }
    
        private let bar = VerticalBarView(frame: .zero)
    
        override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
    
            commonInit()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
    
            commonInit()
        }
    
        func commonInit() {
            self.contentView.addSubview(bar)
            // setup constraints as needed so bar is positioned and sized properly
            let constraints = [
                VerticalBarView.topAnchor.constraint(equalTo: CustomCell.topAnchor),
                VerticalBarView.bottomAnchor.constraint(equalTo: CustomCell.bottomAnchor)
            ]
    
            NSLayoutConstraint.activate(constraints)
        }
    }
    

    Plist文件(Items.plist)

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <array>
        <dict>
            <key>name</key>
            <string>Item A</string>
            <key>style</key>
            <string>single</string>
            <key>colour</key>
            <string>A90F32</string>
        </dict>
        <dict>
            <key>name</key>
            <string>Item B</string>
            <key>style</key>
            <string>single</string>
            <key>colour</key>
            <string>427B7B</string>
        </dict>
        <dict>
            <key>name</key>
            <string>Item C</string>
            <key>style</key>
            <string>single</string>
            <key>colour</key>
            <string>C9910D</string>
        </dict>
        <dict>
            <key>name</key>
            <string>Item D</string>
            <key>single</key>
            <string>triple</string>
            <key>colour</key>
            <string>CF009E</string>
        </dict>
        <dict>
            <key>name</key>
            <string>Item E</string>
            <key>style</key>
            <string>single</string>
            <key>colour</key>
            <string>003CA6</string>
        </dict>
        <dict>
            <key>name</key>
            <string>Item F</string>
            <key>style</key>
            <string>double</string>
            <key>colour</key>
            <string>704B1C</string>
        </dict>
        <dict>
            <key>name</key>
            <string>Item G</string>
            <key>style</key>
            <string>double</string>
            <key>colour</key>
            <string>6EC4E8</string>
        </dict>
        <dict>
            <key>name</key>
            <string>Item H</string>
            <key>style</key>
            <string>single</string>
            <key>colour</key>
            <string>95BF32</string>
        </dict>
    </array>
    </plist>
    

    Extensions.swift

    import Foundation
    import UIKit
    
    extension UIColor {
    
        static let colorRed = UIColor().colorFromHex("A90F32")
        static let colorTeal = UIColor().colorFromHex("427B7B")
        static let colorGold = UIColor().colorFromHex("C9910D")
        static let colorMagenta = UIColor().colorFromHex("CF009E")
        static let colorNavy = UIColor().colorFromHex("003CA6")
        static let colorBrown = UIColor().colorFromHex("704B1C")
        static let colorLightBlue = UIColor().colorFromHex("6EC4E8")
        static let colorGreen = UIColor().colorFromHex("95BF32")
    
        func colorFromHex(_ hex : String) -> UIColor {
            var hexString = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
    
            if hexString.hasPrefix("#") {
                hexString.remove(at: hexString.startIndex)
            }
    
            if hexString.count != 6 {
                return UIColor.black
            }
    
            var rgb : UInt32 = 0
            Scanner(string: hexString).scanHexInt32(&rgb)
    
            return UIColor.init(red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0,
                                green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0,
                                blue: CGFloat(rgb & 0x0000FF) / 255.0,
                                alpha: 1.0)
        }
    }
    

    Items.swift(包含struct)

    import Foundation    
    
    struct mainItem {
        var title: String
        var style: String
        var color: String
    }
    
    var itemA = mainItem(title: "Item A", style: "single", color: "A90F32")
    var itemB = mainItem(title: "Item B", style: "single", color: "427B7B")
    var itemC = mainItem(title: "Item C", style: "single", color: "C9910D")
    var itemD = mainItem(title: "Item D", style: "triple", color: "CF009E")
    var itemE = mainItem(title: "Item E", style: "single", color: "003CA6")
    var itemF = mainItem(title: "Item F", style: "double", color: "704B1C")
    var itemG = mainItem(title: "Item G", style: "double", color: "6EC4E8")
    var itemH = mainItem(title: "Item H", style: "single", color: "95BF32")
    

    当前结果

    enter image description here

    预期结果

    enter image description here

    enter image description here

    rmaddy的建议 enter image description here enter image description here

1 个答案:

答案 0 :(得分:4)

有很多部分可以将其分解。

首先,您需要一种方法来创建垂直条。你可以使用图像,但我建议创建一个定义两个属性的自定义UIView:样式(实心,两个条,三个条)和颜色。为样式定义enum。实施draw以根据需要绘制彩色条。

让自定义视图生效后,请实施CustomCell以将此自定义视图的实例添加到其contentView的左端。为条形样式和颜色添加CustomCell类的属性。设置这些属性应更新自定义栏视图上的相应属性。

更新表视图控制器中的数据模型,以包含每行的颜色和样式。

更新cellForRowAt以设置CustomCell的标题,栏样式和条形颜色。

以下是实现条形图的一种方法:

class VerticalBarView: UIView {
    enum Style {
        case single
        case double
        case triple
    }

    var style: Style = .single {
        didSet {
            setNeedsDisplay()
        }
    }
    var color = UIColor.black {
        didSet {
            setNeedsDisplay()
        }
    }

    override func draw(_ rect: CGRect) {
        (backgroundColor ?? .white).set()
        let bg = UIBezierPath(rect: bounds)
        bg.fill()

        color.set()

        switch style {
        case .single:
            let path = UIBezierPath(rect: bounds)
            path.fill()
        case .double:
            let left = CGRect(x: 0, y: 0, width: bounds.width / 2 - 2, height: bounds.height)
            var right = left
            right.origin.x = right.width + 4
            let pathLeft = UIBezierPath(rect: left)
            pathLeft.fill()
            let pathRight = UIBezierPath(rect: right)
            pathRight.fill()
        case .triple:
            let width = (bounds.width - 8) / 3
            var left: CGFloat = 0
            for _ in 0..<3 {
                let rect = CGRect(x: left, y: 0, width: width, height: bounds.height)
                let path = UIBezierPath(rect: rect)
                path.fill()
                left += width + 4
            }
        }
    }
}

// Test code
let view = VerticalBarView(frame: CGRect(x: 0, y: 0, width: 20, height: 44))
view.style = .triple
view.color = UIColor.purple

以下是CustomCell的粗略实现:

class CustomCell: UITableViewCell {
    enum BarStyle {
        case single
        case double
        case triple
    }

    var barStyle: BarStyle = .single {
        didSet {
            switch barStyle {
            case .single:
                bar.style = .single
            case .double:
                bar.style = .double
            case .triple:
                bar.style = .triple
            }
        }
    }
    var barColor = UIColor.black {
        didSet {
            bar.color = barColor
        }
    }

    private let bar = VerticalBarView(frame: .zero)

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        commonInit()
    }

    func commonInit() {
        self.contentView.addSubview(bar)

        let constraints = [
            bar.topAnchor.constraint(equalTo: self.contentView.topAnchor),
            bar.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor),
            bar.leftAnchor.constraint(equalTo: self.contentView.leftAnchor),
            bar.widthAnchor.constraint(equalToConstant: 20)
        ]
        NSLayoutConstraint.activate(constraints)
    }
}

您的cellForRowAt变成了:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell

    cell.textLabel?.text = allItems[indexPath.row].title
    cell.barStyle = allItems[indexPath.row].style
    cell.barColor = allItems[indexPath.row].color

    return cell
}

最后一段代码假设您已将数据模型更新为struct数组,其中struct包含标题,样式和颜色。