How to set action of UILabel in UITableView - ios

I have a UITableView in ViewController and 3 UILabel in it with a Prototype Cell labeled Date, Party and Amount. Now situation is that i want whenever a user tapped on a UILabel, say Date, it shows all records from Database table for particular Date or if User tapped on Party Label then All transactions of particular party will be shown. So please help me in getting this. How could i do this..

There are many to do the same.
You can use button without any border or background image. Just give simple text to button and it would look like label. Add action to the button.
You can use UIGestureRecognizers for the same. You can add Gesture Recognizer directly to all UILabel separately as explained by #LalitKumar. .
You can also add Gesture Recognizer to your Table View and access all its subviews in your UIGesture Recognizer Action .
Add Gesture Recognizer in viewDidLoad as
let tap = UITapGestureRecognizer(target: self, action: #selector(Yourcontroller.handleTap))
yourTableView.isUserInteractionEnabled = true
yourTableView.addGestureRecognizer(tap)
Define action for Gesture Recognizer and get indexpath of cell as well as subviews of cell.
func handleTap(_ gesture: UITapGestureRecognizer){
let tapLocation = gesture.location(in: self.tableView)
if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation)
{
if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) as? UITableViewCell
{
print("Row Selected") // access tapped cell and its subview as
let touchpoint:CGPoint = gesture.location(in: cell)
if cell.datelabel.frame.contains(touchpoint) {
// user tapped date label
} elseif cell.imageView.frame.contains(touchpoint) {
// user tapped image
}
}
}
}

let tap = UITapGestureRecognizer(target: self, action: #selector(Yourcontroller.tapLabelFunction))
yourLabel.isUserInteractionEnabled = true
yourLabel.addGestureRecognizer(tap)
// if you make label on the cell
cell.yourLabel.userInteractionEnabled = true
cell.yourLabel.tag = indexPath.row
cell.yourLabel.addGestureRecognizer(tap)
}
func tapLabelFunction(sender:UITapGestureRecognizer) {
print("label tapped",sender.view!.tag); // for tag
}

Add this in cellForRowAtIndexPath
yourLabel?.isUserInteractionEnabled = true
if ((yourLabel?.gestureRecognizers?.description) == nil) {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tap(onPeopleName:)))
tapGesture.delegate = self
tapGesture.numberOfTapsRequired = 1
tapGesture.numberOfTouchesRequired = 1
tapGesture.cancelsTouchesInView = false
yourLabel?.addGestureRecognizer(tapGesture)
}
Selector
func tap(onPeopleName gesture: UIGestureRecognizer) {
let lbl: UILabel? = (gesture.view as? UILabel)
let cell: UITableViewCell? = (lbl?.superview?.superview as? UITableViewCell)
let indexPath: IndexPath? = tblViewPracticeDetail.indexPath(for: cell!)
}

Related

how show user selected cell of tableview on longpress

Hello i am adding UILongPressGesture in my tableview and i have added successfully but issue is that how to show that cell is selected i mean i want change color of selected cell and when i again do longpress on selected cell than i want to delselect cell
i have try to add long press in my tableview with code and assign delegates on LongPress here is my code
#objc func longPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) {
if longPressGestureRecognizer.state == UIGestureRecognizer.State.began {
let touchPoint = longPressGestureRecognizer.location(in: self.tblList)
if let indexPath = tblList.indexPathForRow(at: touchPoint) {
}
}
}
And in viewDidload() i am writing this code
let longPressGesture:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(SMSChatViewController.longPress(_:)))
longPressGesture.minimumPressDuration = 1.0 // 1 second press
longPressGesture.delegate = self
self.tblList.addGestureRecognizer(longPressGesture)
so from this code i am able to select cell but how to show user that the cell is selected i don't know how to do this
so i just want like that when user is do longpress than cell color change and set as selected and then again do longpress than deselect cell with its original color
What about you change just the backgroundColor of the cell, when the longPressGesture is recognized? Something like this:
#objc func longPress(_ longPressGestureRecognizer: UILongPressGestureRecognizer) {
if longPressGestureRecognizer.state == UIGestureRecognizer.State.began {
let touchPoint = longPressGestureRecognizer.location(in: self.tblList)
if let indexPath = tblList.indexPathForRow(at: touchPoint) {
let cell = tblList.cellForRow(at: indexPath)
if (cell.isSelected) {
cell.backgroundColor = UIColor.clear // or whatever color you need as default
cell.setSelected(false, animated: true)
} else {
cell.backgroundColor = UIColor.orange
cell.setSelected(true, animated: true)
}
}
}
}
If you need clarification or i missunderstood a thing let me know and i will edit my answer.

Getting Tag from Tap Gesture Recognizer

I've got an array of UIImageViews and have programmatically assigned tap gesture recognizers to them.
myImages.forEach{ UIImageView in
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(gesture:)))
tap.numberOfTapsRequired = 1
tap.delegate = self
view.addGestureRecognizer(tap)
}
What's the best way to assign a sender to each (or determine which image was tapped another way)? I've unsuccessfully tried
var tag = sender.view!.tag
Thanks!
in here you need to follow two steps,
step 1
assign the tags for imageview before append to your myImages array.
step 2
get the tag from imageview array and assign to your each gesture
myImages.forEach{
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
tap.numberOfTapsRequired = 1
tap.view?.tag = $0.tag
$0.isUserInteractionEnabled = true
$0.addGestureRecognizer(tap)
}
and handle the func like
#objc func handleTap(_ sender: UITapGestureRecognizer) {
guard let getTag = sender.view?.tag else { return }
print("getTag == \(getTag)")
}
You can use the block provided by UITapGestureRecognizer init to access your images in place.
myImages.forEach { image in
let tap = UITapGestureRecognizer(block: {[weak self] _ in
//Do your stuff here
//print("Image Tapped:", image.debugDescription)
}, delegate: self)
tap.numberOfTapsRequired = 1
image.addGestureRecognizer(tap)
}
If you want to set UITapGestureRecognizer in UICollectionView or UITableView cell then below solution is useful for us.
Step 1 Assign the UITapGestureRecognizer to particuller textview or other view in UICollectionView or UITableView cell.
cell.textView?.delegate = self
cell.textView?.isEditable = false
cell.textView?.isSelectable = true
let tap = UITapGestureRecognizer(target: self, action:#selector(self.onclickLink(_:)))
cell.textView?.tag = indexPath.row
tap.numberOfTapsRequired = 1
cell.textView?.addGestureRecognizer(tap)
Step 2 Get the tag from UITextView or other View in onclick action.
#IBAction func onclickLink(_ sender: UITapGestureRecognizer) {
print("indexPathRow == \(sender.view?.tag ?? 0)")
}

How can we add a UIGestureRecognizer to Outlet Collection?

I'm trying to add a tap gesture to an outlet collection of labels [UILabel], like this:
#IBOutlet var subLabels: [UILabel]!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(HomePageViewController.selectSubLabel(tap:)))
tap.numberOfTapsRequired = 1
tap.cancelsTouchesInView = false
for i in (0..<(subLabels.count)) {
subLabels[i].addGestureRecognizer(tap)
}
}
func selectSubLabel(tap: UITapGestureRecognizer) {
print("Gesture Is WORKING!")
}
and i tried to add it on a single label in storyboard; but NONE are working.
Firstly, you need to allow user interaction on a label (it is turned off by default):
for i in (0..<(subLabels.count)) {
subLabels[i].isUserInteractionEnabled = true
subLabels[i].addGestureRecognizer(tap)
}
but gesture recognizer can observe for gestures only in one view.
So, there are two options:
I. Dedicated gesture recognizer for every label
for i in (0..<(labels.count)) {
let tap = UITapGestureRecognizer(target: self, action: #selector(selectSubLabel(tap:)))
labels[i].isUserInteractionEnabled = true
labels[i].addGestureRecognizer(tap)
}
II. One gesture recognizer for the parent view of the labels
override func viewDidLoad() {
super.viewDidLoad()
for i in (0..<(labels.count)) {
subLabels[i].isUserInteractionEnabled = true
}
let tap = UITapGestureRecognizer(target: self, action: #selector(selectSubLabel(tap:)))
view.addGestureRecognizer(tap)
}
func selectSubLabel(tap: UITapGestureRecognizer) {
let touchPoint = tap.location(in: view)
guard let label = subLabels.first(where: { $0.frame.contains(touchPoint) }) else { return }
// Do your stuff with the label
}
Please check the User Interaction Enabled Attribute of your UIlabel's in Attribute inspector of Xcode. User Interaction Enabled must be ticked for detecting the tap. Please see the picture below,

How to get the indexpath.row when a UIImageView in a cell is tapped?

swift: how to get the indexpath.row when a button in a cell is tapped?
This link is an answer for when a button is tapped, and if my question is not possible I'll just use a button and put the image on it. I was just wondering if it is possible to this with tapping a UIImageView instead of a button. I tried the exact answer with a UIImageView instead of a UIButton and I got this error
"fatal error: unexpectedly found nil while unwrapping an Optional value".
cell.imagePosted is a UIImageView
let tapGR = UITapGestureRecognizer(target: self,action:Selector("imageTapped:"))
cell.imagePosted.userInteractionEnabled = true
cell.imagePosted.addGestureRecognizer(tapGR);
func imageTapped(img: AnyObject)
{
if let imgView = img as? UIImageView {
if let superView = imgView.superview {
if let cell = superView.superview as? CellCustom {
indexPath2 = self.tableView.indexPathForCell(cell)
}
}
}
print(indexPath2.row)
}
this might help you,
add an UITapGestureRecognizer to UIImageView
You can store indexpath.row in tag property of UIImageView and access that tag on UITapGestureRecognizer event
for example (Objective-C) :
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleImageTap:)];
tap.cancelsTouchesInView = YES;
tap.numberOfTapsRequired = 1;
[cell.imageView addGestureRecognizer:tap];
cell.imageView.tag = indexPath.row;
and get indexpath.row
-(void)handleImageTap:(UITapGestureRecognizer *)gestureRecognizer{
UIView* view = gestureRecognizer.view;
CGPoint loc = [gestureRecognizer locationInView:view];
NSInteger indexpath = [view hitTest:loc withEvent:nil].tag;
NSLog(#"%ld",(long)indexpath);
}
You can create a protocol with a method like imageViewInCellTapped(cell:YourCellType)and a delegate property in the cell. In cellForRowAtIndexPath set the controller the delegate of each cell and implement the method from the protocol. When something happens in your cell like a button or image is tapped you can call delegate?.imageViewInCellTapped(self) where self is the cell then in your controller where this method is implemented you get the index using indexPathForCell method of the tableView.
Here is Madan's code in swift if anybody is interested:
func imageTapped(gestureRecognizer: UITapGestureRecognizer) {
var view: UIView!
var loc: CGPoint!
view = gestureRecognizer.view
loc = gestureRecognizer.locationInView(view)
var indexPath: NSInteger!
indexPath = (view.hitTest(loc, withEvent: nil)?.tag)!
print(indexPath)
}
Hope this code helps to get indexpath for tapped cell swift 3:
func nameTapped(_ sender:UITapGestureRecognizer)
{
var pointVAlue = CGPoint()
pointVAlue = sender.location(in: infoTable)
var indexPath = IndexPath()
indexPath = infoTable.indexPathForRow(at: pointVAlue)!
print(indexPath.row)
/* if indexPath != nil {
let userEnt = ratingArray.object(at: indexPath.row)as! RateEntity
let detailVc = AssociateDetailViewController()
if ((userEnt.userId as String).isEmpty == false )
{
detailVc.m_otherUserId = userEnt.userId as String
self.navController!.pushViewController(detailVc, animated: true)
}
}*/
}

UITableViewController select header for section

I have a UITableView with multiple sections. Each section has a section header (a custom view) is there an easy way to detect when someone selects the section header? (Just like didSelectRowAtIndexPath, but for the header?)
This isn't radically different than #rckoenes answer, but it does provide a more orthodox way of handling events on views rather than using invisible buttons.
I'd rather add a UITapGestureRecognizer to my header view instead of adding invisible buttons and resizing them:
UITapGestureRecognizer *singleTapRecogniser = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)] autorelease];
[singleTapRecogniser setDelegate:self];
singleTapRecogniser.numberOfTouchesRequired = 1;
singleTapRecogniser.numberOfTapsRequired = 1;
[yourHeaderView addGestureRecognizer:singleTapRecogniser];
and then:
- (void) handleGesture:(UIGestureRecognizer *)gestureRecognizer;
You can use gesture.view to see which was touched. Then do whatever you need to do to find out which header it was (tags, data array lookup... )
No there is no way to do it with the UITableViewDelegate.
What you can do is to add a button the size of the section header view and add it to the view. Set the tag of the button to the section index.
Then just add the UIViewController as a target for the UIControlEventTouchUpInside.
Then by looking at the tag of the button you can see which section is clicked.
Here is what worked for me in Swift 2:
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let footerView = UITableViewHeaderFooterView()
footerView.textLabel?.text = "Header Text"
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapRecognizer.delegate = self
tapRecognizer.numberOfTapsRequired = 1
tapRecognizer.numberOfTouchesRequired = 1
footerView.addGestureRecognizer(tapRecognizer)
return footerView
}
#objc func handleTap(gestureRecognizer: UIGestureRecognizer) {
print("Tapped")
}
This worked for evaluating the section and row. I hope it helps everybody else who is struggling to get this work properly...
override func viewDidLoad() {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(sectionTapped(sender:)))
tableView?.addGestureRecognizer(tapGesture)
tapGesture.delegate = self as? UIGestureRecognizerDelegate
}
#objc func sectionTapped(sender: UITapGestureRecognizer) {
if sender.state == UIGestureRecognizerState.ended {
guard let tableView = self.tableView else {
return
}
if let view = sender.view {
let tapLocation = sender.location(in: tableView)
if let tapIndexPath = tableView.indexPathForRow(at: tapLocation) {
if (tableView?.cellForRow(at: tapIndexPath) as? UITableViewCell) != nil {
// do something with the row
print("tapped on row at index: \(tapIndexPath.row)")
}
} else {
for i in 0..<tableView.numberOfSections {
let sectionHeaderArea = tableView.rectForHeader(inSection: i)
if sectionHeaderArea.contains(tapLocation) {
// do something with the section
print("tapped on section at index: \(i)")
}
}
}
}
}
}

Resources