Odpowiedzi:
Możesz użyć funkcji UIScrollView, setContentOffset:animated:
aby przewinąć do dowolnej części widoku zawartości. Oto kod, który przewinąłby do dołu, zakładając, że scrollView to self.scrollView
:
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];
Mam nadzieję, że to pomaga!
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
contentSize
jest niższy niż bounds
. Tak powinno być:scrollView.setContentOffset(CGPointMake(0, max(scrollView.contentSize.height - scrollView.bounds.size.height, 0) ), animated: true)
let bottomOffsetY = max(collectionView.contentSize.height - collectionView.bounds.height + collectionView.contentInset.bottom, 0)
Szybka wersja zaakceptowanej odpowiedzi do łatwego wklejania kopii:
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height)
scrollView.setContentOffset(bottomOffset, animated: true)
Najprostsze rozwiązanie:
[scrollview scrollRectToVisible:CGRectMake(scrollview.contentSize.width - 1,scrollview.contentSize.height - 1, 1, 1) animated:YES];
Tylko rozszerzenie istniejącej odpowiedzi.
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];
Dba również o dolną wstawkę (na wypadek, gdybyś używał jej do dostosowania widoku przewijania, gdy klawiatura jest widoczna)
Ustawienie przesunięcia zawartości do wysokości rozmiaru zawartości jest nieprawidłowe: przewija dolną część zawartości do góry widoku przewijania, a tym samym poza zasięg wzroku.
Prawidłowym rozwiązaniem jest przewinięcie dolnej części zawartości do dolnej części przewijanego widoku, tak jak to ( sv
to UIScrollView):
CGSize csz = sv.contentSize;
CGSize bsz = sv.bounds.size;
if (sv.contentOffset.y + bsz.height > csz.height) {
[sv setContentOffset:CGPointMake(sv.contentOffset.x,
csz.height - bsz.height)
animated:YES];
}
if (sv.contentOffset.y + csz.height > bsz.height) {
?
setContentOffset:
polecenie jest ważne.
Szybka implementacja:
extension UIScrollView {
func scrollToBottom(animated: Bool) {
if self.contentSize.height < self.bounds.size.height { return }
let bottomOffset = CGPoint(x: 0, y: self.contentSize.height - self.bounds.size.height)
self.setContentOffset(bottomOffset, animated: animated)
}
}
Użyj tego:
yourScrollview.scrollToBottom(animated: true)
Biorąc contentInset
pod uwagę rozwiązanie Swift 2.2
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
To powinno być rozszerzenie
extension UIScrollView {
func scrollToBottom() {
let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height + contentInset.bottom)
setContentOffset(bottomOffset, animated: true)
}
}
Pamiętaj, że możesz sprawdzić, czy bottomOffset.y > 0
przed przewinięciem
Co jeśli contentSize
jest niższy niż bounds
?
Dla Swift jest to:
scrollView.setContentOffset(CGPointMake(0, max(scrollView.contentSize.height - scrollView.bounds.size.height, 0) ), animated: true)
Przewiń na górę
- CGPoint topOffset = CGPointMake(0, 0);
- [scrollView setContentOffset:topOffset animated:YES];
Przewiń do dołu
- CGPoint bottomOffset = CGPointMake(0, scrollView.contentSize.height - self.scrollView.bounds.size.height);
- [scrollView setContentOffset:bottomOffset animated:YES];
Znalazłem również inny użyteczny sposób na zrobienie tego w przypadku korzystania z UITableview (który jest podklasą UIScrollView):
[(UITableView *)self.view scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
Korzystanie z setContentOffset:animated:
funkcji UIScrollView do przewijania w dół w Swift.
let bottomOffset : CGPoint = CGPointMake(0, scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
Wygląda na to, że wszystkie odpowiedzi tutaj nie uwzględniały bezpiecznego obszaru. Od iOS 11 iPhone X miał bezpieczny obszar. Może to wpłynąć na scrollViewcontentInset
.
W przypadku iOS 11 i nowszych, aby poprawnie przewinąć do dołu z dołączoną wstawką zawartości. Powinieneś użyć adjustedContentInset
zamiast contentInset
. Sprawdź ten kod:
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.height + scrollView.adjustedContentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.adjustedContentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];
contentOffset.x
):extension UIScrollView {
func scrollsToBottom(animated: Bool) {
let bottomOffset = CGPoint(x: contentOffset.x,
y: contentSize.height - bounds.height + adjustedContentInset.bottom)
setContentOffset(bottomOffset, animated: animated)
}
}
Bibliografia:
W przypadku (opcjonalnie) footerView
i contentInset
rozwiązaniem jest:
CGPoint bottomOffset = CGPointMake(0, _tableView.contentSize.height - tableView.frame.size.height + _tableView.contentInset.bottom);
if (bottomOffset.y > 0) [_tableView setContentOffset: bottomOffset animated: YES];
Szybki:
Możesz użyć takiego rozszerzenia:
extension UIScrollView {
func scrollsToBottom(animated: Bool) {
let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height)
setContentOffset(bottomOffset, animated: animated)
}
}
Posługiwać się:
scrollView.scrollsToBottom(animated: true)
Kategoria na ratunek!
Dodaj to do współdzielonego nagłówka narzędzia gdzieś:
@interface UIScrollView (ScrollToBottom)
- (void)scrollToBottomAnimated:(BOOL)animated;
@end
A następnie do implementacji tego narzędzia:
@implementation UIScrollView(ScrollToBottom)
- (void)scrollToBottomAnimated:(BOOL)animated
{
CGPoint bottomOffset = CGPointMake(0, self.contentSize.height - self.bounds.size.height);
[self setContentOffset:bottomOffset animated:animated];
}
@end
Następnie zaimplementuj go w dowolnym miejscu, na przykład:
[[myWebView scrollView] scrollToBottomAnimated:YES];
Dla widoku poziomego ScrollView
Jeśli podoba mi się, że ma widok poziomy ScrollView i chcesz przewinąć do jego końca (w moim przypadku do jego prawej strony), musisz zmienić niektóre części akceptowanej odpowiedzi:
Cel C
CGPoint rightOffset = CGPointMake(self.scrollView.contentSize.width - self.scrollView.bounds.size.width + self.scrollView.contentInset.right, 0 );
[self.scrollView setContentOffset:rightOffset animated:YES];
Szybki
let rightOffset: CGPoint = CGPoint(x: self.scrollView.contentSize.width - self.scrollView.bounds.size.width + self.scrollView.contentInset.right, y: 0)
self.scrollView.setContentOffset(rightOffset, animated: true)
Jeśli w jakiś sposób zmienisz scrollView contentSize (np. Dodasz coś do stackView, który znajduje się w scrollView), musisz wywołać scrollView.layoutIfNeeded()
przed przewinięciem , w przeciwnym razie nic nie zrobi.
Przykład:
scrollView.layoutIfNeeded()
let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
if(bottomOffset.y > 0) {
scrollView.setContentOffset(bottomOffset, animated: true)
}
Dobrym sposobem na zapewnienie widoczności dolnej części treści jest użycie formuły:
contentOffsetY = MIN(0, contentHeight - boundsHeight)
Dzięki temu dolna krawędź treści zawsze znajduje się na dolnej krawędzi widoku lub powyżej niej. Jest MIN(0, ...)
to wymagane, ponieważ UITableView
(i prawdopodobnie UIScrollView
) zapewnia, contentOffsetY >= 0
gdy użytkownik próbuje przewijać poprzez widoczne przyciąganie contentOffsetY = 0
. Wygląda to dość dziwnie dla użytkownika.
Kod do wdrożenia to:
UIScrollView scrollView = ...;
CGSize contentSize = scrollView.contentSize;
CGSize boundsSize = scrollView.bounds.size;
if (contentSize.height > boundsSize.height)
{
CGPoint contentOffset = scrollView.contentOffset;
contentOffset.y = contentSize.height - boundsSize.height;
[scrollView setContentOffset:contentOffset animated:YES];
}
Jeśli nie potrzebujesz animacji, działa to:
[self.scrollView setContentOffset:CGPointMake(0, CGFLOAT_MAX) animated:NO];
Chociaż Matt
rozwiązanie wydaje mi się poprawne, należy uwzględnić również wstawkę widoku kolekcji, jeśli istnieje taka, która została skonfigurowana.
Dostosowany kod będzie:
CGSize csz = sv.contentSize;
CGSize bsz = sv.bounds.size;
NSInteger bottomInset = sv.contentInset.bottom;
if (sv.contentOffset.y + bsz.height + bottomInset > csz.height) {
[sv setContentOffset:CGPointMake(sv.contentOffset.x,
csz.height - bsz.height + bottomInset)
animated:YES];
}
Rozwiązanie, aby przewinąć do ostatniego elementu tabeli Widok:
Swift 3:
if self.items.count > 0 {
self.tableView.scrollToRow(at: IndexPath.init(row: self.items.count - 1, section: 0), at: UITableViewScrollPosition.bottom, animated: true)
}
Nie działa na mnie, gdy próbowałem go używać w UITableViewController
sprawie self.tableView
(iOS 4.1)
, po dodaniufooterView
. Przewija się poza granice, pokazując czarny ekran.
Alternatywne rozwiązanie:
CGFloat height = self.tableView.contentSize.height;
[self.tableView setTableFooterView: myFooterView];
[self.tableView reloadData];
CGFloat delta = self.tableView.contentSize.height - height;
CGPoint offset = [self.tableView contentOffset];
offset.y += delta;
[self.tableView setContentOffset: offset animated: YES];
CGFloat yOffset = scrollView.contentOffset.y;
CGFloat height = scrollView.frame.size.height;
CGFloat contentHeight = scrollView.contentSize.height;
CGFloat distance = (contentHeight - height) - yOffset;
if(distance < 0)
{
return ;
}
CGPoint offset = scrollView.contentOffset;
offset.y += distance;
[scrollView setContentOffset:offset animated:YES];
Przekonałem się, że contentSize
tak naprawdę nie odzwierciedla faktycznego rozmiaru tekstu, więc przy próbie przewinięcia w dół będzie to nieco odsuwane. Najlepszym sposobem, aby określić rzeczywisty rozmiar zawartość jest rzeczywiście korzystać z NSLayoutManager
„s usedRectForTextContainer:
metody:
UITextView *textView;
CGSize textSize = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size;
Aby ustalić, ile tekstu faktycznie ma być wyświetlany UITextView
, możesz go obliczyć, odejmując wstawki kontenera tekstu od wysokości ramki.
UITextView *textView;
UIEdgeInsets textInsets = textView.textContainerInset;
CGFloat textViewHeight = textView.frame.size.height - textInsets.top - textInsets.bottom;
Następnie łatwo jest przewijać:
// if you want scroll animation, use contentOffset
UITextView *textView;
textView.contentOffset = CGPointMake(textView.contentOffset.x, textSize - textViewHeight);
// if you don't want scroll animation
CGRect scrollBounds = textView.bounds;
scrollBounds.origin = CGPointMake(textView.contentOffset.x, textSize - textViewHeight);
textView.bounds = scrollBounds;
Niektóre liczby w celach informacyjnych dotyczące różnych rozmiarów pustych UITextView
.
textView.frame.size = (width=246, height=50)
textSize = (width=10, height=16.701999999999998)
textView.contentSize = (width=246, height=33)
textView.textContainerInset = (top=8, left=0, bottom=8, right=0)
Rozszerz UIScrollView, aby dodać metodę scrollToBottom:
extension UIScrollView {
func scrollToBottom(animated:Bool) {
let offset = self.contentSize.height - self.visibleSize.height
if offset > self.contentOffset.y {
self.setContentOffset(CGPoint(x: 0, y: offset), animated: animated)
}
}
}
Wersja Xamarin.iOS dla UICollectionView
zaakceptowanej odpowiedzi ułatwiająca kopiowanie i wklejanie
var bottomOffset = new CGPoint (0, CollectionView.ContentSize.Height - CollectionView.Frame.Size.Height + CollectionView.ContentInset.Bottom);
CollectionView.SetContentOffset (bottomOffset, false);