UITableView - 行 - 多重对齐

时间:2015-06-18 16:30:48

标签: ios swift uitableview alignment

我试图使一行的内容(在UITableView中)有多个对齐方式:左,中,右。我在Stackoverflow上搜索了一个解决方案,发现了这个:Different text alignment to a row in table view。唯一的问题是该解决方案是基于ObjectiveC的,我无法转换为基于Swift的解决方案。

具体来说,我有一个表示活动用户列表的UITableView。将内容加载到表视图中工作正常,但为了便于阅读,内容(分为三种类型)需要在视觉上划分为三个不同的“部分”。我该怎么做呢?上面的解决方案在Swift中会是什么样子?提前谢谢。

代码(适用于Vive)

类声明

class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

viewDidLoad中()

self.activeIDs.delegate = self
self.activeIDs.dataSource = self
self.activeIDs.rowHeight = 25
self.activeIDs.separatorStyle = UITableViewCellSeparatorStyle.None
self.activeIDs.allowsMultipleSelection = true

的cellForRowAtIndexPath

func tableView(tableView: UITableView,
    cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
        let cell = activeIDs.dequeueReusableCellWithIdentifier("cellReuseId", forIndexPath: indexPath) as ActiveIDTableViewCell

        cell.leftLabel.text = "I go left"
        cell.middleLabel.text = "I go center"
        cell.rightLabel.text = "I go right"

        return cell
}

numberOfRowsInSection

func tableView(tableView: UITableView,
    numberOfRowsInSection section: Int) -> Int {
        return 4 //I randomly chose 4, just for example
}

ActiveIDTableViewCell.swift - 几乎已复制

import UIKit

class ActiveIDTableViewCell: UITableViewCell {

// alloc & init labels
let leftLabel = UILabel()
let middleLabel = UILabel()
let rightLabel = UILabel()

// MARK: Memory Management

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    // never forget to call super in overriden UIKit methods (almost never ;))
    super.init(style: .Default, reuseIdentifier: reuseIdentifier)

    // now let's assign these values we've set previously in storyboards
    leftLabel.textAlignment = NSTextAlignment.Left
    // you created a label, but you need to add this label as a subview of cells view.
    contentView.addSubview(leftLabel)

    middleLabel.textAlignment = NSTextAlignment.Center
    contentView.addSubview(middleLabel)

    rightLabel.textAlignment = NSTextAlignment.Right
    contentView.addSubview(rightLabel)
}

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented") //Xcode points to this line when error is thrown
}

// MARK: Layout

override func layoutSubviews() {
    super.layoutSubviews()

    // here happens all the magic which skips autolayouts. You can ofc set autolayouts from code :)
    let frame = self.contentView.bounds
    // frame was the size of the cell, but we want to set our labels at least 10px from sides of cell - so it looks nicely
    let insetFrame = CGRectInset(frame, 10.0, 10.0)
    // width of each label is width of cell / 3 (you want 3 labels next to each other) minus margins
    let labelWidth = (CGRectGetWidth(insetFrame) - 20.0) / 3.0

    // lets calculate the rects and assign frames to calculated values
    let leftLabelRect = CGRectMake(CGRectGetMinX(insetFrame), CGRectGetMinY(insetFrame), labelWidth, CGRectGetHeight(insetFrame))
    leftLabel.frame = leftLabelRect

    let middleLabelRect = CGRectMake(CGRectGetMaxX(leftLabelRect), CGRectGetMinY(insetFrame), labelWidth, CGRectGetHeight(insetFrame))
    middleLabel.frame = middleLabelRect

    let rightLabelRect = CGRectMake(CGRectGetMaxX(middleLabelRect), CGRectGetMinY(insetFrame), labelWidth, CGRectGetHeight(insetFrame))
    rightLabel.frame = rightLabelRect
}}

我已经仔细检查了故事板中是否正确设置了单元标识符和自定义类等内容。

2 个答案:

答案 0 :(得分:0)

好的,小教程如何做,请根据编程最佳实践在您的问题下查看我的评论:

包含ViewController的第一个文件:

class MyTableViewController: UITableViewController {

    // here ofc you'll have your array/dictionary of input data
    let titles = ["iOS", "Android", "Windows Phone", "Firefox OS", "Blackberry OS", "Tizen", "Windows Mobile", "Symbian", "Palm OS"]

    // this is to make sure how many rows your table should have
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return titles.count
    }

    // here you dequeue tableViewCells, so they're reusable (so your table is fast & responding
    // allocating new resources for new cell is very consuming
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell: MyTableViewCell = tableView.dequeueReusableCellWithIdentifier("cellId", forIndexPath: indexPath) as! MyTableViewCell
        // fill your data
        cell.rightLabel.text = "I'm right cell"
        cell.middleLabel.text = titles[indexPath.row]
        cell.leftLabel.text = "I'm left cell"

        return cell;
    }
}

带有单元格类的第二个文件:

class MyTableViewCell: UITableViewCell {

    @IBOutlet weak var leftLabel: UILabel!
    @IBOutlet weak var middleLabel: UILabel!
    @IBOutlet weak var rightLabel: UILabel!

}

现在如何告诉你如何处理IB:/。就个人而言,我更喜欢代码解决方案,但这是你的决定。

  1. 复制代码;)
  2. TableViewController从对象带到您的情节提要板,Identity Inspector将班级设为MyTableViewController
  3. 扩展您的单元格,使高度达到所需的值(我已设置为50),Identity Inspector将类设置为MyTableViewCell
  4. 为您的手机添加3个标签
  5. 选择所有3个标签并添加约束:
    • 等宽
    • 相等的高度
    • 垂直空间到顶部:10
    • 垂直空间到底部:10
  6. 选择左侧标签并设置:
    • 水平空间到中间标签:10
    • 左边的水平空间:10
  7. 选择正确的标签并设置:
    • 水平空间到中间标签:10
    • 水平空间到右边:10
  8. 点击右下角的三角形,然后选择Update Frames。一切都应该正确定位。
  9. 选择每个标签,在右侧面板上选择Attributes Inspector,在那里标记正确的对齐方式(左侧为标签,中间位置为中间标签,右侧为右侧标签)。
  10. 将相应的标签连接到MyTableViewCell IBOutlets
  11. 中的标签

    使用此解决方案,一切都应该可以正常工作。

答案 1 :(得分:0)

确定代码解决方案的另一个答案(因为它完全不同),而不是使用故事板:

  1. 打开项目设置,删除主界面。您希望项目从代码运行而不是使用Storyboard。
  2. 现在您必须先设置应该运行哪个控制器并设置一些UIWindow属性。
  3. 更改以下AppDelegate代码的实现。

    import UIKit
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
    
        func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // create window and set proper size of it
            self.window = UIWindow(frame: UIScreen.mainScreen().bounds) 
            self.window?.backgroundColor = UIColor.whiteColor()
            self.window?.makeKeyAndVisible()
            // assign your controller to be the 'entering' point
            self.window?.rootViewController = UINavigationController(rootViewController: MyViewController(style:UITableViewStyle.Plain)) 
    
            // start the app
            return true
        }
    }
    
    1. 您还需要在控制器中设置比使用代码更多的详细信息。
    2. 复制以下代码:

      import UIKit
      
      class MyViewController: UITableViewController {
      
          // use let to keep ID, as at least in 2 places we need this string, it's easier to maintain it in one place and omit any typos
          let cellReuseId = "cellReuseId"
          let titles = ["iOS", "Android", "Windows Phone", "Firefox OS", "Blackberry OS", "Tizen", "Windows Mobile", "Symbian", "Palm OS"]
      
          // MARK: Memory Management
      
          override init(style: UITableViewStyle) {
              super.init(style: style)
          }
      
          required init!(coder aDecoder: NSCoder!) {
              fatalError("init(coder:) has not been implemented")
          }
      
          override init!(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
              super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
          }
      
          // MARK: View Lifecycle
      
          override func viewDidLoad() {
              // tell the table which class should be used to dequeue cells with given reuse id (previously you set it in storyboards)
              tableView.registerClass(MyTableViewCell.self, forCellReuseIdentifier: cellReuseId)
          }
      
          // MARK: UITableViewDelegate && UITableViewDataSource
      
          override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
              return titles.count
          }
      
          override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
              let cell = tableView.dequeueReusableCellWithIdentifier(cellReuseId, forIndexPath: indexPath) as! MyTableViewCell
              cell.rightLabel.text = "I'm right cell"
              cell.middleLabel.text = titles[indexPath.row]
              cell.leftLabel.text = "I'm left cell"
      
              return cell
          }
      }
      
      1. 您还必须创建您的单元格类并在其中设置所有变量。
      2. 复制以下代码:

        import UIKit
        
        class MyTableViewCell: UITableViewCell {
        
            // alloc & init labels
            let leftLabel = UILabel()
            let middleLabel = UILabel()
            let rightLabel = UILabel()
        
            // MARK: Memory Management
        
            override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
                // never forget to call super in overriden UIKit methods (almost never ;))
                super.init(style: .Default, reuseIdentifier: reuseIdentifier)
        
                // now let's assign these values we've set previously in storyboards
                leftLabel.textAlignment = NSTextAlignment.Left
                // you created a label, but you need to add this label as a subview of cells view.
                contentView.addSubview(leftLabel)
        
                middleLabel.textAlignment = NSTextAlignment.Center
                contentView.addSubview(middleLabel)
        
                rightLabel.textAlignment = NSTextAlignment.Right
                contentView.addSubview(rightLabel)
            }
        
            required init(coder aDecoder: NSCoder) {
                fatalError("init(coder:) has not been implemented")
            }
        
            // MARK: Layout
        
            override func layoutSubviews() {
                super.layoutSubviews()
        
                // here happens all the magic which skips autolayouts. You can ofc set autolayouts from code :)
                let frame = self.contentView.bounds
                // frame was the size of the cell, but we want to set our labels at least 10px from sides of cell - so it looks nicely
                let insetFrame = CGRectInset(frame, 10.0, 10.0)
                // width of each label is width of cell / 3 (you want 3 labels next to each other) minus margins
                let labelWidth = (CGRectGetWidth(insetFrame) - 20.0) / 3.0
        
                // lets calculate the rects and assign frames to calculated values
                let leftLabelRect = CGRectMake(CGRectGetMinX(insetFrame), CGRectGetMinY(insetFrame), labelWidth, CGRectGetHeight(insetFrame))
                leftLabel.frame = leftLabelRect
        
                let middleLabelRect = CGRectMake(CGRectGetMaxX(leftLabelRect), CGRectGetMinY(insetFrame), labelWidth, CGRectGetHeight(insetFrame))
                middleLabel.frame = middleLabelRect
        
                let rightLabelRect = CGRectMake(CGRectGetMaxX(middleLabelRect), CGRectGetMinY(insetFrame), labelWidth, CGRectGetHeight(insetFrame))
                rightLabel.frame = rightLabelRect
            }
        }
        
        1. 现在你可以运行项目了,一切都应该顺利进行。
        2. 最后,我个人更喜欢代码的一个小解释:

          1. 您无法在Storyboards中使用继承。对我而言,不可接受。你甚至无法重复使用视图(除非你为它们制作额外的xib)。因此,您可以添加相同的子视图,并为少数TableView中使用的单元格重新点击相同的自动布局 - >笨。如果我错了,请纠正我,我想知道我错了。
          2. 使用GIT和合并时更容易维护。
          3. LayoutSubviews至少从iOS 3开始正常运行。与此同时,在故事板中,有几种不同的方法来布局,所有工作都不是最好的方式。
          4. 大多数开发人员在使用Storyboard时都不使用真正的MVC:即使他们在代码中执行某些操作,他们也从不创建UIView类。
          5. 你无法在故事板中做任何事情。无法使用CoreGraphics等绘图。
          6. 使用Storyboard创建复杂的布局很麻烦。与此同时,您可以更快地完成代码中的所有操作。