I have one UITableViewCell. In TableViewCell, I have 7 buttons in single row. I want to play music. When i press button1, its background colour should be changed. If I pressed button2, its background colour should be changed, and button1 would be deselect. I also set the tag for each button in row, but i don't understand, how to do? Sound is playing fine but i am unable to select and deselect buttons. I am using swift3. Thanks in advance.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> tableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PlayerCell") as! tableViewCell
cell.Btn_one.addTarget(self, action: #selector(TableViewController.BtnAction_One), for: .touchUpInside)
//For example
if (cell.Btn_one.tag == 1){
cell.Btn_one.backgroundColor = .white
}else if (cell.Btn_two.tag == 2){
cell.Btn_two.backgroundColor = .red
}
}
#IBAction func BtnAction_One(_ sender: UIButton) {
self.play()
}
#Chetan solution for this : first one
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellData", for: indexPath)
let btn1 = cell.viewWithTag(1) as! UIButton
let btn2 = cell.viewWithTag(2) as! UIButton
let btn3 = cell.viewWithTag(3) as! UIButton
let btn4 = cell.viewWithTag(4) as! UIButton
let btn5 = cell.viewWithTag(5) as! UIButton
let btn6 = cell.viewWithTag(6) as! UIButton
btn1.addTarget(self, action: #selector(btnClicked(sender:)), for: .touchUpInside)
btn2.addTarget(self, action: #selector(btnClicked(sender:)), for: .touchUpInside)
btn3.addTarget(self, action: #selector(btnClicked(sender:)), for: .touchUpInside)
btn4.addTarget(self, action: #selector(btnClicked(sender:)), for: .touchUpInside)
btn5.addTarget(self, action: #selector(btnClicked(sender:)), for: .touchUpInside)
btn6.addTarget(self, action: #selector(btnClicked(sender:)), for: .touchUpInside)
return cell
}
when this will to btnClicked
` func btnClickec(sender:UIButton){
sender.isSelected = true
let cell = sender.superview?.superview as! UITableViewCell
let btn1 = cell.viewWithTag(1) as! UIButton
let btn2 = cell.viewWithTag(2) as! UIButton
let btn3 = cell.viewWithTag(3) as! UIButton
let btn4 = cell.viewWithTag(4) as! UIButton
let btn5 = cell.viewWithTag(5) as! UIButton
let btn6 = cell.viewWithTag(6) as! UIButton
let arr = [btn1,btn2,btn3,btn4,btn5,btn6];
for index in 0...5{
let btn = arr[index]
if index+1 == sender.tag{
btn.isSelected = true
}else{
btn.isSelected = false
}
}
}
`
And second one : or you can collection view inside tableviewcell also
This is how I did it:
first the function:
func switchColor(isWhite: Bool, sender: UIButton) {
if isWhite == true {
sender.backgroundColor = UIColor.clear
sender.setTitleColor(UIColor.white, for: UIControlState.normal)
}else if isWhite == false {
sender.backgroundColor = UIColor.white
sender.setTitleColor(UIColor.clear, for: UIControlState.normal)
}
Then where I call it:
#IBAction func RepeatWeeklyPressed(_ sender: UIButton) {
if sender.backgroundColor == UIColor.white {
switchColor(isWhite: true, sender: sender)
}else {
switchColor(isWhite: false, sender: sender)
}
print("Pressed a repeat button")
}
Hope this helps!
Well, I suggest you to subclass from UIButton, like this:
class CustomButton: UIButton {
var isPressed = false
override init(frame: CGRect) {
super.init(frame: frame)
}
convenience init(frame: CGRect, title: String, tag: Int) {
self.init(frame: frame)
self.frame = frame
setTitle(title, for: .normal)
setTitleColor(.white, for: .normal)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
switch tag {
case 0: //Play a music
if isPressed{
backgroundColor = .black
} else {
backgroundColor = .clear
}
case 1: //Play a video
if isPressed{
backgroundColor = .black
} else {
backgroundColor = .clear
}
default: //Other
if isPressed{
backgroundColor = .black
} else {
backgroundColor = .clear
}
}
if isPressed { isPressed = false } else { isPressed = true }
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
After that, in your cell I'd have some like...
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .default, reuseIdentifier: nil)
let musicB = CustomButton(frame: CGRect(x: 0, y: 0, width: 0, height: 0), title: "1", tag: 1)
addSubview(musicB)
}
You'll want to subclass the button as CustomButton or whatever you would like to call it. And you'll need to create a delegate to let your viewcontroller know whats up.
Create a func that takes in an integer. This will be the code that'll take in your button's tag and preform some code. #Gabs had the right idea there.
func select(index: Int) {
switch sender.tag {
case 0: //do something
case 1: //do something
}
}
Create a single IBAction then link all your buttons to it. Inside, call the method created above
#IBAction func buttonTapped(_ sender: Any) {
select(index: sender.tag)
}
all that's missing is the viewController being informed on which button has been tapped. Set a delegate for it in your CustomCell view file and have it capture the sender.tag in your IBAction. Be sure to conform your viewcontroller too so the delegation works.
Related
I have added a switch along with each cell in table view but the switch function is not get called. If I give the switch in the front page its displaying successfully. But in tableview cell its not working `
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = models[indexPath.row].Address
cell.textLabel?.text = models[indexPath.row].Number
cell.textLabel?.text = models[indexPath.row].Role
cell.textLabel?.text = models[indexPath.row].Name
//switch
let mySwitch = UISwitch(frame: .zero)
mySwitch.setOn(false, animated: true)
mySwitch.tag = indexPath.row
mySwitch.tintColor = UIColor.red
mySwitch.onTintColor = UIColor.green
mySwitch.addTarget(self, action: #selector(switchValueDidChange(_:)), for: .valueChanged)
cell.accessoryView = mySwitch
return cell
}
#IBAction func switchValueDidChange(_sender: UISwitch){
if _sender .isOn{
print("switch on")
view.backgroundColor = UIColor.red }
else{
view.backgroundColor = UIColor.systemPurple
}
}
`
The signature is wrong. There must be a space character between the underscore and sender. And if it's not a real IBAction replace #IBAction with #objc
#objc func switchValueDidChange(_ sender: UISwitch) {
if sender.isOn {...
and – not related to the issue – the selector can be simply written
#selector(switchValueDidChange)
I have added one Button into tableview button is not clicked. The button is not clicked on the top of TableView. What should I do to make the button clickable? I need to make the CircleMenu button clickable. The button is now on top of tableView3. Do I need to add the button to the tableView?
override func viewDidLoad() {
super.viewDidLoad()
let button = CircleMenu(
frame: CGRect(x: view.frame.width/2 - 10, y: view.frame.height - 270, width: 50, height: 50),
normalIcon:"icon_menu",
selectedIcon:"icon_close",
buttonsCount: 3,
duration: 4,
distance: 85)
button.backgroundColor = UIColor.flatSkyBlue
button.delegate = self
button.layer.cornerRadius = button.frame.size.width / 2.0
view.addSubview(button)
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == self.tableView1 {
if !chipnumber2.text!.isEmpty {
let cell:DeviceTableViewCell2 = tableView1.dequeueReusableCell(withIdentifier: cellIdNew, for: indexPath) as! DeviceTableViewCell2
let deviceItem: Device3New = itemsNew[indexPath.row]
let tap1 = UITapGestureRecognizer(target: self, action: #selector(tittleNewTapped(_:)))
let tap2 = UITapGestureRecognizer(target: self, action: #selector(tittleNewTapped2(_:)))
return cell
}
}
if tableView == self.tableView2 {
if !chipnumber.text!.isEmpty {
let cell:DeviceTableViewCell2 = tableView2.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! DeviceTableViewCell2
let deviceItem: Device3 = items[indexPath.row]
cell.backgroundColor = GradientColor(UIGradientStyle.leftToRight, frame: self.view.frame, colors: [UIColor.flatPowderBlueDark, UIColor.flatSand])
return cell
}
}
if tableView == self.tableView3 {
if !chipnumber3.text!.isEmpty {
let cell:DeviceTableViewCell2 = tableView3.dequeueReusableCell(withIdentifier: cellIdNew2, for: indexPath) as! DeviceTableViewCell2
cell.backgroundColor = GradientColor(UIGradientStyle.leftToRight, frame: self.view.frame, colors: [UIColor.flatPowderBlueDark, UIColor.flatSand])
return cell
}
}
return UITableViewCell()
}
}
Just add a target to the button:
button.addTarget(self, action: #selector(buttonClicked(_:)), for: .touchUpInside)
And then a selector method:
#objc func buttonClicked(_ sender: UIButton) {
print("clicked!")
}
(Edit: Possible duplicate?)
I have a UISearchController with a separate UITableViewController as its searchResultsController.
class SearchResultsViewController: UITableViewController {
var fruits: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView(frame: .zero)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
#objc func addFruit(_ sender: UIButton) {
let point = tableView.convert(sender.bounds.origin, to: sender)
let indexPath = tableView.indexPathForRow(at: point)
print(indexPath?.row)
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruits.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = fruits[indexPath.row]
cell.selectionStyle = .none
let addButton = UIButton(type: .custom)
addButton.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
addButton.setImage(UIImage(named: "add"), for: .normal)
addButton.contentMode = .scaleAspectFit
addButton.addTarget(self, action: #selector(addFruit(_:)), for: .touchUpInside)
addButton.sizeToFit()
cell.accessoryView = addButton
return cell
}
}
I need to show a custom button in cells that search results are shown. So I added a UIButton as the cells' accessoryView. And it looks and works fine.
Now I need to get the cell's indexPath when the user taps on this button.
I'm trying to get it like shown below.
#objc func addFruit(_ sender: UIButton) {
let point = tableView.convert(sender.bounds.origin, to: sender)
let indexPath = tableView.indexPathForRow(at: point)
}
But it keeps returning nil for every cell.
Is there any other way to get the indexPath from a custom button tap? I added a demo project here as well.
Create a custom class named SOButton and add variable of type IndexPath to it. Use this class for your add button initialisation.
//Your class will look like -
class SOButton: UIButton {
var indexPath: IndexPath?
}
//Your action will look like -
#objc func addFruit(_ sender: SOButton) {
print(sender?.indexPath.row)
}
//And in your cellForRow add
let addButton = SOButton(type: .custom)
addButton.indexPath = indexPath
Hope this helps you :)
Please update your code. you pass the UIButton sender in convert function , please pass the tableView into them
func getIndexPathByCgPoint(_ sender: UIButton) -> IndexPath? {
let point = sender.convert(sender.bounds.origin, to: tableview)
guard let indexPath = tableview.indexPathForRow(at: point) else {
return nil
}
return indexPath
}
But in case of section header it return nil.
let buttonPosition = sender.convert(CGPoint.zero, to: self.tableView)
let currentIndexPath = self.tableView.indexPathForRow(at: buttonPosition)
Try this it worked for me :)
I would suggest using this light solution: add indexPath.row to button tag:
let addButton = UIButton(type: .custom)
addButton.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
addButton.tag = indexPath.row
And in button action:
#objc func addFruit(_ sender: UIButton) {
print(sender.tag)
}
This question already has answers here:
How to change Button color in specific TableViewCell
(2 answers)
Closed 5 years ago.
I have a multiple tableViewCells and each tableviewCell contains of 4 buttons. I need to change the color of the button when the button is pressed. I tried to use delegate method for UIButton. like this:
import UIKit
class CustomButton: UIButton {
override var isHighlighted: Bool {
didSet {
if isSelected {
backgroundColor = UIColor.lightGray
} else {
backgroundColor = UIColor.init(red: 34/255, green: 89/255, blue: 128/255, alpha: 1.0)
}
}
}
}
But it is change the color of button in all other cells. But I need to change the button color only in that cell that I have pressed. (I have 4 buttons in 1 cell and I want to change the color of that button that I pressed and only in that cell )
How I implemented My buttons and added the target functions to each button:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Questions.count
}
var variant1 = UIButton()
var variant2 = UIButton()
var variant3 = UIButton()
var variant4 = UIButton()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "finalCell")!
variant1 = cell.contentView.viewWithTag(1) as! UIButton
variant2 = cell.contentView.viewWithTag(2) as! UIButton
variant3 = cell.contentView.viewWithTag(3) as! UIButton
variant4 = cell.contentView.viewWithTag(4) as! UIButton
let questionTextView = cell.contentView.viewWithTag(5) as! UITextView
questionTextView.text = "\(Questions[indexPath.row].content!)"
variant1.addTarget(self, action: #selector(self.variant1ButtonPressed), for: .touchUpInside)
variant2.addTarget(self, action: #selector(self.variant2ButtonPressed), for: .touchUpInside)
variant3.addTarget(self, action: #selector(self.variant3ButtonPressed), for: .touchUpInside)
variant4.addTarget(self, action: #selector(self.variant4ButtonPressed), for: .touchUpInside)
return cell
}
There is the target functions of the buttons(I have identified the indexpath of button when it is pressed):
func variant1ButtonPressed(_ sender:AnyObject) {
let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.tableView)
let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
let intIndexpath = Int((indexPath?.row)!)
}
func variant2ButtonPressed(_ sender:AnyObject) {
let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.tableView)
let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
let intIndexpath = Int((indexPath?.row)!)
}
func variant3ButtonPressed(_ sender:AnyObject) {
let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.tableView)
let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
let intIndexpath = Int((indexPath?.row)!)
}
func variant4ButtonPressed(_ sender:AnyObject) {
let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.tableView)
let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
let intIndexpath = Int((indexPath?.row)!)
}
Please Help!!!
Fisrt of all you are not using delegate.
Second, you've defined your class CustomButton and you are setting your button as UIButton.
Replace this:
var variant1 = UIButton()
var variant2 = UIButton()
var variant3 = UIButton()
var variant4 = UIButton()
For this:
var variant1 = CustomButton()
var variant2 = CustomButton()
var variant3 = CustomButton()
var variant4 = CustomButton()
or simply override the function in your View Controller and delegate your button to self.
Try to change following change in your code
1.
var variant1 : CustomButton!
var variant2 : CustomButton!
var variant3 : CustomButton!
var variant4 : CustomButton!
2 Assign customclass to button in cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "finalCell")!
variant1 = cell.contentView.viewWithTag(1) as! CustomButton
variant2 = cell.contentView.viewWithTag(2) as! CustomButton
variant3 = cell.contentView.viewWithTag(3) as! CustomButton
variant4 = cell.contentView.viewWithTag(4) as! CustomButton
let questionTextView = cell.contentView.viewWithTag(5) as! UITextView
questionTextView.text = "\(Questions[indexPath.row].content!)"
variant1.addTarget(self, action: #selector(self.variant1ButtonPressed(_:)), for: .touchUpInside)
variant2.addTarget(self, action: #selector(self.variant2ButtonPressed(_:)), for: .touchUpInside)
variant3.addTarget(self, action: #selector(self.variant3ButtonPressed(_:)), for: .touchUpInside)
variant4.addTarget(self, action: #selector(self.variant4ButtonPressed(_:)), for: .touchUpInside)
return cell
}
You are only setting 4 tags for all of your buttons. The number of tags needs to be equal to the total number of buttons that you have. So if you have two cells and 8 buttons, the tags should be 1...8. There are a lot of numbers so you need to create them in a loop and also look for the specific clicked button in a loop as well. I also suggest you to do that in a custom cell class.
I'm adding UIButton in UITableView, I'm trying to change UIButton background color, UIButton title color and UIButton image color on table view cell selection and same vice versa.
MY Code is
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let propertyCell = tablePropertyList.cellForRowAtIndexPath(indexPath) as! PropertyListTableCell
propertyCell.buttonDownload.selected = true
propertyCell.buttonDownload.setTitleColor(utility!.uicolorFromHex(0xf8f8f8), forState: UIControlState.Selected)
let image:UIImage = UIImage(named: "DownloadSelected")!
propertyCell.buttonDownload.setImage(image, forState: UIControlState.Selected)
propertyCell.buttonDownload.backgroundColor = utility!.uicolorFromHex(0x006747)
propertyCell.buttonDownload.layer.borderColor = utility!.uicolorFromHex(0x006747).CGColor
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath)
{
let propertyCell = tablePropertyList.cellForRowAtIndexPath(indexPath) as! PropertyListTableCell
propertyCell.buttonDownload.selected = false
propertyCell.buttonDownload.setTitleColor(utility!.uicolorFromHex(0x006747), forState: UIControlState.Normal)
let image:UIImage = UIImage(named: "Download")!
propertyCell.buttonDownload.setImage(image, forState: UIControlState.Normal)
propertyCell.buttonDownload.backgroundColor = utility!.uicolorFromHex(0xf8f8f8)
propertyCell.buttonDownload.layer.borderColor = utility!.uicolorFromHex(0xf8f8f8).CGColor
}
//on UIButton Action
MY Code is
func downloadViewAction(sender: UIButton)
{
sender.selected = true
sender.setTitleColor(utility!.uicolorFromHex(0xf8f8f8), forState: UIControlState.Selected)
let image:UIImage = UIImage(named: "DownloadSelected")!
sender.setImage(image, forState: UIControlState.Selected)
sender.backgroundColor = utility!.uicolorFromHex(0x006747)
sender.layer.borderColor = utility!.uicolorFromHex(0x006747).CGColor
print("inside ownload action view")
let splitView:UISplitViewController = DevelopmemtSplitViewController()
if let path = tablePropertyList.indexPathForSelectedRow {
let selectedproperty = propertyArray[path.row]
self.showActivityIndicator(splitView.view, message: "Downloading properties for "+selectedproperty)
}
}
awakeFromNib method of cell class can be used to change titlecolor, image of button based on state. Please refer following code
class PropertyListTableCell : UITableViewCell
{
func awakeFromNib()
{
propertyCell.buttonDownload.setTitleColor(utility!.uicolorFromHex(0x006747), forState: UIControlState.Normal)
propertyCell.buttonDownload.setTitleColor(utility!.uicolorFromHex(0xf8f8f8), forState: UIControlState.Selected)
}
}
func downloadViewAction(sender: UIButton)
{
sender.selected = true //automatically changes titlecolor of button
}
If I'm getting it right. You have a button inside every PropertyListTableCell and you want to change the way that button looks depending on the selection state of the cell.
If so, overwrite the setSelected(_:animated:) function in your PropertyListTableCell class, this way, whenever a cell is selected or deselect the button appearance will change automatically.
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: true);
if (selected) {
self.buttonDownload.backgroundColor = utility!.uicolorFromHex(0x006747)
self.buttonDownload.layer.borderColor = utility!.uicolorFromHex(0x006747).CGColor
}
else {
propertyCell.buttonDownload.backgroundColor = utility!.uicolorFromHex(0xf8f8f8)
propertyCell.buttonDownload.layer.borderColor = utility!.uicolorFromHex(0xf8f8f8).CGColor
}
self.buttonDownload.selected = true;
}
As commented Savitha above, the button image and the title color can be defined just once in the awakeFromNib (for example).
And there is no need to change any visual in the button action function because it's done when selecting the cell:
func downloadViewAction(sender: UIButton) {
let cell = sender as! as! PropertyListTableCell;
let indexPath = tableView.indexPathForCell(cell);
tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: .None);
print("inside ownload action view")
let selectedproperty = propertyArray[path.row]
self.showActivityIndicator(splitView.view, message: "Downloading properties for "+selectedproperty)
}