I'm currently trying to replicate the array you can see below in the picture:
I've created a custom cell class so I can display a label and a switch button. The part I have no idea about is how to display the legend below every cell.
Here is my code at the moment:
var options = ["Solstice", "Equinox", "Enable Snapshot"]
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return options.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
let switchView = UISwitch(frame: CGRect.zero)
cell.addSubview(switchView)
cell.accessoryView = switchView
cell.nameLabel.text = options[indexPath.row]
return cell
}
Could the legend be another custom cell, with a different style? What would be the best way to do it?
Setup your table view with a grouped style instead of plain. Put each row is in its own section.
Use a section footer title for each of the legends. This is done with the func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? data source method.
There are two options:-
1)
var options = [ {"title":"Solstice", "description" :"legend" }, {"title":"Equinox", "description" :"legend"} , {"title":"Enable Snapshot", "description" :"legend"}]
Then, You can create the label,switch and legend in same cell itself. For the label in legend should be given number of lines 0, and no constant height so that label increases height based on text similar to AutoLayout to dynamically size UILabel Height and Width
2) Create view with switch as section headers, and legend as row inside each header // this is commonly used when there are more than one row for each section, since your use case has only one row (legend), using single cell will be easier for implementation
Related
I have an application that is viewbased and I am adding a uitableview as a subview to the main view. The uitableview is full with class Category cells. Everything works fine, but I want to have “Quick notes” Category always on the top of the uitableview. This means when I reloadData() in the Array, “Quick Notes” is always with index 0 and it goes on the bottom of the uitableview. And when I create new cell I need it to go under the “Quick Notes” section.
Please help me, what code I need to achieve that functionality and where I need to put it. Thanks!
Edit:
Thats where I am adding "Quick Notes" to the Realm database.
private let categories = try! Realm()
private init() {
if categories.objects(Category.self).isEmpty {
createCategoryWith(title: "Quick Notes", color: "#FF0000", icon: "quickNotes")
}
}
Update the array in the ViewController:
func didCreateCategory(category: Category) {
RealmHandler.shared.createCategoryWith(title: category.title, color: category.color, icon: category.icon)
self.categories = RealmHandler.shared.getAllCategories()
tableView.reloadData()
}
DataSourceDelegate:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "categoryCell", for: indexPath)
cell.textLabel?.text = categories[categories.count - (1+indexPath.row)].getTitle()
cell.contentView.backgroundColor = hexStringToUIColor(hex: categories[categories.count-(1+indexPath.row)].getColor())
return cell
}
use viewForHeaderInSection delegate method of tableView.
tableView(_ tableView: UITableView, viewForHeaderInSection section: Int)
here you can define your header cell.
then implement your logic that what do you want to show on this cell.
this headerCell will be always on top of your tableView.
I am a new in-app ios development. I am trying to get a UI like this: -
Here two types of tables are attached with one table view. This design in andriod.
I tried in IOS and take one table view with custom header and in the header I set another table view. Like this:-
And set code like this : -
override func viewWillLayoutSubviews() {
secondview?.frame.size = CGSize(width: tableViews.frame.width, height: secondtableViews.contentSize.height + 50 + tableViews.contentSize.height)
secondview.layer.masksToBounds = true
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == tableViews {
debugPrint(" first")
return 50
}else{
debugPrint(" second")
return 50
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == tableViews {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")! as UITableViewCell
cell.textLabel?.text = "skdjfhkjfhjkshfkhsdkfhjsd"
return cell
}else{
let cell = tableView.dequeueReusableCell(withIdentifier: "gcell")! as UITableViewCell
cell.textLabel?.text = "skdjfhkjfh jkshfkhsdkfhjsd"
return cell
}
return UITableViewCell()
}
I change the height of main table view. It workes on some part height do not work according to the content of table view and the data of first table showing on second and second is showing on first. Can any one help me out from this design issue.
you should go with one tableview with TWO sections and TWO different type of cell...!
I have a UITableView which represent a questionnaire with Dynamic UI Cells. I've created 2 cells.
The first UI Cell need to be all the time on the top (like a Title/Header) and the second UI Cell need to be Dynamic (this means that the second UI Cell can display 10 or 20 questions). Is there any way to do this ?
I've already created a UITableViewCell for both UI Cells and I linked all the components.
Now I don't know where to specify that Cell 0 to be returned 1 time and Cell 1 to be returned X times.
Also how I keep Cell 0 on the top all the time ?
Here is a printscreen which reflect my issue:
Here is my code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
// Static cell - Checks Left
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "checksLeftCell", for: indexPath) as! ChecksLeftTableViewCell
return cell
// Dynamic cell - Questions
case 1:
let cell = tableView.dequeueReusableCell(withIdentifier: Constants.defectAndDamageCell, for: indexPath) as! DefectAndDamageCheckCell
cell.configCell()
cell.delegate = self
return cell
default:
return UITableViewCell()
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch indexPath.row {
case 0: return 100
case 1: return 400
default:
return 170
}
}
I expect to have "frozen" cell on the top and the second one to be a dynamic cell.
Thanks if you read this and I hope that I explained well what is in my mind.
This isn't sign of good thinking about design. It looks like you don't need UITableView at all. You can achieve better result using basic UIViews for each component such as Title, question details, tags, etc.
You can help yourself using UIStackView.
Instead of a static cell you can use a Section Header with a custom View inside of it:
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let nameLabel = UILabel(frame: CGRect(x: 10, y: 0, width: tabelView.frame.width, height: 40))
nameLabel.text = //
nameLabel.font = taskNameLabel.font.withSize(14)
//Or add whatever you need here
let sub = UIView(frame: CGRect(x: 0, y: 0, width: tabelView.frame.size.width, height: 40))
sub.backgroundColor = .white
sub.addSubview(NameLabel)
return sub
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Constants.defectAndDamageCell, for: indexPath) as! DefectAndDamageCheckCell
cell.configCell()
cell.delegate = self
return cell
}
I would try using UICollectionView instead of the tableview.
From UICollectionView, use the UICollectionViewDelegateFlowLayout delegate.
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { #your code for header view }
https://developer.apple.com/documentation/uikit/uicollectionviewdatasource/1618037-collectionview
or
Create a section header in your TableView, and create a custom view in it.
So your TableView would have 1 section header and 1 row.
Good luck.
There are many ways to solve this.
If you want a static view that sticks to the top try this:
Subclass a UIViewController and add a container UIView at the top/leading/trailing. Embed your header labels and content in the content view. Next, add a UITableView and pin it to the leading/trailing/bottom of the superview. Make your view controller the data source and delegate.
In this way, you will still have scrolling within the tableview and can reload the cells as needed while managing your static header content as IBOutlets.
If you use the selected answer with stack views, you will have to implement a scrolling solution by embedding your stack view in a UIScrollView when your content is longer than the screen size. You should probably just stick to using a tableview because that behavior is inherited.
I have a table view in Swift with headers that expand or contract to show or hide cells, but for some reason there are extra row dividers in the middle of the page for no reason, and the label in the header is not showing up.
class ExpandableHeader: UITableViewHeaderFooterView {
var section: Int = 0
let expandLabel = UILabel()
}
func numberOfSections(in tableView: UITableView) -> Int {
// return number of section in table from data
return list.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// return number of rows in each section from data
return list[section].items.count + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Create cell with the identifier which was set in the storyboard prototype cell
// set cell data/name from our data object
if indexPath.row < list[indexPath.section].items.count {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = list[indexPath.section].items[indexPath.row].name
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "custom", for: indexPath)
return cell
}
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
// create a header of type of our subclassed header with section number
let headerView = ExpandableHeader()
headerView.expandLabel.text = "+"
headerView.expandLabel.frame.size.height = 30
headerView.expandLabel.frame.size.width = 30
headerView.expandLabel.textAlignment = NSTextAlignment.center
headerView.addSubview(headerView.expandLabel)
headerView.expandLabel.frame.origin.x = view.frame.maxX - headerView.expandLabel.frame.width
// assign selected/current section number to the header object
headerView.section = section
// create Gesture Recognizer to add ability to select header to this cutsom header with an action
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(headerClicked(sender:)))
// add Gesture Recognizer to our header
headerView.addGestureRecognizer(tapGesture)
return headerView
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// check if row's section expanded parameter is set to true or false. set height of rows accordingly to hide or show them
if list[indexPath.section].expanded == true {
return 44
} else {
return 0
}
}
I added the relevant lines of code above. When you change the row height to 0, should the cell separator lines also be changed to height 0, or hidden?
Why is the header in each section not going all the way to the right side of the screen when the storyboard has it all the way to the right edge?
Is this also why the text label for the header is not being displayed? Because the right edge is getting cut off?
Sorry for the basic questions, I'm still getting the hang of this, so any suggestions would be much appreciated.
To hide extra row divider use below lines of code
let backgroundView = UIView(frame: CGRect.zero)
self.tableView.tableFooterView = backgroundView //instead of tableView give your tableView name
I am interested in having a tableview for comments (something similar to instagram comments). So far, I have used a custom cell to set up a textView for comments in my set array, dataName. I was wondering how I could go about setting up a textfield and button on the last row of the tableview that would act as the place to input more comments. Do I need to create another customcell for this and implement this in cellForRowAt indexPath ?
var comments = ["I like this item","Where did you get this?", "I can't believe you found this!", "Hello", "Yay"]
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return comments.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
cell.commentView.text = dataName[indexPath.row]
cell.commentView.textColor = UIColor.lightGray
cell.commentView.isEditable = false
cell.commentView.isScrollEnabled = false
return cell
}
You can accomplish you desired effect by adding a view that contains a text field and a button as the footer view of the tableview. And when a new comment is added you will proceed to add the comment to the array, and reload the tableview or insertRow with animation.
You already have one cell prototype called "Cell". Just add another cell prototype called "Comment". Now you have two cell prototypes with two different identifiers. If you're on the last row, ask for the "Comment" cell prototype in your dequeue call.