#objc func addinterestserver(_ sender: UIButton) {
sender.backgroundColor = UIColor.white
sender.setTitleColor(UIColor.black, for: .normal)
sender.setTitle(NSLocalizedString("Added", comment: ""), for: .normal)
sender.isEnabled = false
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! SearchInterestsCustom
let release = arrayOfRels[(indexPath as NSIndexPath).row]
cell.user.text = release.title
cell.match.text = release.count + NSLocalizedString(" people added", comment: "")
cell.addbutton.tag = release.eventID
cell.addbutton.addTarget(self, action: #selector(SearchInterests.addinterestserver), for: .touchUpInside)
cell.addbutton.layer.cornerRadius = 20
return cell
}
After user tapped the button, It affects also other cell's button, clearly I see same modified buttons several times upon scroll.
How to avoid this?
You can avoid this by
var allSelected = [Int]()
//
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! SearchInterestsCustom
if allSelected.contains(release.eventID) {
cell.addbutton.backgroundColor = UIColor.white
cell.addbutton.setTitleColor(UIColor.black, for: .normal)
cell.addbutton.setTitle(NSLocalizedString("Added", comment: ""), for: .normal)
cell.addbutton.isEnabled = false
}
else {
// set default values
}
}
//
#objc func addinterestserver(_ sender: UIButton) {
sender.backgroundColor = UIColor.white
sender.setTitleColor(UIColor.black, for: .normal)
sender.setTitle(NSLocalizedString("Added", comment: ""), for: .normal)
sender.isEnabled = false
allSelected.append(sender.tag) // store it here
}
Related
I am facing this weird problem of updating a button in a cell on click. I have this like button which i change depend on status i get in response when i click the button. So when the like status is false. I show it in grey and on click if the status in back-end changes and if i get the status as true in response i change it to pink and vice- versa. The issue is for the first time. once i change the cell the functionality works as expected.
Here is my code
I made a variable for the cell to access it globally
var TheVideoPlayerCell:VideoPlayerCell?
func registerTableCells(){
myTable.register(UITableViewCell.self, forCellReuseIdentifier: "DefaultCell")
myTable.register(UINib(nibName: "VideoPlayerCell", bundle: nil), forCellReuseIdentifier: "VideoPlayerCell")
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videoArrObj?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "VideoPlayerCell", for: indexPath) as! VideoPlayerCell
TheVideoPlayerCell = cell
cell.obj = videoArrObj?[indexPath.row]
cell.btn_Likes.addTarget(self, action: #selector(onClickLike), for: .touchUpInside)
cell.selectionStyle = .none
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return CGFloat(self.myTable.frame.height)
}
Once i get a response from backend
self.TheVideoPlayerCell?.btn_Likes.isEnabled = true
let obj = try JSONDecoder().decode(LikeStatusModal.self, from: data)
let likeStatus = obj.data?.like_status ?? false
let totalLikes = obj.data?.total_likes ?? ""
if likeStatus{
self.TheVideoPlayerCell?.btn_Likes.setImage(UIImage(named: "icon_like_selected"), for: .normal)
}else{
self.TheVideoPlayerCell?.btn_Likes.setImage(UIImage(named: "icon_like_unselected"), for: .normal)
}
if totalLikes != ""{
self.TheVideoPlayerCell?.lbl_NoOfLikes.text = totalLikes
}
self.TheVideoPlayerCell?.obj?.is_like = likeStatus
self.TheVideoPlayerCell?.obj?.likes = totalLikes
self.videoArrObj?[self.currentIndex].is_like = likeStatus
self.videoArrObj?[self.currentIndex].likes = totalLikes
You are getting the wrong indexpath. Try accessing the cell this way.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "VideoPlayerCell", for: indexPath) as! VideoPlayerCell
cell.obj = videoArrObj?[indexPath.row]
cell.btn_likes.tag = indexPath.row
cell.btn_Likes.addTarget(self, action: #selector(onClickLike(sender:)), for: .touchUpInside)
cell.selectionStyle = .none
return cell
}
func onClickLike(sender : UIButton) {
// Here is have the api request for that video obj
ServiceSuccessData(action : "YourString", data : Data, index : sender.tag)
}
//Once I get response from server
func ServiceSuccessData(action:String, data:Data, index : Int){
let cell = tableView.cellForRow(at: IndexPath(row: index, section: 0)) as! YourCell
cell.btn_Likes.isEnabled = true
DispatchQueue.main.async {
let obj = try JSONDecoder().decode(LikeStatusModal.self, from: data)
let likeStatus = obj.data?.like_status ?? false
let totalLikes = obj.data?.total_likes ?? ""
if likeStatus{
cell.btn_Likes.setImage(UIImage(named: "icon_like_selected"), for: .normal)
} else {
cell.btn_Likes.setImage(UIImage(named: "icon_like_unselected"), for: .normal)
}
if totalLikes != ""{
cell.lbl_NoOfLikes.text = totalLikes
}
cell.obj?.is_like = likeStatus
cell.obj?.likes = totalLikes
self.videoArrObj?[self.currentIndex].is_like = likeStatus
self.videoArrObj?[self.currentIndex].likes = totalLikes
}
}
My task I am trying to show tableView with check box button inside the popup viewcontroller.
Whenever user click the button it is changing check and uncheck but I need to do when I click done button I have to keep user checked and if click cancel it should uncheck(which is user checked before click cancel). I need to understand and fix this task.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:MyCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MyCustomCell
cell.myCellLabel.text = self.animals[indexPath.row]
if selectedRows.contains(indexPath)
{
cell.checkBox.setImage(UIImage(named:"check.png"), for: .normal)
}else{
cell.checkBox.setImage(UIImage(named:"uncheck.png"), for: .normal)
}
cell.checkBox.tag = indexPath.row
cell.checkBox.addTarget(self, action: #selector(checkBoxSelection(_:)), for: .touchUpInside)
return cell
}
// method to run when table view cell is tapped
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) as? MyCustomCell else {
return
}
if self.selectedRows.contains(indexPath) {
self.selectedRows.remove(at: self.selectedRows.index(of: indexPath)!)
cell.checkBox.setImage(UIImage(named:"uncheck.png"), for: .normal)
} else {
self.selectedRows.append(indexPath)
cell.checkBox.setImage(UIImage(named:"check.png"), for: .normal)
let indexPath = tableView.indexPathForSelectedRow //optional, to get from any UIButton for example
let currentCell = tableView.cellForRow(at: indexPath!) as! MyCustomCell
}
}
#IBAction func cancelPopup(_ sender: Any) {
self.removeAnimate()
}
#IBAction func donePopUp(_ sender: AnyObject) {
self.removeAnimate()
}
You may consider using basic taleview cell with setting acessoryType . Putting checkbox and labels all at the left seems giving poor UX
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DefectCell", for: indexPath)
let category = defectSet [indexPath.section]
let item = category.items[indexPath.row]
cell.textLabel?.text = item.name
cell.selectionStyle = .none
let isFound = User.shared.selectedDefect.filter{ $0.id == item.id }.count > 0
if (isFound)
{
cell.accessoryType = .checkmark
}
else
{
cell.accessoryType = .none
}
return cell
}
I have a strange behavior in the UITABLEVIEW.
I have a TableView with Button, what I wanted to do is when I clicked to a button in the tableView, I want the color border to change to red.
The problem is that the color is changing not only for the clicked button, but also for others row in the tableview:
Here is my implementation
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! chooseProductTVC
cell.Btn_AddProduct.addTarget(self, action: #selector(self.btnAction(_:)), for: .touchUpInside)
return cell
}
#objc func btnAction(_ sender: MyButton) {
sender.BorderColor = UIColor.red
let point = sender.convert(CGPoint.zero, to: tbl_View_ChooseProduct as UIView)
let indexPath: IndexPath! = self.tbl_View_ChooseProduct.indexPathForRow(at: point)
let object = self.fetchedResultsController.object(at: indexPath)
print (object.produit_name)
print("row is = \(indexPath.row) && section is = \(indexPath.section)")
}
As you can see in the picture below I have only clicked on the first button (Abricot) ==> other button has also automatically changed the border (Avocat) and many others.
This is because of cell dequeuing try to re set when you load the table , suppose here default is blue
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
cell.Btn_AddProduct.addTarget(self, action: #selector(self.btnAction(_:)), for: .touchUpInside)
if selected
cell.Btn_AddProduct.BorderColor = UIColor.red
else
cell.Btn_AddProduct.BorderColor = UIColor.blue
return cell
}
Since we reuse the cell for displaying, we have to modify the color every time after dequeing.
Add new property selected to product model.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! chooseProductTVC
cell.Btn_AddProduct.addTarget(self, action: #selector(self.btnAction(_:)), for: .touchUpInside)
let object = self.resultArray(at: indexPath.row)
if object.selected
cell.Btn_AddProduct.BorderColor = .red
else
cell.Btn_AddProduct.BorderColor = .blue
return cell
}
#objc func btnAction(_ sender: MyButton) {
sender.BorderColor = UIColor.red
let point = sender.convert(CGPoint.zero, to: tbl_View_ChooseProduct as UIView)
let indexPath: IndexPath! = self.tbl_View_ChooseProduct.indexPathForRow(at: point)
let object = self.fetchedResultsController.object(at: indexPath)
object.selected = true
print (object.produit_name)
print("row is = \(indexPath.row) && section is = \(indexPath.section)")
}
Tip: You could use tableChooseProduct(iOS) instead of tbl_View_ChooseProduct.(android). This link may helpful.
You have to store default Colors in Dictionary.
var orderColor = [Int : UIColor]()
override func viewDidLoad() {
super.viewDidLoad()
for i in 0...29 // TotaL number of rows
{
orderColor[i] = UIColor.blue // DEFAULT color of the Button
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 30
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! chooseProductTVC
cell.Btn_AddProduct.addTarget(self, action: #selector(self.btnAction(_:)), for: .touchUpInside)
cell.Btn_AddProduct.BorderColor = orderColor[indexPath.row]
cell.selectionStyle = .none
return cell
}
#objc func btnAction(_ sender: MyButton) {
let point = sender.convert(CGPoint.zero, to: tbl_View_ChooseProduct as UIView)
let indexPath: IndexPath! = self.tbl_View_ChooseProduct.indexPathForRow(at: point)
orderColor[indexPath.row] = UIColor.red
tbl_View_ChooseProduct.reloadData()
}
i have added data in table view and i have manually added "select all" option in to list at first position now when user select first option which is select all then all item in to list should be selected and deselected when choose same. i have tried code below but its not working so can any one help me to solve this
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = ObjTableview.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! SelectUserCell
for i in 0 ..< self.getStudentName.count {
cell.btnCheckbox.setImage(UIImage(named: "selectedItem"), for: .normal)
print (i) //i will increment up one with each iteration of the for loop
}
}
var unchecked = true
#IBAction func btnCheckBoxClick(_ sender: Any) {
if unchecked == true {
//(sender as AnyObject).setImage(UIImage(named: "selectedItem"), for: .normal)
cell?.btnCheckbox.setImage(UIImage(named: "selectedItem"), for: .normal)
//unchecked = false
let cello = ObjTableview.cellForRow(at: indexPath!)
print(cello!)
ObjTableview.reloadData()
}else
{
//(sender as AnyObject).setImage(UIImage(named: "unSelectedItem"), for: .normal)
cell?.btnCheckbox.setImage(UIImage(named: "unSelectedItem"), for: .normal)
// unchecked = true
}
}
Jayprakash, You are almost there. You need to modify some lines -
Here is your modified code snippet
var unchecked:Bool = true
#IBAction func btnCheckBoxClick(_ sender: Any) {
if(unchecked){
unchecked = false
}
else{
unchecked = true
}
ObjTableview.reloadData()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if(indexPath.row == 0){
btnCheckBoxClick(sender: UIButton())
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell : SelectUserCell!
cell = tableView .dequeueReusableCell(withIdentifier: "SelectUserCell", for: indexPath) as! SelectUserCell
cell.selectionStyle = UITableViewCellSelectionStyle.none
if(unchecked){
cell.btnCheckbox.setImage(UIImage(named: "unSelectedItem"), for: .normal)
}
else{
cell.btnCheckbox.setImage(UIImage(named: "selectedItem"), for: .normal)
}
// Do your stuff here
return cell
}
Hop it will simplify your code structure.
I am implementing a like dislike button on the tableview cell but unable to change the image of the button. can anybody help me out using swift 3
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var array: [String] = ["A","B","C","D","E","F"]
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: cell_TableTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "cell_TableTableViewCell") as UITableViewCell! as! cell_TableTableViewCell!
cell.textLabel?.text = array[indexPath.row]
cell.button_Outlet.tag = indexPath.row
cell.button_Outlet.addTarget(self, action: "LikePressed", for: .touchUpInside)
return cell
}
}
func LikePressed(sender : UIButton){
sender.isSelected = !sender.isSelected
}
While designing your custom cell, you can add image for that button for different states
Default
Selected
When you add selector for that button, in that selector you just need to change button's selection state
func buttonTapped(sender : UIButton){
sender.isSelected = !sender.isSelected
}
It's very simple, for example your button is from storyboard. Add make that it custom button.
1) And add tag value in cellForRowAt indexPath:.
2) And set two images for that butoon.
3) Finally fix selected sate.
See my code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: cell_TableTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "cell_TableTableViewCell") as UITableViewCell! as! cell_TableTableViewCell!
cell.textLabel?.text = array[indexPath.row]
//Step 1
cell.button_Outlet.tag = indexPath.row
cell.button_Outlet.addTarget(self, action: "LikePressed", for: .touchUpInside)
//Step 2
cell.button_Outlet.setImage(UIImage(named: "LikeImage"), for: .selected)
cell.button_Outlet.setImage(UIImage(named: "DisLikeImage"), for: .selected)
return cell
}
//Step 3
func btnPressed(sender:UIButton) {
if sender.isSelected == false {
sender.isSelected = true
} else {
sender.isSelected = false
}
}
IBOutlet the UIButton into your cell class(Eg. TableViewCell).
Write a method in ViewController class to detect buttonTap.
Eg:
func dislikeTapped(_ sender: UIButton) {
// set required image to sender
}
In TableView-CellForRow method add target to the button in cell.
Eg:
cell.dislikeButton.addTarget(self, action: #selector(self.dislikeTapped(_:), for: .touchUpInside)
You need to create an array too to maintain the state of button as when you scroll cell that are not visible on screen are removed from memory, so they are dequeued again from one that are visible, if you not maintain the state it will use attributes of cell u dequeued from.
var arrSelectedButtonswitTag = [Int]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: cell_TableTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "cell_TableTableViewCell") as UITableViewCell! as! cell_TableTableViewCell!
cell.textLabel?.text = array[indexPath.row]
//Step 1
cell.button_Outlet.tag = indexPath.row
cell.button_Outlet.addTarget(self, action: "LikePressed", for: .touchUpInside)
//Step 2
cell.button_Outlet.setImage(UIImage(named: "LikeImage"), for: .selected)
cell.button_Outlet.setImage(UIImage(named: "DisLikeImage"), for: .normal)
if arrSelectedButtonswitTag.contain(sender.tag)
sender.isSelected = false
arrSelectedButtonswitTag.remove(sender.tag)
} else {
sender.isSelected = true
arrSelectedButtonswitTag.appen(sender.tag)
}
return cell
}
//Step 3
func btnPressed(sender:UIButton) {
if arrSelectedButtonswitTag.contain(sender.tag)
sender.isSelected = false
arrSelectedButtonswitTag.remove(sender.tag)
} else {
sender.isSelected = true
arrSelectedButtonswitTag.append(sender.tag)
}
}