Why am I scroll first cell then third cell also scrolling?
Screen Record
It is because of cell reuse, so basically the cell that you scroll goes off screen and will be reused when another cell down is needed.
In your UITableViewCell subclass you can implement prepareForReuse method, this is called when cell is ready to be reused and you can set contentOffset to 0 there, something like:
override func prepareForReuse() {
super.prepareForReuse()
scrollView.contentOffset = CGPoint(x: 0, y: 0)
}
Related
I want to animate a subview of a custom TableViewCell. To perform this animation, the cell needs the width of this subview, which is laid out by an auto-layout-constraint.
However, when I use the animation-function in the cellForRowAtIndex function (mycell.animate()), the width is 0, because the subviews are not laid out yet and the animation will not work.
In a regular view, I would use viewDidLayoutSubviews(), because then the view is laid out, I can get the width and perform the animation. However, what's the equivalent function for a custom UITableViewCell?
I tried the willDisplay delegate function of the TableView, but when I print out the width of the cells subview, it still says 0...
The correct place is inside layoutSubviews:
class MyCell : UITableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
// do your thing
}
}
It will work if you animate your view inside draw function in tableViewCell
override func draw(_ rect: CGRect) {
super.draw(rect)
//Your code here
}
I have created a simple UICollectionView inside of a tableviews, UITableviewCell. The collection view is set to scroll horizontally. I am trying to scroll to a certain element within the collection view using scrollToIndex at:, I have placed the scroll request in the tableviewcell's layoutSubviews method. When the collection view is displayed, no scrolling takes place.
Here is the tableviewcell's layoutSubviews code:
override func layoutSubviews() {
super.layoutSubviews()
let indexPath = IndexPath(item: 1, section: 0)
self.collectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.left , animated: false)
}
It's quite simple, so really not sure why this is not working?
Many thanks for any help!
I have a UICollectionView that is populated with all photos from the devices photo library. After a cell (photo) is tapped, it segues to a view controller that allows for editing. On this view, there is an "Add Photo" button to return the user back to the UICollectionView (to select another photo). I need for the scroll position to "focus" the previous tapped cell in the center of the view without any animations or jumping.
I have tried saving the tapped indexPath as a variable, then on viewDidAppear, scroll to that indexPath with scrollToItemAtIndexPath. The problem is I can't figure out how to update a variable (to save indexPath) on cell tap. I tried this in didSelectItemAtIndexPath, but the value never actually saves.
var cellTappedIndexPath = Int()
Inside didSelectItemAtIndexPath:
cellTappedIndexPath = indexPath.row
The value for cellTappedIndexPath never saves.
Just for testing out scrollToItemAtIndexPath, I have added the following to viewDidAppear:
customViewCollectionView.scrollToItemAtIndexPath(NSIndexPath(forItem: 25, inSection: 0), atScrollPosition: UICollectionViewScrollPosition.CenteredVertically, animated: false)
// 25 is just a number I have set for testing. Ultimately, I would like this to be the saved indexPath of the last tapped cell.
This causes the collectionView to "jump" to cell 25 once it's fully loaded. If I set animated to true, it loads at the top, then scrolls down to cell 25. Not my desired result.
I just want to be able to do 2 things here.
1 - Save the cell tapped as a variable.
2 - use scrollToItemAtIndexPath (with the variable in #1) so the view just loads up instantly with the last cell tapped right into the middle, No animations or anything.
Let me know if further clarification is needed. THANKS!
You could save the selected indexPathreceived when the collectionview cell is tapped and use it when required.
var selectedIndexPath: NSIndexPath?
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
selectedIndexPath = indexPath
}
func scrollToCell(){
if let index = selectedIndexPath{
customViewCollectionView.scrollToItemAtIndexPath(index, atScrollPosition: .CenteredVertically, animated: false)
}else{
print("A cell hasnt been selected yet")
}
}
So I want a signature view within a table cell. Obviously whenever somebody tries to draw in the cell, the table scrolls.
How would I stop the scrolling but ONLY when the user is writing in the signature box?
I found better solution for this issue rather than putting button. Implement the delegate methods in viewController,
class mainVC: UIViewController,YPSignatureDelegate {
Than set delegate of signature view to this view controller
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SignatureCell", for: indexPath) as! SignatureCell
cell.signatureView.delegate = self
return cell
}
And then add these code. This are two delegates of YPSignature. Add in Main view controller
func didStart() {
tableView.isScrollEnabled = false
}
// didFinish() is called rigth after the last touch of a gesture is registered in the view.
// Can be used to enabe scrolling in a scroll view if it has previous been disabled.
func didFinish() {
tableView.isScrollEnabled = true
}
I would solve this with a button covering the cell, and when the user taps it, the cell displays the YPDrawSignatureView. Just before the signature view is shown, disable the scrolling:
tableView.scrollEnabled = false
Later when you save the signature, enable scrolling again by setting scrollEnabled to true.
I added a uitableview and custom cells. In one of the custom cells contain a button(ex. addSignatureButton) on the top of signatureView.
I used delegate method to communicate between uitableviewcell and uiviewcontroller. A delegate is added to UITableViewCell to notify whether the addSignatureButton is tapped. Once it is tapped, addSignatureButton is hidden, signatureView is visible and the tableview's scroll is disabled. When user finishes adding signature, signatureView is hidden, addSignatureButton is visible and tableview scroll is enabled.
https://github.com/alvinvgeorge/DrawSignatureOnTableViewCell
I have tableView and when i type i want auto height cell. But i don't know how to fix it. My first idea was:
self.chatTableView.cellForRowAtIndexPath(indexPath)?.textLabel?.text = new_char
self.chatTableView.cellForRowAtIndexPath(indexPath)?.sizeToFit()
self.chatTableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: false)
When i have this line with .sizeToFit() my result looks like this:
But when i comment this line:
self.chatTableView.cellForRowAtIndexPath(indexPath)?.textLabel?.text = new_char
self.chatTableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: false)
My result looks this:
Is any way to fix it ?
You have changed the height of your UITableViewCell directly. But the height of the cell is handled in the UITableView. To make this work you have to do two things:
1. Use self sizing cells:
Just add this two lines of code to your viewDidLoadmethod:
override func viewDidLoad() {
super.viewDidLoad()
...
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 40
}
The estimatedRowHeight is only used to calculate the scroll bar size and position so you just put the normal expected height of your cells here.
2. Reload the cell after you changed the text
After you changed the text of your cell's label, you have to tell the UITableView to reload this cell so that its height gets adjusted. You do this by calling this method:
func addSomeText() {
// add the text to your data source
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
Obviously the indexPath is your cell's indexPath.
One important thing: You cannot add the new text directly to the cell. Instead you have to add it to your dataSource. Otherwise the text will be gone after the reload, because the cell gets its text from the dataSource when it is dequeued.