UICollectionView는 IndexPath에서 셀로 자동 스크롤


101

컬렉션 뷰를로드하기 전에 사용자는 컬렉션 뷰 배열의 이미지 수를 설정합니다. 모든 셀이 화면에 맞지 않습니다. 30 개의 셀이 있고 화면에는 6 개만 있습니다.

질문 : UICollectionView로드시 원하는 이미지가있는 셀로 자동으로 스크롤하는 방법은 무엇입니까?

답변:


90

viewWillAppear컬렉션보기가 아직 레이아웃을 완료하지 않았기 때문에 스크롤이 안정적으로 작동하지 않을 수 있음을 발견 했습니다. 잘못된 항목으로 스크롤 할 수 있습니다.

또한 스크롤 viewDidAppear을하면 스크롤되지 않은 뷰가 일시적으로 깜박이 는 것을 발견했습니다 .

그리고을 (를) 통해 매번 스크롤하면 viewDidLayoutSubviews일부 컬렉션 레이아웃으로 인해 스크롤 할 때마다 하위보기 레이아웃이 발생하기 때문에 사용자가 수동으로 스크롤 할 수 없습니다.

내가 찾은 결과는 다음과 같습니다.

목표 C :

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    // If we haven't done the initial scroll, do it once.
    if (!self.initialScrollDone) {
        self.initialScrollDone = YES;

        [self.collectionView scrollToItemAtIndexPath:self.myInitialIndexPath
                                    atScrollPosition:UICollectionViewScrollPositionRight animated:NO];
    }
}

빠른 :

 override func viewWillLayoutSubviews() {

    super.viewWillLayoutSubviews()

      if (!self.initialScrollDone) {

         self.initialScrollDone = true
         self.testNameCollectionView.scrollToItem(at:selectedIndexPath, at: .centeredHorizontally, animated: true)
    }

}

좋은 팁. initialScrollDone이 메서드는 두 번 이상 호출되고 scrollToItemAtIndexPath를 호출하면 LenK가 한 것처럼 플래그를 사용하는 것을 강조 하겠습니다. scrollToItemAtIndexPath : 두 번 이상 collectionView를 스크롤 할 수 없게 렌더링하는 것 같습니다 (iOS 시뮬레이터 iPhone 5 / iOS 8)
maz

1
iOS8에서 잘 작동합니다. 받아 들여진 대답이어야합니다.
Nick

5
이것은 iOS 8.3에서 작동하지 않았습니다. [self.collectionView layoutIfNeeded];이전 에 전화 해야했는데 viewDidLoad.
Brent Dillingham

1
이것은 확실히 받아 들여진 대답이어야합니다. 위의 대답은 첫 번째 셀이 표시되고 새 셀로 업데이트 될 때 플래시를주었습니다.이 방법은 원활하게 전환됩니다.
simon_smiley 2015-06-18

이것은 iOS 9에서도 작동하며 자동 레이아웃을 엉망으로 만들지 않습니다.
Mr. Zystem 2015

168

새로 수정 된 답변 :

이것을 추가하십시오 viewDidLayoutSubviews

빠른

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    let indexPath = IndexPath(item: 12, section: 0)
    self.collectionView.scrollToItem(at: indexPath, at: [.centeredVertically, .centeredHorizontally], animated: true)
}

보통 .centerVertically의 경우는

ObjC

-(void)viewDidLayoutSubviews {
   [super viewDidLayoutSubviews];
    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:12 inSection:0];
   [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically | UICollectionViewScrollPositionCenteredHorizontally animated:NO];
}

이전 iOS에서 작동하는 이전 답변

이것을 추가하십시오 viewWillAppear:

[self.view layoutIfNeeded];
[self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];

4
그것이 바로 제가 사용하려는 것입니다. 배열에있는 개체의 번호가 있고 해당 개체의 이름을 알고 있습니다. 하지만 올바른 indexPath를 입력하는 방법을 모르겠습니다 ... 어떤 아이디어라도?
AlexanderZ

4
당신은 쉽게 만들 수 있습니다 indexPath:[NSIndexPath indexPathForItem:numberOfTheObject inSection:sectionNumber]
boweidmann

3
약간의 오류가있었습니다. 하지만 언급 된 모든 코드를 (void) viewDidLayoutSubviews {} 안에 넣었고 이제는 잘 작동합니다. 고맙습니다 Bogdan.
AlexanderZ

1
셀을 '확대'하고 확대 표시하려면 어떻게해야합니까?
fatuhoku 2014

9
이것은 iOS 7.1에서 안정적으로 작동하지 않으며 컬렉션보기가 검은 색 화면으로 나타날 수 있습니다. 또한 아래 viewDidLayoutSubviews의 솔루션과 같은 상태를 유지하고 싶지 않았습니다. 내가 단순히 수행했다 [self.view 것은 layoutIfNeeded] 바로 scrollToItemAtIndexPath 호출하기 전에
다니엘 Galasko

15

위의 답변에 전적으로 동의합니다. 유일한 것은 솔루션이 viewDidAppear에 코드를 설정했다는 것입니다.

viewDidAppear 
{
    [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
}

viewWillAppear를 사용했을 때 스크롤이 작동하지 않았습니다.


2
viewDidAppear는 컬렉션 뷰가 움직이고 / 깜박이는 것을 볼 수 있다는 단점이 있습니다. 뷰가 이미 나타났습니다 (이름에서 알 수 있듯이) ... 왜 Apple이 이례적인 경우가 아닌 좋은 방식으로 설계하지 않았는지 궁금합니다. viewDidLayoutSubviews 방식은 다음과 같습니다. a는 어색한 비트
TheEye

12

이것은 나를 위해 작동하는 것처럼 보였으며 다른 답변과 비슷하지만 몇 가지 뚜렷한 차이점이 있습니다.

- (void)viewDidLayoutSubviews
{     
   [self.collectionView layoutIfNeeded];
   NSArray *visibleItems = [self.collectionView indexPathsForVisibleItems];
   NSIndexPath *currentItem = [visibleItems objectAtIndex:0];
   NSIndexPath *nextItem = [NSIndexPath indexPathForItem:someInt inSection:currentItem.section];

   [self.collectionView scrollToItemAtIndexPath:nextItem atScrollPosition:UICollectionViewScrollPositionNone animated:YES];
}

12

빠른:

your_CollectionView.scrollToItemAtIndexPath(indexPath, atScrollPosition: UICollectionViewScrollPosition.CenteredHorizontally, animated: true)

스위프트 3

let indexPath = IndexPath(row: itemIndex, section: sectionIndex)

collectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.right, animated: true)

스크롤 위치 :

UICollectionViewScrollPosition.CenteredHorizontally / UICollectionViewScrollPosition.CenteredVertically

9

GCD를 사용하여 viewDidLoad의 다음 반복 메인 런 루프로 스크롤을 디스패치하여이 동작을 달성 할 수 있습니다. 컬렉션보기가 화면에 표시되기 전에 스크롤이 수행되므로 깜박이지 않습니다.

- (void)viewDidLoad {
    dispatch_async (dispatch_get_main_queue (), ^{
        NSIndexPath *indexPath = YOUR_DESIRED_INDEXPATH;
        [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:NO];
    });
}

위치가 3 일 때 indexpath를 얻는 방법?
kemdo

5

나는 그것을하고 추천 할 것입니다 collectionView: willDisplay:당신이 컬렉션 뷰 대리인이 뭔가를 제공하는 것을 확신 할 수 있습니다 그럼. 여기 내 예 :

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    /// this is done to set the index on start to 1 to have at index 0 the last image to have a infinity loop
    if !didScrollToSecondIndex {
        self.scrollToItem(at: IndexPath(row: 1, section: 0), at: .left, animated: false)
        didScrollToSecondIndex = true
    }
}

1
willDisplay 대신 didEndDisplaying을 사용하는 것이 제대로 작동하는 방법이라는 것을 알았습니다. 셀이 화면에있는 한 willDisplay는 괜찮 았습니다. 그러나 셀이 아직 화면에 없으면이 방법으로 스크롤하지 않았습니다. didEndDisplaying은 해당 사용 사례에서 완벽하게 작동했습니다. 저를 올바른 길로 안내해 주신 귀하의 답변에 감사드립니다!
C6Silver

2

위에서 언급 한 대안으로. 데이터로드 후 호출 :

빠른

collectionView.reloadData()
collectionView.layoutIfNeeded()
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .right)

1

여기에 모든 답변-해킹. relaodData :
서브 클래스 컬렉션 뷰 레이아웃 을 사용한 후 어딘가에서 컬렉션 뷰를 스크롤하는 더 좋은 방법을 찾았습니다. 어떤 레이아웃을 사용하든 prepareLayout 메서드를 재정의하고, 슈퍼 호출 후 필요한 오프셋을 설정했습니다.
예 : https://stackoverflow.com/a/34192787/1400119

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.