I am trying to write a function that scrolls to the bottom cell of a given section in my tableView, I'm calling this function after my tableView.reloadData() function but it is not scrolling, any ideas why?
func scrollToBottom(section: Int){
DispatchQueue.main.async {
let indexPath = IndexPath(row: self.session[section].count - 1, section: section)
self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
You don't need put code in DispatchQueue.main because it already run on main thread.
Try this
func scrollToBottom(section: Int){
let indexPath = IndexPath(row: self.session[section].count - 1, section: section)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}
Related
I have a horizontal collectionview that adds a new cell every time I tap the button. I am attempting to scroll the collectionview to the next cell once the cells are no longer visible each time I tap the button.
The code I have now is not working properly
Code:
#IBAction func random(_ sender: Any) {
resultsCollection.reloadData()
let collectionBounds = resultsCollection.bounds
let contentOffset = CGFloat(floor(resultsCollection.contentOffset.x - collectionBounds.size.width))
self.moveToFrame(contentOffset: contentOffset)
}
func moveToFrame(contentOffset : CGFloat) {
let frame: CGRect = CGRect(x : contentOffset ,y : resultsCollection.contentOffset.y ,width : resultsCollection.frame.width,height : resultsCollection.frame.height)
resultsCollection.scrollRectToVisible(frame, animated: true)
}
How can I fix this so that it scrolls correctly when I tap the button?
After reload your data, call this lines.
let lastItem = resultsCollection(resultsCollection, numberOfItemsInSection: 0) - 1
let indexPath = IndexPath(row: lastItem, section: 0)
resultsCollection.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
Use the following code to achieve your needs. For animation, you just need to pass value true/false in animated of scrollToRow function.
Hope this will help you!
To scroll top without animation
func scrollToTopWithoutAnimation() {
DispatchQueue.main.async {
if self.dataArray.count > 0 {
let indexPath = IndexPath(row: 0, section: 0)
collectionView.scrollToItem(at: indexPath, at: .top, animated: false)
}
}
}
To scroll top with animation
func scrollToTopWithAnimation() {
DispatchQueue.main.async {
if self.dataArray.count > 0 {
let indexPath = IndexPath(row: 0, section: 0)
collectionView.scrollToItem(at: indexPath, at: .top, animated: true)
}
}
}
Set IndexPath row as per your needs
I am creating a chat interface.
User's message is put in a new UITable view cell.
And when update the table view, I use the following code.
extension UITableView {
func scrollToBottom() {
let rows = self.numberOfRows(inSection: 0)
if rows > 0 {
let indexPath = IndexPath(row: rows - 1, section: 0)
self.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
}
Actually this works a little better, but there is something strange.
When I turn off the app and turn it on again, or after exiting the screen and entering again, the following issues arise.
The issue is that when I add a new cell, it goes up to the first cell in the table view and back down to the last cell.
See the issue(https://vimeo.com/266821436)
As the number of cells increases, the scrolling becomes too fast and too messy.
I just want to keep updating the last cell that is newly registered.
What should I do?
Please use DispatchQueue to Scroll because of the method you are fire is executed with tableView load data so we need to give time to scroll.
extension UITableView {
func scrollToBottom() {
let rows = self.numberOfRows(inSection: 0)
if rows > 0 {
DispatchQueue.main.async {
let indexPath = IndexPath(row: rows - 1, section: 0)
self.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
}
}
or
func scrollToBottom(){
DispatchQueue.main.async {
let indexPath = IndexPath(row: self.array.count-1, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
self.scrollToRow(at: indexPath.last ...)
I'm developing an iOS Chat App and I have a problem on the chat view. I'm using UITableViewController for the chat view. Sometimes my table jumps when new row is inserted as you can see in video: https://youtu.be/8IgEUJ5uYAc .
This is how I'm inserting and scrolling to the bottom of the table:
self.conversation.append(message)
self.tableView.beginUpdates()
self.tableView.insertRows(at: [IndexPath(row: self.conversation.count - 1, section: 0)], with: UITableViewRowAnimation.none)
self.tableView.endUpdates()
DispatchQueue.main.async {
self.tableView.scrollToRow(at: IndexPath(row: self.conversation.count - 1, section: 0), at: UITableViewScrollPosition.bottom, animated: false)
self.footerView?.isHidden = true
self.theMessage.text = nil
self.switchBottomActions(showSend: false)
}
Each message object has a property called estimatedMessageHeight. I'm saving there the message cell size, so tableView's heightForRowAt code is:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
guard let cellHeight = self.conversation[indexPath.row].estimatedHeight else {
return 0
}
return cellHeight
}
Any solution?
I was also facing same issue and finally I ended up with following solution. It gives me same animation feel like we have in WhatsApp app.
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: [], animations: {
let reloadIndexPath = IndexPath(item: self.arrTableVwData.count - 1, section: 0)
self.tableVw.beginUpdates()
self.tableVw.insertRows(at:[reloadIndexPath], with: UITableViewRowAnimation.fade)
self.tableVw.endUpdates()
self.tableVw.scrollToRow(at: reloadIndexPath, at: .bottom, animated: false)
}, completion: nil)
NOTE: please do not pass any animation types in options:[] as we already passing them in insertRows and scrollToRow methods.
Make this function:
func scrollToBottom(){
DispatchQueue.main.async {
let indexPath = IndexPath(row: self.chatListDB.count-1, section: 0)
self.tblView.scrollToRow(at: indexPath, at: .bottom, animated: false)
}
}
and call it after inserting the value.
You should uncheck Bounce Vertically in the Attribute Inspector for your UITableView.
I am trying to scroll horizontally to a collectionView when I call a function and am receiving the error 'none' is unavailable: use [] to construct an empty option set - not sure what is wrong here...Thanks in advance!
func handleSearch() {
scrollToMenuIndex(menuIndex: 2)
}
func scrollToMenuIndex(menuIndex: Int) {
let indexPath = NSIndexPath(item: menuIndex, section: 0)
collectionView?.scrollToItem(at: indexPath as IndexPath, at: .none, animated: true)
}
You have to provide a position where the item should be scrolled to. See the documentation for UICollectionViewScrollPosition for possible values. In the meantime you could use this:
collectionView?.scrollToItem(at: indexPath as IndexPath, at: .left, animated: true)
I have a method that scrolls my UITableView to the bottom:
func tableViewScrollToBottom(_ animated: Bool) {
let delay = 0.1 * Double(NSEC_PER_SEC)
let time = DispatchTime.now() + Double(Int64(delay)) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: time, execute: {
print(self.tview.numberOfRows(inSection: 0))
print(self.tview.numberOfSections)
let indexPath = IndexPath(row: self.tview.numberOfRows(inSection: 0), section: self.tview.numberOfSections)
print(indexPath)
print("it will crash now")
self.tview.scrollToRow(at: indexPath, at: .bottom, animated: animated)
})
}
it worked well before, however when I added Header View - it crashes.
I see in the console:
8
1
[1, 8]
it will crash now
so I do not understand why this line:
self.tview.scrollToRow(at: indexPath, at: .bottom, animated: animated)
causes crash. What am I missing here?
You have problem with this
let indexPath = IndexPath(row: self.tview.numberOfRows(inSection: 0), section: self.tview.numberOfSections)
Try doing -1
let indexPath = IndexPath(row: self.tview.numberOfRows(inSection: 0)-1, section: self.tview.numberOfSections-1)