Ich habe ein benutzerdefiniertes Aktualisierungssteuerelement implementiert (meine eigene Klasse, keine Unterklasse), und aus irgendeinem Grund, seit ich auf iOS 8 umgestiegen bin, führt das Festlegen des contentInset der Bildlaufansicht (insbesondere UICollectionView) zum Starten der Aktualisierungsanimation zu einem seltsamen Sprung/Stottern. Hier ist mein Code:
- (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];
}
Grundsätzlich animiere ich das contentInset auf der Höhe des Refresh-Steuerelements, sobald der Benutzer die Aktualisierung freigibt. Ich denke, die Animation würde das Stottern/Ruckeln reduzieren, wie es in iOS 7 der Fall war. Wenn in iOS 8 die ScrollView-Funktion jedoch vom Ziehen befreit wird, springt der Inhalt der Scroll-Ansicht nicht nur zum contentInset, sondern springt tatsächlich vom Release-Punkt ab schnell und animiert dann reibungslos. Ich bin mir nicht sicher, ob dies ein Fehler in iOS 8 ist oder was. Ich habe auch versucht, Folgendes hinzuzufügen:
scrollView.contentOffset = CGPointZero;
im Animationsblock, der nichts geändert hat.
Hat jemand irgendwelche Ideen? Jede Hilfe wäre sehr dankbar. Vielen Dank!
Ich habe die Methode mit meinem Animationsblock geändert in:
- (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;
}];
}
- (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];
}];
}
}
}
sie können dies versuchen, der Schlüssel verwendet zwei Animationen.
Um den Sprung zu entfernen, wird Ryanthons Antwort den Trick ausführen. In meiner App mit iOS9.0 ist kein Animationsblock erforderlich, um den Sprung zu entfernen. Das Zurücksetzen von contentOffset nach dem Festlegen von contentInset führt dazu.
Wenn Sie die Scrollgeschwindigkeit von tableView beim Ausblenden der Aktualisierungsansicht steuern möchten, lösen doppelte Animationsblöcke in der Antwort von user3044484 die Zauberei aus. Ein Animationsblock reicht nicht aus.
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;
}];
}];
}
Ich hatte das gleiche Problem und verschob meinen Animationsblock auf den ...
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
delegieren Sie stattdessen die Methode. Nicht perfekt, aber ich kann das Problem noch nicht genau bestimmen. Sieht aus wie scrollViews -layoutSubviews
Methode wird unter iOS8 häufiger aufgerufen, was zu nervösen Animationen führt.
Zwei Lösungen:
Ich habe beschlossen durch: -
- Deaktivieren Sie die Absprungfunktion, wenn ContentInset auf contentOffsetY aktualisiert wird.
- Behalten Sie den Überblick über contentOffset und Update auf 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)
}
}
animieren in - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
funktioniert leider nicht für mich. Der Scrollview springt trotzdem ab.
Laut Bounds ändert sich automatisch in UIScrollView mit Content-Insets das scheint mir ein iOS8-Bug.