1

Please find the below screenshot.

Mock up I need the solution to be working in iOS 8 too. Stack View is not helpful in iOS 8

I have been assigned this mock up... I don't exactly know how to repeat a particular label in the tableViewCell. As you can see I need to repeat the violet label and white labels depending on the items in JSON data..

SaiPavanParanam
  • 416
  • 6
  • 16
  • 1
    Can you have any number of that kind of label, or just 0, 1 or 2? If yes, just prepare theses case, and hide them if necessary. – Larme Jan 04 '17 at 13:33
  • @Larme can you elaborate.. what are you talking about when you are mentioning 0,1,2 – SaiPavanParanam Jan 04 '17 at 13:37
  • The violet label, if you can have it only once or twice (but not 32 times for instance in the same cell), it's easier. But first, are you able to custom yourself your `UITableViewCell`? – Larme Jan 04 '17 at 13:39
  • Can you explain more about repeating violet label and white labels? – Vishal Sonawane Jan 04 '17 at 13:47
  • White label has a Gas Station Name and violet label has the amount of gallons in the Gas Station.. The number of violet labels and white labels is always equal... and that number wont be more than 5. So we can have max 5 sites for a particular order – SaiPavanParanam Jan 04 '17 at 13:52

5 Answers5

2

This is the perfect scenario to user UIStackView, add 5 labels inside Stack View and hide(.isHidden Property) the labels which you do not want to show, this will cause Stack View to Shrink and Expand based upon number of labels present inside it.

I hope you are already informed with Stack View, if not then you must look for basic online tutorial.

Bista
  • 7,869
  • 3
  • 27
  • 55
1

As Mr.Bista mentioned there is an option with StackView.

  1. Create custom cell in Storyboard with the design.
  2. Instead of adding multiple labels use stack view.
  3. In code use self sizing cells. You can refer to this site to guide you. APPCode self sizing cells or just seek on stackoverflow.

I did not test it by myself now, but I assume it can be tricky to use stackView and self sizing cell. Since every cell can have different height based on contents of StackView. So to be hundred percent sure, you can always calculate the height of cell.

  1. Change the content of stack view based on json content. (Number of records for violet labels)

You can also check the stack for similar questions. Please see this link where there is possible answer for you. Multiple UILabels inside a self sizing UITableViewCell

Community
  • 1
  • 1
Radim Halfar
  • 536
  • 2
  • 6
  • 15
  • how to do this in iOS 8.0, since stack view is unavailable in less than 9 versions of iOS – SaiPavanParanam Jan 05 '17 at 07:30
  • So if you are using < iOS 8, you use do it this way. **1.** Add subview to cell (Standard UIView), add height constraint to it. **2.** Calculate the height for that subview based on number of violet cell records in json file **3.** Modify the height constraint of that view from step 1 **4.** Generate the labels in code and add them as subview to view from step 1. @SaiPavanParanam – Radim Halfar Jan 05 '17 at 08:44
1

You can use a combination of horizontal and vertical stack views to achieve this:

enter image description here

This solution allows you to avoid two pitfalls with the other approaches suggested above:

  • You don't have to mess with toggling views' hidden property
  • You aren't limited to a fixed maximum number of items

Here's the code:

import UIKit

class Order {
    var stations = [Station]()
    var companies = [String]()
}
class Station {
    let name: String
    let amount: Int
    init(name: String, amount: Int) {
        self.name = name
        self.amount = amount
    }
}

class TableViewController: UITableViewController {

    var orders = [Order]()

    override func viewDidLoad() {
    super.viewDidLoad()

    tableView!.rowHeight = UITableViewAutomaticDimension
    tableView!.estimatedRowHeight = 44.0

    //simulated data
    let order1 = Order()
    order1.companies.append("Global @ CITGO Braintree, Braintree")
    order1.companies.append("Exxon @ Global, Chelsea")
    order1.stations.append(Station(name: "Tyngsboro Mobil #2871", amount: 4000))
    order1.stations.append(Station(name: "Grafton St #10095", amount: 15000))
    orders.append(order1)

    let order2 = Order()
    order2.companies.append("Exxon @ Global, Chelsea")
    order2.stations.append(Station(name: "Winstead Citgo #2001", amount: 3000))
    orders.append(order2)

    let order3 = Order()
    order3.companies.append("MSCG @ Sunoco Partners")
    order3.stations.append(Station(name: "Citgo #123", amount: 7000))
    order3.stations.append(Station(name: "Mobil #345", amount: 12500))
    order3.stations.append(Station(name: "Exxon #567", amount: 300))
    order3.stations.append(Station(name: "Citgo #789", amount: 6100))
    order3.stations.append(Station(name: "Stoughton Mobil #2744", amount: 9098))
    order3.stations.append(Station(name: "Westborough Mobil #2720", amount: 120000))
    orders.append(order3)
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return orders.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as! TableViewCell

    let order = orders[indexPath.row]

    cell.companyLabel.text = ""
    for (index, company) in order.companies.enumerated() {
        cell.companyLabel.text! += company
        if index < order.companies.count - 1 {
            cell.companyLabel.text! += "\n"
        }
    }

    for station in order.stations {

        // create horizontal stack view to arrange the station name and amount
        let horizontalStackView = UIStackView()
        horizontalStackView.axis = .horizontal

        let nameLabel = UILabel()
        nameLabel.translatesAutoresizingMaskIntoConstraints = false
        nameLabel.text = station.name
        horizontalStackView.addArrangedSubview(nameLabel)

        let amountLabel = UILabel()
        amountLabel.translatesAutoresizingMaskIntoConstraints = false
        amountLabel.addConstraint(NSLayoutConstraint(item: amountLabel, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: 60))
        amountLabel.backgroundColor = UIColor.purple
        amountLabel.textAlignment = .right
        amountLabel.textColor = UIColor.white
        amountLabel.text = String(station.amount)
        horizontalStackView.addArrangedSubview(amountLabel)

        // add the horizontal stack view to the vertical stack view containing all stations
        cell.stackView.addArrangedSubview(horizontalStackView)
    }

    return cell
}

}

Here's what the storyboard looks like:

enter image description here

Mike Taverne
  • 9,156
  • 2
  • 42
  • 58
  • But won't your code fail if the site name is more than two lines... will numbers properly align again?? – SaiPavanParanam Jan 05 '17 at 05:02
  • Try copying the code into a sample project. I made it so you can easily change the sample data and see what happens. You can use the UIStackView's spacing property to add space between the violet labels. Obviously you will have to do some work on your own to get the style exactly like the mockup, but I have shown you how to repeat the labels within a cell. Good luck! – Mike Taverne Jan 05 '17 at 05:25
  • Great, if it works for you, would you be so kind as to accept this answer? Thanks. – Mike Taverne Jan 05 '17 at 05:35
  • yeah... sure.. but let me try it first – SaiPavanParanam Jan 05 '17 at 05:37
  • Can you please send your project file – SaiPavanParanam Jan 05 '17 at 05:39
  • how to do this in iOS 8.0, since stack view is unavailable in less than 9 versions of iOS – SaiPavanParanam Jan 05 '17 at 07:29
  • If you can avoid supporting iOS 8, that is your best way out. Is this an app for consumers or business? If you must support iOS 8, then you could roll your own equivalent of the stack view, but it is not easy. A stack view is really a container for other views, where the stack view arranges them for you automatically by adding the necessary constraints. You can use a simple UIView as a container and add your labels to it, but you will need to add the constraints in code yourself. Doable, but not simple. – Mike Taverne Jan 05 '17 at 07:43
  • I need to support this in iOS 8 since many people who are going to use my app will need it in iOS 8.0. I will try what you suggested – SaiPavanParanam Jan 05 '17 at 08:01
0

In storyboard you have to two UILabel each for white and violet. If Json have data then assign it otherwise do below code

cell.label1.frame.size.height = 0
cell.label2.frame.size.height = 0

Note : Becarefull about constraints you are giving to the components in the UITableViewCell.

dahiya_boy
  • 9,298
  • 1
  • 30
  • 51
  • i cant understand your answer – SaiPavanParanam Jan 04 '17 at 13:40
  • This will cause many problems with the layout of your cells, so I wouldn't recommend this method. – Benjamin Lowry Jan 04 '17 at 13:51
  • 1
    I am doing this since many months, i never got any trouble, even it is finest for me. @BenjaminLowry If you have any other method, happy to hear. – dahiya_boy Jan 04 '17 at 13:53
  • I agree with @Larme about creating custom cell classes for the different alternatives. That way you can determine the characteristics of your UI much more easily. The method that you are suggesting is either going to leave too much space between labels (just because the height is zero doesn't mean the intermediate label isn't there) or will just cause there to be blank space between labels, which won't look good either. If you are using prototype cells then messing with the height of the cell isn't a good idea, and if you are doing it programmatically then just add/don't add the label subview. – Benjamin Lowry Jan 04 '17 at 13:57
  • I'm DVing this answer as I am skeptical of its validity and its ability to answer OPs question. – Benjamin Lowry Jan 04 '17 at 13:59
  • @SaiPavanParanam. There are two labels each for violet and white as you see in image. Now each and every cell there are two labels but some cells you need one label. To solve this, hide one label and give its height to `0`. – dahiya_boy Jan 04 '17 at 14:12
  • @BenjaminLowry With the `autolayout` [ http://stackoverflow.com/questions/18746929/using-auto-layout-in-uitableview-for-dynamic-cell-layouts-variable-row-heights ] you can set components within the `UITableViewCell` and there is no any line of code and no space between labels. Thats why I write in note about constraints. There is uncertainty of where he need two label or single label. If he take 2 custom cell then he also put the condition & again do the code for seperate custom cell – dahiya_boy Jan 04 '17 at 14:17
0

According to @the_dahiya_boy answer:

  1. You get the JSON field with specific fields (there can be one or two fields that need to be displayed in violet fields)

  2. You check how many fields there are

  3. If there is only one field then you can take set the frame of your second view (for second field, that is empty) as 0