refreshcontrol ios uiscrollview uicollectionview pull-to-refresh

ios - refreshcontrol - swiperefreshlayout swift



Animar UIScrollView contentInset hace que salte el tartamudeo (7)

Impliqué un control de actualización personalizado (mi propia clase, no una subclase), y por alguna razón desde que me mudé a iOS 8, configurar el contenido de la vista de desplazamiento (específicamente, UICollectionView) para iniciar la actualización de la animación provoca un salto / tartamudeo extraño. Aquí está mi código:

- (void)containingScrollViewDidScroll:(UIScrollView *)scrollView { CGFloat scrollPosition = scrollView.contentOffset.y + scrollView.contentInset.top; if( scrollPosition > 0 || self.isRefreshing ) { return; } CGFloat percentWidth = fabs( scrollPosition ) / self.frame.size.height / 2; CGRect maskFrame = self.maskLayer.frame; maskFrame.size.width = self.imageLayer.frame.size.width * percentWidth; [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; self.maskLayer.frame = maskFrame; [CATransaction commit]; } - (void)containingScrollViewDidEndDragging:(UIScrollView *)scrollView { if( ( self.maskLayer.frame.size.width >= self.imageLayer.frame.size.width ) && !self.isRefreshing ) { self.isRefreshing = YES; [self setLoadingScrollViewInsets:scrollView]; [self startAnimation]; [self sendActionsForControlEvents:UIControlEventValueChanged]; } } - (void)setLoadingScrollViewInsets:(UIScrollView *)scrollView { UIEdgeInsets loadingInset = scrollView.contentInset; loadingInset.top += self.frame.size.height; UIViewAnimationOptions options = UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState; [UIView animateWithDuration:0.2 delay:0 options:options animations:^ { scrollView.contentInset = loadingInset; } completion:nil]; }

Básicamente, una vez que el usuario lanza la actualización, animo el contentInset a la altura del control de actualización. Me imagino que la animación reduciría el tartamudeo / saltos, como lo hizo en iOS 7. Pero en iOS 8, cuando se desplaza el scrollView, en lugar de solo animar a contentInset, el contenido de la vista de desplazamiento salta desde el punto de lanzamiento realmente Rápidamente, y luego se anima sin problemas. No estoy seguro de si esto es un error en iOS 8 o qué. También he intentado añadir:

scrollView.contentOffset = CGPointZero;

En el bloque de animación, que no cambió nada.

¿Alguien tiene alguna idea? Cualquier ayuda sería muy apreciada. ¡Gracias!


Cambié el método con mi bloque de animación a:

- (void)setLoadingScrollViewInsets:(UIScrollView *)scrollView { UIEdgeInsets loadingInset = scrollView.contentInset; loadingInset.top += self.view.frame.size.height; CGPoint contentOffset = scrollView.contentOffset; [UIView animateWithDuration:0.2 animations:^ { scrollView.contentInset = loadingInset; scrollView.contentOffset = contentOffset; }]; }


Dos soluciones:

  1. deshabilitar rebote cuando comienza a cargar y habilitar rebote cuando termina de cargar
  2. después de configurar la inserción de contenido cuando comience a cargar, configure la compensación de contenido con un valor constante

He resuelto por: -

  • Desactive el Bounce cuando ContentInset se actualice a contentOffsetY.
  • Mantenga un registro de contentOffset y actualice a tableView ContentInset.

var contentOffsetY:CGFloat = 100 func tracScrollContent(location: UIScrollView) { if(location.contentOffset.y == -contentOffsetY ) { tblView.isScrollEnabled = true tblView.bounces = false tblView.contentInset = UIEdgeInsets(top: contentOffsetY, left: 0, bottom: 0, right: 0) }else if(location.contentOffset.y >= 0 ){ tblView.bounces = true tblView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) } }

Github Demo Swift-3


Para eliminar el salto, la respuesta de Ryanthon hará el truco. En mi aplicación con iOS9.0, ni siquiera se necesita un bloque de animación para eliminar el salto, simplemente restableciendo contentOffset después de configurar contentInset hará el truco.

Si desea controlar la velocidad de desplazamiento de tableView al ocultar la vista de actualización, el doble truco de los bloques de animación en la respuesta del usuario 3044484 hará la magia, un bloque de animación no es suficiente.

if (self.tableView.contentInset.top == 0) { UIEdgeInsets tableViewInset = self.tableView.contentInset; tableViewInset.top = -1.*kTableHeaderHeight; [UIView animateWithDuration: 0 animations: ^(void){} completion:^(BOOL finished) { [UIView animateWithDuration: 0.5 animations:^{ //no need to set contentOffset, setting contentInset will change contentOffset accordingly. self.tableView.contentInset = tableViewInset; }]; }]; }


Tuve el mismo problema, y ​​moví mi bloque de animación al ...

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView

método de delegado en su lugar. No es perfecto, pero todavía no puedo identificar el problema. Parece que el método -layoutSubviews se llama más a menudo en iOS8, lo que provoca animaciones repentinas.



- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ CGPoint point = scrollView.contentOffset; static CGFloat refreshViewHeight = 200.0f; if (scrollView.contentInset.top == refreshViewHeight) { //openning if (point.y>-refreshViewHeight) { //will close //必须套两层animation才能避免闪动! [UIView animateWithDuration:0 animations:NULL completion:^(BOOL finished) { [UIView animateWithDuration:0.25 animations:^{ scrollView.contentOffset = CGPointMake(0.0f, 0.0f); scrollView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f); } completion:NULL]; }]; } } else{ //closing static CGFloat openCriticalY = 40.0f;//会执行打开的临界值 if(point.y<-openCriticalY){ //will open [UIView animateWithDuration:0 animations:NULL completion:^(BOOL finished) { [UIView animateWithDuration:0.25 animations:^{ scrollView.contentInset = UIEdgeInsetsMake(refreshViewHeight, 0.0f, 0.0f, 0.0f); scrollView.contentOffset = CGPointMake(0.0f, -refreshViewHeight); } completion:NULL]; }]; } } }

Puedes probar esto, la clave es usar dos animaciones.