I'm using collectionView, and I customized the collectionViewCell in a separate class with type (collectionViewCell). I want to perform an animation when user clicks on a cell. So, I created a UIButton in collectionViewCell and I customized it to cover the whole cell.
button = UIButton(frame: self.frame)
button.addTarget(self, action: "scaleToSmall", forControlEvents: .TouchDown)
self.addSubview(button)
Right now, the animation works perfectly, but the issue is I lost the ability select the cell, and the function didSelectItemAtIndexPath does not call anymore
I found out how to get the indexPath of the cell that has clicked,
But how can I call didSelectItemAtIndexPath again and tell it this cell is selected in order to perform the next action (segue to another ViewController) ???
Thanks in advance!!
You said that you created a button that covers the whole cell, if I have that right. Because of that, didSelectRowAtIndexPath won't do anything because that button is covering the whole cell. Take the Twitter app, for example. You can tap on the cell to open the tweet or you can tap on the user's profile image to open their profile. In this case, it's like you have the profile picture button covering the whole cell. Maybe you can set the animation in didSelectRowAtIndexPath or make the button smaller.
Hope this helps!
Related
I have a UITableView that rapidly update the data and there is a button in the UITableViewCell. From iOS 11 to 14, it works perfectly but after the iOS15 update, the button is broken.
It seems to be untouchable while the cell is updating. So, I can't touch the button
It need to touch on it a lot of times to make the button action fired
When it fired, some time is fire as another cell context. For example: I press the button on cell 1 it should send the sender from cell 1 to the responder but it send the sender from cell 2 instead
The button was embedded as
cell.contentView.isUserInteractionEnabled = true
cell.button.addTarget(self, action: #selector(self.doSomething(sender:)), for: .touchUpInside)
Anyone has some suggestion for me? Thank you
UPDATE
I found the solution is use reconfigure instead of reloadData for UITableView
let indexPaths = tableView.indexPathsForVisibleRows!
if !indexPaths.isEmpty {
tableView.reconfigureRows(at: indexPaths)
}
cell.contentView.isUserInteractionEnabled = true
Remove this line in your code.
I've been trying to create table view cells each with a UIImageView serving as a background for them. However, when I tap on each cell the table view will not register the click and will not transition to the view controller I have hooked up, even while I'm using the didSelectRowAtIndexPath function.
I realize it's probably an issue with the ImageView obstructing the table views ability to register the cell tap. The cells will transition however when I drag my finger/mouse on it from left to right, just not on taps. I tried to use a Tap Gesture Recognizer on the Image View however it only worked for the cell at the very top and not all of them. How do I tackle this issue?
Here is an image of the table view cells so you have an idea of what I'm working with: http://imgur.com/a/Ku4uD. Thank you!
If you uncheck User Interaction Enabled on your Image View, the problem should be solved. When running into a problem always check the user interaction of the most child view and work your way up.
One trick I have also learned is to create a subclass of a child and override touchesShouldCancel like so:
override func touchesShouldCancel(in view: UIView) -> Bool {
print("touchesShouldCancel")
//Run extra code that you want when the user selects this view
//then still retrieve the tap by its parent.
return false
}
I am unsure of exactly what your problem is, but I would delete whatever segue that you have, add a new one by dragging from the yellow circle on the left side of the center portion of the top of your tableView ViewController inside the storyboard, to the viewController that you desire it to segue to. Give the segue an appropriate identifier, and then inside your tableView class under tableView didSelectRow add performSegue(withIdentifier: "ChosenIdentifier", sender: indexPath)
Then in prepare forSegue add in:
if let vc = sender.destination as? TheViewControllerYouAreSegueingTo {
if let indexPath = sender as? IndexPath {
vc.variableIdentifyingWhatCellWasClicked = indexPath.row
}
}
with whatever adjustment is needed to meet your specific needs.
I'm having a TableView. In that tableView, I custom it's cells
like this
In this cell I have 2 part. An Image and an TextField.
It's look like facebook's post status. When I click to Image, I want to open a new ViewController and the same for TextField
But I have a problem that I can't call segue from my cell's class file.
Are there any way that I can call a function in TableViewController's class from TableViewCell's class ?
I know that I can use delegate but I don't like this way a lot, because if I do this way I have to set a lot of delegate in my project.
Are there any better way to present a new ViewController directly from TableViewCell's class
Using a delegate is a very good way to solve your problem.
If you don't like that solution then you could design a table view cell that has a closure property set by the view controller, and invokes that closure when the button is pressed.
EDIT:
Another alternative is to leave the button action empty in your custom cell, but still connect up outlets to the buttons.
Then in your cellForRow(at:) method, install an IBAction that has your view controller as the target. (Credit to #SoanSani, who's answer is below)
In that IBAction method, you can use the coordinates of the button to figure out the indexPath of the cell hat contains the button that was tapped.
I've created an extension to UITableView that lets you figure out the cell that contains any view. The code is below:
import UIKit
public extension UITableView {
/**
This method returns the indexPath of the cell that contains the specified view
- Parameter view: The view to find.
- Returns: The indexPath of the cell containing the view, or nil if it can't be found
*/
func indexPathForView(_ view: UIView) -> IndexPath? {
let origin = view.bounds.origin
let viewOrigin = self.convert(origin, from: view)
let indexPath = self.indexPathForRow(at: viewOrigin)
return indexPath
}
}
You can use delegates, but if you dont want to use delegates
while setting up the cell add target to your button tableViewController class and then you can receive all events in tableview class rather than cell class.
But this would require to add tags which you can use to differentiate which button in cell was clicked
Objective C Code
[OkBtn addTarget:self action:#selector(okButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
Swift Code
OkBtn.addTarget(self, action: #selector(ViewController.okButtonTapped), for: .TouchUpInside)
I have a UITablaView in my Objective C application. I have the custom cells with a label and a UIImageView. I want to disable a part of the rows, to disable didSelectRowAtIndexPath when users click on this row's part.
I want this:
Is it possible?
Here is the simple and the most elegant solution that I can think off.
I believe you must be having a CustomCell, which holds the IBOutlet to imageView on the left side :) You can make use of hitTest method to solve your problem :)
In your CustomCell lets assume it to be MyTestCell class write this,
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.myImageView.frame.contains(point) {
return nil
}
return super.hitTest(point, with: event)
}
Where myImageView is the IBOulet of imageView on the left hand side of your cell :)
All am doing is checking where did user tap, if the touch point is within the frame of cells imageView you return nil as the view. When you return nil touch event stops propagating to its parent views and finally will never reach cell hence didSelectRowAtIndexPath never called,
On the other hand you should handover touch to the next view and you do it simply by calling same method on its super iOS will eventually trace it back to cell and triggers didSelectRowAtIndexPath
Hope it helps :)
You can do a simple trick (without the need of writing code) to solve this issue, by adding a button that covers the part that you want to disable the selection of it. Obviously, the button should not have any text or background color (it should be clear color), also make sure to add suitable constraints for making sure that is covered the wanted part of the cell.
So when tapping on the button, nothing should happen and didselectRow should not get called because the actual touching event should be referred to the button, not to the row.
Hope this helped.
This is very simple trick,
Add a button on profile image part, means on red part as shown in picture (provided by you). And don't do on click on button click.
Happy Coding!!!!
Simply put the button over Green area and set tag for each button. Onclick you can perform your functionality using tag. Like this
inside
func tableView(tableView: UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let obj: AnyObject = self.dataList.objectAtIndex(indexPath.row);
cell?.populateCellWithData(obj, indexPath: indexPath)
cell?.destinationLabel.userInteractionEnabled = true
let destRecognizer : UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "DestLabelTapped:")
destRecognizer.numberOfTapsRequired = 1
destRecognizer.delegate = self
cell?.destinationLabel.addGestureRecognizer(destRecognizer)
}
and in DestLabelTapped you can peform your functionlity
Another way
Just set two Tableview and scroll them side by side and one table is selectable and another is not. (don't do this)
In my understanding the tricks with buttons and other UIElements that are covering the content are not the right way to solve the target. As you will need extra manipulations with them in Storyboard, if you will need to make dynamically content, if you will work with constraints and many more situations where you will need to control your content and + the artificial cover. There are few things to do:
Set UITableView selection to No Selection
Put the second part that you want to be active in UIView. This UIView will be the content container.
Add UITapGestureRecognizer to UIView
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(selectCellAction:)];
Add IBAction where you could do all you need.
- (IBAction)selectCellAction:(id)sender
{
// do what you need
}
And thats all.
You may simply do change the image view width constraints to 0. Where you want to action is performed. As for example:
1) If you use a button that cover the image.
2) If you take a navigation bar then you there take a button and perform the action.
hope this will help.
I am using MGSwipeTableCell in my app. When a cell is swiped open to reveal buttons if I tap on another cell it dismisses the swipe cell (hides the buttons again). I want the previously swiped cell to dismiss the buttons and then select the new cell in one tap instead of two (i.e. tap off and then tap new cell). Is there any way to to do this?
See the description below, I think this delegate function of MGSwipeTableCell might help you.
-(void) swipeTableCell:(MGSwipeTableCell*) cell didChangeSwipeState:(MGSwipeState) state gestureIsActive:(BOOL) gestureIsActive
{
/**
* Called when the user clicks a swipe button or when a expandable button is automatically triggered
* #return YES to autohide the current swipe buttons
**/
}
On MGSwipeTableCell version 1.5.4 or later
cell.touchOnDismissSwipe = YES;
It will dismiss the cell you did swiped and also select the cell you tap