I have a UitableView with 3 section (3 cell), In section 1 I have a list of item where user can delete using button, all delete process is good but when I delete a item; the uitableview goes to top and goes to bottom (is something like reload the view) and I want that
When user delete a item only remove from position this is my code
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var value: Int = 0
if(section == 0){
value = 1
}else if(section == 1){
value = items.count //20
}else if(section == 2){
value = 1
}
return value
}
#objc func delete_item(sender: UIButton){
let point = sender.convert(CGPoint.zero, to: tv_items)
guard let indexPath = tv_items.indexPathForRow(at: point) else{
return
}
tv_items.beginUpdates()
self.items.remove(at: indexPath.row)
tv_items.deleteRows(at: [indexPath], with: .fade)
tv_items.endUpdates()
}
cell.btn_delete.tag = indexPath.row
cell.btn_delete.addTarget(self, action: #selector(delete_item), for: .touchUpInside)
Thanks in advance
Use the below method and I think it will solve your issue:-
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50.0 // height of the row (Eg. 50.0)
}
If you are using estimatedHeightForRowAt, disable this and use heightForRowAt function.
Alternatively, use this after endUpdates():
tv_items.scrollToRow(at: indexPath, at: .top, animated: false)
If you have a constant row height, you can use:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 80 // or any constant height
}
If you need varying height based on content, lemme know what the content is so I can help.
Related
I've currently multiple items in tableView cell .I want to increase the height of cell when text condition is matched like if name = "john" then increase the height of cell without disturbing another cell. I want to achieve this screenshot result
My current code is
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == tableOrder {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.tableOrderHeight.constant = self.tableOrder.contentSize.height
//self.tableOrderHeight.constant = (6 * 80)
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath ) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PriceTVCell.self)) as? PriceTVCell else {return UITableViewCell()}
return cell
}
first get the index of the row you want to increase the height and use the delegate function heightForRowAt.
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == customRow {
return 100.0;//Choose your custom row height
}
}
I have created two expandable cells but the second one doesn't expand when I tap on it
I googled a lot of ways how to do this but this one seemed the shortest and the simplest one.
private var dateCellExpanded: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// For removing the extra empty spaces of TableView below
self.tableView!.tableFooterView = UIView()
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
if dateCellExpanded {
dateCellExpanded = false
} else {
dateCellExpanded = true
}
tableView.beginUpdates()
tableView.endUpdates()
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row == 0 {
if dateCellExpanded {
return 250
} else {
return 40
}
}
return 40
}
I expect to be able to add as many cells as I want and have them expand on tap, but only the first one does.
Here's what happens
It's only working for the first row because you're limiting it to the first row with if indexPath.row == 0.
You'll need an array of Bool rather than a single Bool as you need to track the state for all rows.
Just initialize the array to an array of false values with the count of your rows. Set NUMBER_OF_ROWS below accordingly.
Then, when selecting a cell, you flip (or toggle()) the boolean for that row and ask the table to update.
private var isCellExpanded: [Bool] = Array(repeating: false, count: NUMBER_OF_ROWS)
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
isCellExpanded[indexPath.row].toggle()
tableView.beginUpdates()
tableView.endUpdates()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if isCellExpanded[indexPath.row] {
return 250
} else {
return 40
}
}
Note that this assumes that you're only using one section. Otherwise you'll have to adjust the data structure [Bool] to [[Bool]].
I want to make a tableview with a button in the section. I want the button to add one more row to a tableview like this
Here is the source code:
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection sectionInd: Int) -> Int {
if sectionInd == 0 {
return others.count
} else {
return 1
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "ShareCell", for: indexPath as IndexPath) as! SelectOthersTableViewCell
cell.firstName.text = others[indexPath.row].firstname
cell.lastName.text = others[indexPath.row].lastname
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "addCell", for: indexPath as IndexPath) as! addTableCell
cell.addCells.tag = indexPath.row
cell.addCells.addTarget(self, action: #selector(OthersViewController.addButtonClicked(sender:)), for: UIControlEvents.touchUpInside)
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var height:CGFloat = CGFloat()
if indexPath.section == 0 {
height = 145
} else {
height = 50
}
return height
}
#objc func addButtonClicked(sender:UIButton) {
data.append("Guest 1")
let buttonPosition = sender.convert(CGPoint.zero, to: self.tableView)
let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
print("indexPath \(indexPath!)")
selectedIndexes[indexPath!] = !(selectedIndexes[indexPath!] ?? false)
tableView.reloadRows(at: [indexPath!], with: .automatic)
tableView.beginUpdates()
tableView.insertRows(at: [IndexPath(row: data.count-1, section: 0)], with: .automatic)
tableView.endUpdates()
}
i need help please. How to add new row by tap button on icon (+)?
On click of "Add" button, You should not reload the the entire table view because it increases the processing time. Instead of that you can use of
beginUpdates and endUpdates for inserting new cell when button clicked.
Basic Approaches:
(1). On click of "Add", update your data-source for table-view.
dataSource.append(NewRecord)
(2). Insert the new cell:
tableView.beginUpdates()
tableView.insertRows(at: [IndexPath(row: dataSource.count-1, section: 0)], with: .automatic)
tableView.endUpdates()
Reviewing your Code:
func addButtonClicked(sender:UIButton) {
data.append("Guest 1")
.....
}
Your datasource is others on which the tableview is created and configured.
But on click of add button (addButtonClicked function), you are not updating the others data-source. Please verify it, except that your code seems good.
fun onPlusButtonClicked(){
sections.append(whatever you want)
items[2].append(["1", "2", "3", "4"]) // whatever you want to add here
tableview.reloadData() // you can call this on a background thread as well, if its not working
}
// Ex of how to use with tableview
var sections = Your array
var items = your array
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section]
}
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items[section].count
}
I have a tableview with different sections, I need to be able to multiselect from different sections, but the rows in each section should be able to select mutually exclusive wise. For eg: in below screenshot I should be able to select either Margarita or BBQ Chicken from Pizza and same for Deep dish pizza but I should be able to multiselect between Pizza section and Deep dish pizza
Below is my code so far, I was wondering what would be the best way to approach this.
let section = ["Pizza", "Deep dish pizza"]
let items = [["Margarita", "BBQ Chicken"], ["Sausage", "meat lovers"]]
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.section[section]
}
override func numberOfSections(in tableView: UITableView) -> Int {
return section.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath)
// Configure the cell...
cell.textLabel?.text = items[indexPath.section][indexPath.row]
return cell
}
You should create some data element to track the selection for each row.
I would suggest a dictionary of [Int:Int] where the key is the section and the value is the row.
When a row is selected, you can then easily check to see if another row is already selected in that section, and deselect it if required.
var rowSelections = [Int:Int]()
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let section = indexPath.section
if let row = self.rowSelections[section] {
tableView.deselectRow(at: IndexPath(row:row, section:section), animated: true)
}
self.rowSelections[section]=indexPath.row
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let section = indexPath.section
self.rowSelections[section]=nil
}
Ok, so I figured it out, I created a method that would loop and check through all the rows and called it in both tableview didselect and deselect
func updateTableViewSelections(selectedIndex:IndexPath)
{
for i in 0 ..< tableView.numberOfSections
{
for k in 0 ..< tableView.numberOfRows(inSection: i)
{
if let cell = tableView.cellForRow(at: IndexPath(row: k, section: i))
{
if sections.getType(index: i) == selectedIndex.section
{
if (selectedIndex.row == k && cell.isSelected)
{
cell.setSelected(cell.isSelected, animated: false)
}
else
{
cell.setSelected(false, animated: false)
}
}
}
}
}
}
First allow multiple selection:
yourTableView.allowsMultipleSelection = true
To get the select rows:
let selectedRows = tableView.indexPathsForSelectedRows
Then within the didselectrow function you can iterate through the selected rows and ensure that only 1 row within the section can be selected.
I have been searching for this answer and my problem seems to be two-fold: (1) answers are from 2011 and I'm too new to Swift to translate old code and (2) in implementing the code I have found, it changes the height of ALL the cells in the tableView. I have some cells that are larger than others and I need them to be left alone by this.
My question is how to target a single cell's height to expand and contract based on a switch being toggled and have it not effect the height of any other cells.
iOS "create new calendar" event is what I'm looking for and the expandable cell will have a date picker in it, if that matters. Also, I'm using STATIC cells...some being custom and some using built-in features.
EDIT -- added code
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 1 && indexPath.row == 2 {
pickerVisible = !pickerVisible
tableView.reloadData()
}
tableView.deselectRow(at: indexPath, animated: true)
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 1 && indexPath.row == 2 && toggle.isOn == false {
return 0.0
}
if indexPath.section == 1 && indexPath.row == 3 {
if toggle.isOn == false || pickerVisible == false {
return 0.0
}
return 165.0
}
return 44.0
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 44.0
}