【问题标题】:How to add vertical bar to UITableViewCell programmatically如何以编程方式将竖线添加到 UITableViewCell
【发布时间】:2023-03-03 08:59:24
【问题描述】:

我正在尝试在 UITableView 中的每个项目旁边添加一个彩色垂直条,但不确定实现此目的的正确和最有效的方法。是否可以重复使用相同的UITableViewCell 来为条形着色?由于项目 D 有 3 个垂直条,项目 F 和 G 有 2 个垂直彩色条,我是否需要创建不同的自定义 UITableViewCell?是否可以使用a 而不是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 文件 (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")

当前结果

预期结果

rmaddy 的建议

【问题讨论】:

  • 为什么要以编程方式执行此操作?只需将图像视图添加到情节提要中的CustomCell,将插座添加到CustomCell 类,然后在tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) 中将图像更新为您想要的任何内容
  • 检查您的 plist 文件。有两个style 错误。
  • 为什么您在不久前编辑问题时不赞成我的回答?为什么永远不接受答案?缺少什么?
  • @rmaddy 您的建议返回 3 个错误。请参阅上面的最新屏幕截图。 Value of type 'String' has no member 'title'/'style'/'color'
  • 对。预计您会做一些工作,而不是盲目地复制和粘贴所有内容。每次我充实越来越多的答案时,你确实不断改变你的要求。我认为错误来自我的cellForRowAt,这在很大程度上留给你充实。我在cellForRow 中输入的代码可作为您的粗略指导。

标签: ios swift uitableview


【解决方案1】:

这有很多部分,所以分解一下。

首先,您需要一种创建垂直条的方法。您可以使用图像,但我建议创建一个自定义 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
}

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

【讨论】:

  • 如果您不想使用图像视图,这是一个很好的例子?。如果您允许用户设置自定义颜色,那会非常酷。
  • @AaronBrager 请注意color 属性。
  • 简单直接的解决方案,赞。如果应该只在cellForRow 中设置样式,则不需要属性观察器。
  • @vadian cellForRowAt 不会知道VerticalBarViewCustomCell 将有自己的样式和颜色属性,这些属性只会委托给它的 VerticalBarView 实例。
  • 我假设视图连接到自定义单元格中的插座,并且样式设置在 cellForRowcell.verticalBarView.style = ... 但我忽略了一切都是在代码中实现的。
猜你喜欢
  • 2023-03-17
  • 2019-02-11
  • 1970-01-01
  • 2023-04-08
  • 2019-08-11
  • 2011-08-22
  • 2013-12-30
  • 1970-01-01
  • 2013-03-09
相关资源
最近更新 更多