Je voudrais savoir quand un UITableView
a défilé jusqu'en bas pour charger et afficher plus de contenu, quelque chose comme un délégué ou quelque chose d'autre pour que le contrôleur sache quand le tableau est descendu en bas.
Est-ce que quelqu'un sait cela, aidez-moi s'il vous plaît, merci d'avance!
Le meilleur moyen est de tester un point en bas de l'écran et d'utiliser cette méthode lorsque l'utilisateur fait défiler (scrollViewDidScroll
):
- (NSIndexPath *)indexPathForRowAtPoint:(CGPoint)point
Testez un point près du bas de l'écran, puis utilisez indexPath pour vérifier si indexPath est la dernière ligne, puis ajoutez-le.
dans le délégué de tableview faire quelque chose comme ça
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
CGPoint offset = aScrollView.contentOffset;
CGRect bounds = aScrollView.bounds;
CGSize size = aScrollView.contentSize;
UIEdgeInsets inset = aScrollView.contentInset;
float y = offset.y + bounds.size.height - inset.bottom;
float h = size.height;
// NSLog(@"offset: %f", offset.y);
// NSLog(@"content.height: %f", size.height);
// NSLog(@"bounds.height: %f", bounds.size.height);
// NSLog(@"inset.top: %f", inset.top);
// NSLog(@"inset.bottom: %f", inset.bottom);
// NSLog(@"pos: %f of %f", y, h);
float reload_distance = 10;
if(y > h + reload_distance) {
NSLog(@"load more rows");
}
}
_ {Les néo-modes modifiés répondent un peu.
Cette réponse s'adresse à ceux d'entre vous qui veulent seulement que l'événement soit déclenché une fois par relâchement du doigt.
Convient lorsque vous chargez plus de contenu à partir d'un fournisseur de contenu (service Web, données de base, etc.) . Notez que cette approche ne respecte pas le temps de réponse de votre service Web.
- (void)scrollViewDidEndDragging:(UIScrollView *)aScrollView
willDecelerate:(BOOL)decelerate
{
CGPoint offset = aScrollView.contentOffset;
CGRect bounds = aScrollView.bounds;
CGSize size = aScrollView.contentSize;
UIEdgeInsets inset = aScrollView.contentInset;
float y = offset.y + bounds.size.height - inset.bottom;
float h = size.height;
float reload_distance = 50;
if(y > h + reload_distance) {
NSLog(@"load more rows");
}
}
ajoutez cette méthode dans la UITableViewDelegate
:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat height = scrollView.frame.size.height;
CGFloat contentYoffset = scrollView.contentOffset.y;
CGFloat distanceFromBottom = scrollView.contentSize.height - contentYoffset;
if(distanceFromBottom < height)
{
NSLog(@"end of the table");
}
}
Aucune des réponses ci-dessus ne m'a aidé, alors je suis venu avec ceci:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)aScrollView
{
NSArray *visibleRows = [self.tableView visibleCells];
UITableViewCell *lastVisibleCell = [visibleRows lastObject];
NSIndexPath *path = [self.tableView indexPathForCell:lastVisibleCell];
if(path.section == lastSection && path.row == lastRow)
{
// Do something here
}
}
Utiliser la méthode – tableView:willDisplayCell:forRowAtIndexPath:
(UITableViewDelegate
)
Il vous suffit de comparer la indexPath
avec les éléments de votre tableau de données (ou la source de données que vous utilisez pour la vue tableau) pour déterminer si le dernier élément est affiché.
UITableView
est une sous-classe de UIScrollView
et UITableViewDelegate
est conforme à UIScrollViewDelegate
. Ainsi, le délégué que vous attachez à la vue table obtiendra des événements tels que scrollViewDidScroll:
et vous pourrez appeler des méthodes telles que contentOffset
sur la vue table pour rechercher la position de défilement.
NSLog(@"%f / %f",tableView.contentOffset.y, tableView.contentSize.height - tableView.frame.size.height);
if (tableView.contentOffset.y == tableView.contentSize.height - tableView.frame.size.height)
[self doSomething];
Gentil et simple
dans Swift
vous pouvez faire quelque chose comme ceci. La condition suivante sera vraie chaque fois que vous atteindrez la fin de la tableview
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row+1 == postArray.count {
println("came to last row")
}
}
S'appuyant sur la réponse de @Jay Mayu, que j'ai trouvée être l'une des meilleures solutions
Objectif c
// UITableViewDelegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
// Need to call the service & update the array
if(indexPath.row + 1 == self.sourceArray.count) {
DLog(@"Displayed the last row!");
}
}
Swift 2.x
// UITableViewDelegate
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if (indexPath.row + 1) == sourceArray.count {
print("Displayed the last row!")
}
}
Prendre neoneye d'excellentes réponses mais en Swift, et renommer les variables.
Fondamentalement, nous savons que nous avons atteint le bas de la vue du tableau si la variable yOffsetAtBottom
dépasse la hauteur du contenu du tableau.
func isTableViewScrolledToBottom() -> Bool {
let tableHeight = tableView.bounds.size.height
let contentHeight = tableView.contentSize.height
let insetHeight = tableView.contentInset.bottom
let yOffset = tableView.contentOffset.y
let yOffsetAtBottom = yOffset + tableHeight - insetHeight
return yOffsetAtBottom > contentHeight
}
J'utilise généralement cela pour charger plus de données, lorsque la dernière cellule commence à s'afficher
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == myDataArray.count-1) {
NSLog(@"load more");
}
}
Voici le code de version de Swift 3.0.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset = scrollView.contentOffset
let bounds = scrollView.bounds
let size = scrollView.contentSize
let inset = scrollView.contentInset
let y: Float = Float(offset.y) + Float(bounds.size.height) + Float(inset.bottom)
let height: Float = Float(size.height)
let distance: Float = 10
if y > height + distance {
// load more data
}
}
Ma solution consiste à ajouter des cellules avant que tableview ne décélère en fonction du décalage estimé. C'est prévisible par vélocité.
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)offset {
NSLog(@"offset: %f", offset->y+scrollView.frame.size.height);
NSLog(@"Scroll view content size: %f", scrollView.contentSize.height);
if (offset->y+scrollView.frame.size.height > scrollView.contentSize.height - 300) {
NSLog(@"Load new rows when reaches 300px before end of content");
[[DataManager shared] fetchRecordsNextPage];
}
}
Mise à jour pour Swift 3
La réponse de Neoneye a fonctionné le mieux pour moi dans l'Objectif C, c'est l'équivalent de la réponse dans Swift 3:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let offset: CGPoint = scrollView.contentOffset
let bounds: CGRect = scrollView.bounds
let size: CGSize = scrollView.contentSize
let inset: UIEdgeInsets = scrollView.contentInset
let y: CGFloat = offset.y + bounds.size.height - inset.bottom
let h: CGFloat = size.height
// print("offset: %f", offset.y)
// print("content.height: %f", size.height)
// print("bounds.height: %f", bounds.size.height)
// print("inset.top: %f", inset.top)
// print("inset.bottom: %f", inset.bottom)
// print("position: %f of %f", y, h)
let reloadDistance: CGFloat = 10
if (y > h + reloadDistance) {
print("load more rows")
}
}
Je veux effectuer une action sur mon tout 1 tableviewcell complet.
Donc, le code est lié au:
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
NSArray* cells = self.tableView.visibleCells;
NSIndexPath *indexPath = nil ;
for (int aIntCount = 0; aIntCount < [cells count]; aIntCount++)
{
UITableViewCell *cell = [cells objectAtIndex:aIntCount];
CGRect cellRect = [self.tableView convertRect:cell.frame toView:self.tableView.superview];
if (CGRectContainsRect(self.tableView.frame, cellRect))
{
indexPath = [self.tableView indexPathForCell:cell];
// remain logic
}
}
}
Puisse cela aider quelqu'un.
La réponse de @ neoneye a fonctionné pour moi. Voici la Swift 4 version
let offset = scrollView.contentOffset
let bounds = scrollView.bounds
let size = scrollView.contentSize
let insets = scrollView.contentInset
let y = offset.y + bounds.size.height - insets.bottom
let h = size.height
let reloadDistance = CGFloat(10)
if y > h + reloadDistance {
//load more rows
}