Как программно добавить вертикальную черту в UITableViewCell - PullRequest
0 голосов
/ 05 мая 2018

Я пытаюсь добавить цветную вертикальную полосу рядом с каждым элементом в UITableView, но не уверен в правильном и наиболее эффективном способе достижения этого. Можно ли повторно использовать один и тот же UITableViewCell, чтобы по-разному раскрасить полосу? Поскольку у элемента D есть 3 вертикальные полосы, а у элементов F & G есть две вертикальные цветные полосы, мне нужно будет создать другой пользовательский 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 с белым фоном.

Просмотр контроллера

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 file (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 (содержит структуру)

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

предложение Рмадди enter image description here enter image description here

1 Ответ

0 голосов
/ 05 мая 2018

В этом есть много частей, поэтому разбейте их на части.

Для начала вам нужен способ создать вертикальную черту. Вы можете использовать изображения, но я бы предложил создать пользовательский 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
}

В этом последнем фрагменте кода предполагается, что вы обновили модель данных как массив структур, в котором структура содержит заголовок, стиль и цвет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...