it-swarm.com.ru

UIScrollView прокрутить вниз программно

Как я могу сделать прокрутку UIScrollView вниз в моем коде? Или в более общем смысле, в любой точке подпредставления?

262
nico

Вы можете использовать функцию setContentOffset:animated: в UIScrollView для прокрутки к любой части представления содержимого. Вот некоторый код, который прокручивается вниз, при условии, что ваш scrollView - 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];

Надеюсь, это поможет!

585
Ben Gotow

Быстрая версия принятого ответа для легкого копирования копии: 

let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height)
scrollView.setContentOffset(bottomOffset, animated: true)
89
Esqarrouth

Самое простое решение:

[scrollview scrollRectToVisible:CGRectMake(scrollview.contentSize.width - 1,scrollview.contentSize.height - 1, 1, 1) animated:YES];
49
Hai Hw

Просто улучшение существующего ответа.

CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height - self.scrollView.bounds.size.height + self.scrollView.contentInset.bottom);
[self.scrollView setContentOffset:bottomOffset animated:YES];

Он также заботится о нижней вставке (если вы используете ее для настройки вида прокрутки, когда клавиатура видна)

25
vivek241

Неправильно задано смещение содержимого по высоте размера содержимого: оно прокручивает нижнюю часть содержимого до top представления прокрутки и, таким образом, скрывается.

Правильное решение состоит в том, чтобы прокрутить нижнюю часть содержимого до нижнего представления прокрутки, например так (sv - это 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];
}
19
matt

Решение Swift 2.2, учитывающее contentInset

let bottomOffset = CGPoint(x: 0, y: scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)

Это должно быть в расширении

extension UIScrollView {

  func scrollToBottom() {
    let bottomOffset = CGPoint(x: 0, y: contentSize.height - bounds.size.height + contentInset.bottom)
    setContentOffset(bottomOffset, animated: true)
  }
}

Обратите внимание, что вы можете проверить, если bottomOffset.y > 0 перед прокруткой

15
onmyway133

Пролистать наверх

- CGPoint topOffset = CGPointMake(0, 0);
- [scrollView setContentOffset:topOffset animated:YES];

Прокрутить до низа

- CGPoint bottomOffset = CGPointMake(0, scrollView.contentSize.height - self.scrollView.bounds.size.height);
 - [scrollView setContentOffset:bottomOffset animated:YES];
13
Waseem

Быстрая реализация: 

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)
  }
}

Вы называете расширение следующим образом:

yourScrollview.scrollToBottom(animated: true)
11
duan

Что если contentSize ниже, чем bounds

Для Свифта это: 

scrollView.setContentOffset(CGPointMake(0, max(scrollView.contentSize.height - scrollView.bounds.size.height, 0) ), animated: true)
10
Bartłomiej Semańczyk

Я также нашел другой полезный способ сделать это в случае, если вы используете UITableview (который является подклассом UIScrollView):

[(UITableView *)self.view scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
7
nico

Использование функции setContentOffset:animated: в UIScrollView для прокрутки вниз в Swift.

let bottomOffset : CGPoint = CGPointMake(0, scrollView.contentSize.height - scrollView.bounds.size.height + scrollView.contentInset.bottom)
scrollView.setContentOffset(bottomOffset, animated: true)
6
Kim

С (необязательным) footerView и contentInset решение:

CGPoint bottomOffset = CGPointMake(0, _tableView.contentSize.height - tableView.frame.size.height + _tableView.contentInset.bottom);
if (bottomOffset.y > 0) [_tableView setContentOffset: bottomOffset animated: YES];
5
Pieter

валдыр, надеюсь это тебе поможет

CGPoint bottomOffset = CGPointMake(0, [textView contentSize].height - textView.frame.size.height);

if (bottomOffset.y > 0)
 [textView setContentOffset: bottomOffset animated: YES];
3
Misha

Категория на помощь!

Добавьте это к общему заголовку утилиты где-нибудь:

@interface UIScrollView (ScrollToBottom)
- (void)scrollToBottomAnimated:(BOOL)animated;
@end

А затем к этой реализации утилиты:

@implementation UIScrollView(ScrollToBottom)
- (void)scrollToBottomAnimated:(BOOL)animated
{
     CGPoint bottomOffset = CGPointMake(0, self.contentSize.height - self.bounds.size.height);
     [self setContentOffset:bottomOffset animated:animated];
}
@end

Затем реализуйте его, где хотите, например:

[[myWebView scrollView] scrollToBottomAnimated:YES];
2
BadPirate

Если вам не нужна анимация, это работает:

[self.scrollView setContentOffset:CGPointMake(0, CGFLOAT_MAX) animated:NO];
1
Krys Jurgowski

В то время как решение Matt мне кажется правильным, вам необходимо принять во внимание также вкладку представления коллекции, если она была настроена.

Адаптированный код будет:

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];
}
1
tiguero

Хороший способ обеспечить видимость нижней части вашего контента - использовать формулу:

contentOffsetY = MIN(0, contentHeight - boundsHeight)

Это гарантирует, что нижний край вашего контента всегда находится на уровне нижнего края представления или над ним. MIN(0, ...) требуется, потому что UITableView (и, вероятно, UIScrollView) обеспечивает contentOffsetY >= 0, когда пользователь пытается прокрутить, явно щелкая contentOffsetY = 0. Это выглядит довольно странно для пользователя.

Код для реализации этого:

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];
}
1
jjrscott

Решение для прокрутки до последнего элемента таблицы View: 

Свифт 3:

if self.items.count > 0 {
        self.tableView.scrollToRow(at:  IndexPath.init(row: self.items.count - 1, section: 0), at: UITableViewScrollPosition.bottom, animated: true)
}
1
MarionFlex

Я обнаружил, что contentSize на самом деле не отражает фактический размер текста, поэтому при попытке прокрутки вниз он будет немного отключен. Лучший способ определить фактический размер контента - это использовать метод NSLayoutManager's usedRectForTextContainer::

UITextView *textView;
CGSize textSize = [textView.layoutManager usedRectForTextContainer:textView.textContainer].size;

Чтобы определить, сколько текста на самом деле отображается в UITextView, вы можете рассчитать его, вычтя вставки текстового контейнера из высоты рамки.

UITextView *textView;
UIEdgeInsets textInsets = textView.textContainerInset;
CGFloat textViewHeight = textView.frame.size.height - textInsets.top - textInsets.bottom;

Тогда становится легко прокручиваться:

// 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;

Некоторые цифры для справки о том, что разные размеры представляют для пустой 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)
0
mikeho
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];
0
8suhas

Xamarin.iOS версия принятого ответа 

var bottomOffset = new CGPoint (0,
     scrollView.ContentSize.Height - scrollView.Frame.Size.Height
     + scrollView.ContentInset.Bottom);

scrollView.SetContentOffset (bottomOffset, false);
0
Abdur

Xamarin.iOS версия для UICollectionView принятого ответа для простоты копирования и вставки

var bottomOffset = new CGPoint (0, CollectionView.ContentSize.Height - CollectionView.Frame.Size.Height + CollectionView.ContentInset.Bottom);          
CollectionView.SetContentOffset (bottomOffset, false);
0
Abdur

У меня не получилось, когда я попытался использовать его в UITableViewController на self.tableView(iOS 4.1), после добавления footerView. Он прокручивается за границы, показывая черный экран.

Альтернативное решение:

 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];
0
valdyr

В Свифте:

   if self.mainScroll.contentSize.height > self.mainScroll.bounds.size.height {
        let bottomOffset = CGPointMake(0, self.mainScroll.contentSize.height - self.mainScroll.bounds.size.height);
        self.mainScroll.setContentOffset(bottomOffset, animated: true)
    }
0
Ponja