Jak przewinąć UIScrollView do góry?
Jak przewinąć UIScrollView do góry?
Odpowiedzi:
[self.scrollView setContentOffset:
CGPointMake(0, -self.scrollView.contentInset.top) animated:YES];
[self.scrollView setContentOffset:CGPointZero animated:YES];
lub jeśli chcesz zachować poziomą pozycję przewijania i po prostu zresetować pozycję pionową:
[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, 0)
animated:YES];
[scrollView setContentOffset:CGPointMake(0, -scrollView.contentInset.top) animated:YES];
Działa na iOS 6 i 7
[scrollView setContentOffset:CGPointMake(0, scrollView.contentSize.height-scrollView.frame.size.height) animated:YES];
Oto rozszerzenie Swift, które to ułatwia:
extension UIScrollView {
func scrollToTop() {
let desiredOffset = CGPoint(x: 0, y: -contentInset.top)
setContentOffset(desiredOffset, animated: true)
}
}
Stosowanie:
myScrollView.scrollToTop()
spróbuj pracować z nowym adjustedContentInset
.
Na przykład (przewiń do góry):
var offset = CGPoint(
x: -scrollView.contentInset.left,
y: -scrollView.contentInset.top)
if #available(iOS 11.0, *) {
offset = CGPoint(
x: -scrollView.adjustedContentInset.left,
y: -scrollView.adjustedContentInset.top)
}
scrollView.setContentOffset(offset, animated: true)
Nawet jeśli używasz
prefersLargeTitles
,safe area
etc.
Dla Swift 4
scrollView.setContentOffset(.zero, animated: true)
Posługiwać się setContentOffset:animated:
[scrollView setContentOffset:CGPointZero animated:YES];
W iOS7 miałem problem z uzyskaniem określonego widoku przewijania na górę, który działał w iOS6, i użyłem tego do ustawienia widoku przewijania na górę.
[self.myScroller scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
Odpowiedź Roba Mayoffa w Swift 3.0.1 :
self.scrollView.setContentOffset(
CGPoint(x: 0,y: -self.scrollView.contentInset.top),
animated: true)
Aby w pełni odtworzyć zachowanie scrollToTop paska stanu, musimy nie tylko ustawić contentOffset, ale także upewnić się, że wskaźniki scrollIndicators są wyświetlane. W przeciwnym razie użytkownik może szybko się zgubić.
Jedyną publiczną metodą osiągnięcia tego jest flashScrollIndicators
. Niestety, wywołanie go raz po ustawieniu contentOffset nie daje żadnego efektu, ponieważ jest resetowane natychmiast. Zauważyłem, że działa, gdy wykonuję flashowanie za każdym razem w scrollViewDidScroll:
.
// define arbitrary tag number in a global constants or in the .pch file
#define SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG 19291
- (void)scrollContentToTop {
[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];
self.scrollView.tag = SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.scrollView.tag = 0;
});
}
W swoim UIScrollViewDelegate (lub UITable / UICollectionViewDelegate) zaimplementuj to:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView.tag == SCROLLVIEW_IS_SCROLLING_TO_TOP_TAG) {
[scrollView flashScrollIndicators];
}
}
Opóźnienie ukrywania jest nieco krótsze w porównaniu do zachowania scrollToTop paska stanu, ale nadal wygląda ładnie.
Zauważ, że nadużywam tagu widoku do komunikowania stanu „isScrollingToTop”, ponieważ potrzebuję tego między kontrolerami widoku. Jeśli używasz tagów do czegoś innego, możesz zamienić to na iVar lub właściwość.
Myślę, że mam odpowiedź, która powinna być w pełni kompatybilna z iOS 11, a także wcześniejszymi wersjami (do przewijania w pionie)
Uwzględnia to nowy dostosowany zestaw treści, a także dodatkowe przesunięcie wymagane, gdy preferowane są duże tytuły jest włączona navigationBar który wydaje się wymagać dodatkowego 52px offsetowy na szczycie, co domyślnie jest
Było to trochę trudne, ponieważ dostosowanyContentInset zmienia się w zależności od stanu titleBar (duży tytuł vs mały tytuł), więc musiałem sprawdzić i zobaczyć, jaka była wysokość titleBar i nie zastosować przesunięcia 52px, jeśli jest już w stanie dużym. Nie mogłem znaleźć innej metody sprawdzenia stanu paska nawigacji, więc jeśli ktoś ma lepszą opcję niż sprawdzenie, czy wysokość jest> 44,0, chciałbym to usłyszeć
func scrollToTop(_ scrollView: UIScrollView, animated: Bool = true) {
if #available(iOS 11.0, *) {
let expandedBar = (navigationController?.navigationBar.frame.height ?? 64.0 > 44.0)
let largeTitles = (navigationController?.navigationBar.prefersLargeTitles) ?? false
let offset: CGFloat = (largeTitles && !expandedBar) ? 52: 0
scrollView.setContentOffset(CGPoint(x: 0, y: -(scrollView.adjustedContentInset.top + offset)), animated: animated)
} else {
scrollView.setContentOffset(CGPoint(x: 0, y: -scrollView.contentInset.top), animated: animated)
}
}
Zainspirowany rozwiązaniem Jakuba
Jest to bardzo powszechne, gdy pasek nawigacji nakłada się na małą część zawartości scrollView i wygląda na to, że treść nie zaczyna się od góry. Aby to naprawić, zrobiłem 2 rzeczy:
Przewiń do góry za UITableViewController
, UICollectionViewController
lub dowolny UIViewController
koniecznościUIScrollView
extension UIViewController {
func scrollToTop(animated: Bool) {
if let tv = self as? UITableViewController {
tv.tableView.setContentOffset(CGPoint.zero, animated: animated)
} else if let cv = self as? UICollectionViewController{
cv.collectionView?.setContentOffset(CGPoint.zero, animated: animated)
} else {
for v in view.subviews {
if let sv = v as? UIScrollView {
sv.setContentOffset(CGPoint.zero, animated: animated)
}
}
}
}
}
W SWIFT 5 Po prostu ustaw wartość Offset na zero
scrollView.setContentOffset(CGPoint.zero, animated: true)
Próbowałem wszystkich sposobów. Ale dla mnie nic nie działało. Wreszcie mi się to podobało.
Dodałem self.view .addSubview(self.scroll)
linię kodu w viewDidLoad. Po rozpoczęciu konfigurowania ramki dla widoku przewijania i dodaniu komponentów do widoku przewijania.
U mnie to zadziałało.
Upewnij się, że dodałeś self.view .addSubview(self.scroll)
linię na początku. następnie możesz dodać elementy interfejsu użytkownika.
UIScrollView
contentInset
niestety.[self.scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x, -self.scrollView.contentInset.top) animated:YES];
robi robotę za mnie