보기가 나타나기 전에 iPhone에서 UITableView의 맨 아래로 스크롤하는 방법
나는이 UITableView변수 높이의 세포로 채워된다. 뷰를 볼 때 테이블을 맨 아래로 스크롤하고 싶습니다.
나는 현재 다음과 같은 기능을 가지고 있습니다
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[log count]-1 inSection:0];
[self.table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
log는 각 셀의 내용을 구성하는 객체를 포함하는 가변 배열입니다.
위의 코드는 잘 작동 viewDidAppear하지만 뷰가 처음 나타날 때 테이블 상단을 표시 한 다음 맨 아래로 점프하면 불행한 부작용이 있습니다. table view가 나타나기 전에 하단으로 스크롤 할 수 있다면 선호합니다 .
내가 스크롤을 시도 viewWillAppear하고 viewDidLoad있지만, 두 경우 모두 데이터가 테이블에로드 아직 예외를 던져 모두되지 않았습니다.
내가 가진 것이 가능한 전부라고 말한 경우에도 모든 지침은 대단히 감사하겠습니다.
나는 부름 [table setContentOffset:CGPointMake(0, CGFLOAT_MAX)]이 당신이 원하는 것을 할 것이라고 믿습니다 .
에서 야곱의 대답 이 코드는 다음과 같습니다
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (self.messagesTableView.contentSize.height > self.messagesTableView.frame.size.height)
{
CGPoint offset = CGPointMake(0, self.messagesTableView.contentSize.height - self.messagesTableView.frame.size.height);
[self.messagesTableView setContentOffset:offset animated:YES];
}
}
가장 쉬운 방법은 다음과 같습니다.
if (self.messages.count > 0)
{
[self.tableView
scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.messages.count-1
inSection:0]
atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
스위프트 3 버전 :
if messages.count > 0 {
userDefinedOptionsTableView.scrollToRow(at: IndexPath(item:messages.count-1, section: 0), at: .bottom, animated: true)
}
컨텐츠의 정확한 끝으로 스크롤해야하는 경우 다음과 같이 수행 할 수 있습니다.
- (void)scrollToBottom
{
CGFloat yOffset = 0;
if (self.tableView.contentSize.height > self.tableView.bounds.size.height) {
yOffset = self.tableView.contentSize.height - self.tableView.bounds.size.height;
}
[self.tableView setContentOffset:CGPointMake(0, yOffset) animated:NO];
}
자동 레이아웃을 사용하고 있으며 아무런 대답도 없습니다. 마침내 작동 한 내 솔루션은 다음과 같습니다.
@property (nonatomic, assign) BOOL shouldScrollToLastRow;
- (void)viewDidLoad {
[super viewDidLoad];
_shouldScrollToLastRow = YES;
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
// Scroll table view to the last row
if (_shouldScrollToLastRow)
{
_shouldScrollToLastRow = NO;
[self.tableView setContentOffset:CGPointMake(0, CGFLOAT_MAX)];
}
}
@JacobRelkin 이 승인 한 솔루션은 자동 레이아웃을 사용하는 iOS 7.0에서 작동하지 않았습니다.
사용자 정의 하위 클래스가 UIViewController있고 _tableView의 하위 뷰로 인스턴스 변수 를 추가 했습니다 view. 나는 위치 _tableView자동 레이아웃을 사용하여. 나는이 메소드를 마지막 viewDidLoad과 끝에서 호출하려고 시도 했다 viewWillAppear:. 둘 다 일하지 않았다.
그래서의 사용자 정의 하위 클래스에 다음 메소드를 추가했습니다 UIViewController.
- (void)tableViewScrollToBottomAnimated:(BOOL)animated {
NSInteger numberOfRows = [_tableView numberOfRowsInSection:0];
if (numberOfRows) {
[_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:numberOfRows-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:animated];
}
}
작품 [self tableViewScrollToBottomAnimated:NO]의 끝에서 전화 viewDidLoad. 불행히도 tableView:heightForRowAtIndexPath:모든 셀에 대해 세 번 호출됩니다.
다음은 Swift 2.0에서 구현 한 확장입니다. 이 함수는 tableview로드 된 후에 호출해야합니다 .
import UIKit
extension UITableView {
func setOffsetToBottom(animated: Bool) {
self.setContentOffset(CGPointMake(0, self.contentSize.height - self.frame.size.height), animated: true)
}
func scrollToLastRow(animated: Bool) {
if self.numberOfRowsInSection(0) > 0 {
self.scrollToRowAtIndexPath(NSIndexPath(forRow: self.numberOfRowsInSection(0) - 1, inSection: 0), atScrollPosition: .Bottom, animated: animated)
}
}
}
세부
- Xcode 8.3.2, 신속한 3.1
- Xcode 10.2 (10E125), 스위프트 5
암호
import UIKit
extension UITableView {
func scrollToBottom(animated: Bool) {
let y = contentSize.height - frame.size.height
if y < 0 { return }
setContentOffset(CGPoint(x: 0, y: y), animated: animated)
}
}
용법
tableView.scrollToBottom(animated: true)
전체 샘플
솔루션 코드를 붙여 넣는 것을 잊지 마십시오!
import UIKit
class ViewController: UIViewController {
private weak var tableView: UITableView?
private lazy var cellReuseIdentifier = "CellReuseIdentifier"
override func viewDidLoad() {
super.viewDidLoad()
let tableView = UITableView(frame: view.frame)
view.addSubview(tableView)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
self.tableView = tableView
tableView.dataSource = self
tableView.performBatchUpdates(nil) { [weak self] result in
if result { self?.tableView?.scrollToBottom(animated: true) }
}
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath )
cell.textLabel?.text = "\(indexPath)"
return cell
}
}
실제로 신속하게 수행하는 "Swifter"방법은 다음과 같습니다.
var lastIndex = NSIndexPath(forRow: self.messages.count - 1, inSection: 0)
self.messageTableView.scrollToRowAtIndexPath(lastIndex, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true)
나를 위해 완벽합니다.
프레임에 표시된 테이블의 끝으로 테이블을로드하고 싶었습니다. 나는
NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0] - 1) inSection:0];
[[self tableView] scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
테이블 높이가 프레임 높이보다 작을 때 오류가 발생하여 작동하지 않았습니다. 내 테이블에는 섹션이 하나만 있습니다.
나를 위해 일한 솔루션은 viewWillAppear에서 다음 코드를 구현하는 것입니다.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// on the initial cell load scroll to the last row (ie the latest Note)
if (initialLoad==TRUE) {
initialLoad=FALSE;
NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([self.tableView numberOfRowsInSection:0] - 1) inSection:0];
[[self tableView] scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:NO];
CGPoint offset = CGPointMake(0, (1000000.0));
[self.tableView setContentOffset:offset animated:NO];
}
}
BOOL ivar initialLoad는 viewDidLoad에서 TRUE로 설정됩니다.
스위프트
if tableView.contentSize.height > tableView.frame.size.height {
let offset = CGPoint(x: 0, y: tableView.contentSize.height - tableView.frame.size.height)
tableView.setContentOffset(offset, animated: false)
}
UITableViewScrollPositionBottom대신 사용해야 합니다.
스위프트 3 (Xcode 8.1)의 경우 :
override func viewDidAppear(_ animated: Bool) {
let numberOfSections = self.tableView.numberOfSections
let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1)
let indexPath = IndexPath(row: numberOfRows-1 , section: numberOfSections-1)
self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.middle, animated: true)
}
물론 버그입니다. 아마도 코드 어딘가에 있습니다 table.estimatedRowHeight = value(예 : 100). 이 값을 행 높이가 얻을 수있는 최대 값 ( 예 : 500)으로 바꾸십시오. 이렇게하면 다음 코드와 함께 문제가 해결됩니다.
//auto scroll down example
let delay = 0.1 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), {
self.table.scrollToRowAtIndexPath(NSIndexPath(forRow: self.Messages.count - 1, inSection: 0), atScrollPosition: UITableViewScrollPosition.Bottom, animated: false)
})
위의 솔루션을 사용하면 테이블 맨 아래로 스크롤됩니다 (테이블 내용이 먼저로드 된 경우에만).
//Scroll to bottom of table
CGSize tableSize = myTableView.contentSize;
[myTableView setContentOffset:CGPointMake(0, tableSize.height)];
After a lot of fiddling this is what worked for me:
var viewHasAppeared = false
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if !viewHasAppeared { goToBottom() }
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
viewHasAppeared = true
}
private func goToBottom() {
guard data.count > 0 else { return }
let indexPath = NSIndexPath(forRow: data.count - 1, inSection: 0)
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: .Bottom, animated: false)
tableView.layoutIfNeeded()
}
The key turned out to be not wrapping scrollToRowAtIndexPath inside of dispatch_async as some have suggested, but simply following it with a call to layoutIfNeeded.
My understanding of this is, calling the scroll method in the current thread guarantees that the scroll offset is set immediately, before the view is displayed. When I was dispatching to the main thread, the view was getting displayed for an instant before the scroll took effect.
(Also NB you need the viewHasAppeared flag because you don't want to goToBottom every time viewDidLayoutSubviews is called. It gets called for example whenever the orientation changes.)
In Swift 3.0
self.tableViewFeeds.setContentOffset(CGPoint(x: 0, y: CGFLOAT_MAX), animated: true)
If you have to load the data asynchronously prior to scrolling down, here's the possible solution:
tableView.alpha = 0 // We want animation!
lastMessageShown = false // This is ivar
viewModel.fetch { [unowned self] result in
self.tableView.reloadData()
if !self.lastMessageShown {
dispatch_async(dispatch_get_main_queue()) { [unowned self] in
if self.rowCount > 0 {
self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.rowCount, inSection: 0), atScrollPosition: .Bottom, animated: false)
}
UIView.animateWithDuration(0.1) {
self.tableView.alpha = 1
self.lastMessageShown = true // Do it once
}
}
}
}
Function on swift 3 scroll to bottom
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(false)
//scroll down
if lists.count > 2 {
let numberOfSections = self.tableView.numberOfSections
let numberOfRows = self.tableView.numberOfRows(inSection: numberOfSections-1)
let indexPath = IndexPath(row: numberOfRows-1 , section: numberOfSections-1)
self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.middle, animated: true)
}
}
func scrollToBottom() {
let sections = self.chatTableView.numberOfSections
if sections > 0 {
let rows = self.chatTableView.numberOfRows(inSection: sections - 1)
let last = IndexPath(row: rows - 1, section: sections - 1)
DispatchQueue.main.async {
self.chatTableView.scrollToRow(at: last, at: .bottom, animated: false)
}
}
}
you should add
DispatchQueue.main.async {
self.chatTableView.scrollToRow(at: last, at: .bottom, animated: false)
}
or it will not scroll to bottom.
Use this simple code to scroll tableView bottom
NSInteger rows = [tableName numberOfRowsInSection:0];
if(rows > 0) {
[tableName scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:rows-1 inSection:0]
atScrollPosition:UITableViewScrollPositionBottom
animated:YES];
}
Thanks Jacob for the answer. really helpfull if anyone interesting with monotouch c# version
private void SetScrollPositionDown() {
if (tblShoppingListItem.ContentSize.Height > tblShoppingListItem.Frame.Size.Height) {
PointF offset = new PointF(0, tblShoppingListItem.ContentSize.Height - tblShoppingListItem.Frame.Size.Height);
tblShoppingListItem.SetContentOffset(offset,true );
}
}
In iOS this worked fine for me
CGFloat height = self.inputTableView.contentSize.height;
if (height > CGRectGetHeight(self.inputTableView.frame)) {
height -= (CGRectGetHeight(self.inputTableView.frame) - CGRectGetHeight(self.navigationController.navigationBar.frame));
}
else {
height = 0;
}
[self.inputTableView setContentOffset:CGPointMake(0, height) animated:animated];
It needs to be called from viewDidLayoutSubviews
[self.tableViewInfo scrollRectToVisible:CGRectMake(0, self.tableViewInfo.contentSize.height-self.tableViewInfo.height, self.tableViewInfo.width, self.tableViewInfo.height) animated:YES];
The accepted answer didn't work with my table (thousands of rows, dynamic loading) but the code below works:
- (void)scrollToBottom:(id)sender {
if ([self.sections count] > 0) {
NSInteger idx = [self.sections count] - 1;
CGRect sectionRect = [self.tableView rectForSection:idx];
sectionRect.size.height = self.tableView.frame.size.height;
[self.tableView scrollRectToVisible:sectionRect animated:NO];
}
}
No need for any scrolling you can just do it by using this code:
[YOURTABLEVIEWNAME setContentOffset:CGPointMake(0, CGFLOAT_MAX)];
If you are setting up frame for tableview programmatically, make sure you are setting frame correctly.
In Swift, you just need
self.tableView.scrollToNearestSelectedRowAtScrollPosition(UITableViewScrollPosition.Bottom, animated: true)
to make it automatically scroll to the buttom
In swift 3.0 If you want to go any particular Cell of tableview Change cell index Value like change "self.yourArr.count" value .
self.yourTable.reloadData()
self.scrollToBottom()
func scrollToBottom(){
DispatchQueue.global(qos: .background).async {
let indexPath = IndexPath(row: self.yourArr.count-1, section: 0)
self.tblComment.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
I believe old solutions do not work with swift3.
If you know number rows in table you can use :
tableView.scrollToRow(
at: IndexPath(item: listCountInSection-1, section: sectionCount - 1 ),
at: .top,
animated: true)
'Programming' 카테고리의 다른 글
| 오른쪽에 안드로이드 확인란을 표시하는 방법은 무엇입니까? (0) | 2020.07.01 |
|---|---|
| ViewPager를 사용하여 Google Maps V2를 조각에 배치하는 방법 (0) | 2020.07.01 |
| PHP로 파일을 업로드 할 때 $ _FILES가 비어있는 이유는 무엇입니까? (0) | 2020.07.01 |
| “라이브러리를 찾을 수 없습니다”오류 (0) | 2020.07.01 |
| 일상 생활에서 가장 유용한 스크립트는 무엇입니까? (0) | 2020.07.01 |