iOS의 UIScrollView에서 호출이 있는 무한 스크롤

9342 단어 SwiftUIScrollViewiOS

무한 스크롤 by Josh & Eliza, 2011 WWDC

UIScrollView의 무한 스크롤을 사용한 것은 오래전부터 알고 있었다. 내가 가장 먼저 들은 것은2011년 WDC의 Josh & Eliza의 Advanced ScrollView Techniques이었다.
일반적으로 왼쪽 간격 표시와 같이 스크롤 뷰에서는 화면이 왼쪽으로 이동하지만 실제로는 시야각 포트를 오른쪽으로 이동하여 표시됩니다.다음 그림에서 보듯이 처음에는 노란색과 녹색 부분만 화면에 나타나고 왼쪽 백조를 통해 시야 포트를 오른쪽으로 이동한 다음에 노란색 부분만 화면에 나타난다.

일반적인 스크롤 막대의 경우 ContentView 가장자리에서 스크롤할 수 없습니다.

Josh & Eliza가 2011년에 소개한 무한 스크롤 기법의 요점은요.

  • 항상 조정UIScrollViewDelegate.viewDidScroll(...)UIScrollView되어 시야 포트를 중앙에 유지
  • 뷰 포트의 일반적인 동작과 반대로 중심 뷰를 이동하며 뷰 포트를 이동하지 않습니다.
  • ContentView의 유휴 섹션에 새 컨텐츠 추가
  • 그러니까

    보기 포트는 항상 ContentView의 중심이기 때문에 스크롤을 멈추지 않습니다. 프로그램이 ContentView에 새로운 내용을 제공하면 계속 스크롤할 수 있습니다.contentOffset 매번 뷰 포트를 이동할 때마다 이름이 붙고 레이아웃 전 단계에서 이름이 붙기 때문에 스크롤을 동반하는 이런 동작을 설명하기에 가장 적합하다.

    페이지 스크롤


    문제점


    조쉬&엘리자 방법은 매우 간단해서 UIScrollViewDelegate.viewDidScroll(...) 스티커 기능을 사용하지 않으면 지금도 매우 효과적이다.다만, 예를 들어 스크롤 보기를 이미지 뷰어로 사용하고자 하는 경우 등 각 페이지에서 캡처한 붙여넣기 기능을 사용하고자 한다.
    본고에서 사용한 예는 동물판'없으면'응용 프로그램(!?)이다.그리고 좌우로 그림을 굴리면 새로운 동물 캐릭터가 무작위로 표시됩니다.
    UIScrollView에는 표지UIScrollView가 있는데 그것을 isPagingEnabled로 바꾸면 굴러갈 때 각 동물의 그림에서 가볍게 멈춘다.그러나 Josh & Eliza의 무한 스크롤 기술을 사용하면 시거리 포트가 항상 ContentView의 중심에 있기 때문에 iOS로 볼 때 페이지를 전혀 이동하지 않은 것으로 착각해 붙여넣을 수 없다.

    해결책


    기본적인 아이디어는 조쉬&엘리자의 것을 사용하는 것으로, 변경의 관건으로'시야를 자주 조절할 필요가 없다'는 아이디어를 내놨다.Josh & Eliza는 매번 true 조정하고 있다.실제로 조정해야 할 시기는 다음과 같은 두 가지뿐이다.
  • 오른쪽으로 스크롤하고 다음 페이지의 텐트가 시야 포트의 다수를 차지할 때
  • 왼쪽으로 스크롤하고 앞 페이지의 제어 텐트가 시야 포트의 다수를 차지할 때
  • 오른쪽으로 스크롤하여 n+1 페이지가 다수로 변경되는 경우:

    왼쪽으로 스크롤하여 n-1페이지가 다수로 변경되는 경우:

    시간당 1페이지의 보기 포트를 엇갈려 다음 페이지를 채우면 된다.페이지 경계에서 스크롤이 정상적이기 때문에 페이지도 유효합니다.
    코드 예는 다음과 같습니다.
        func scrollViewDidScroll(_ scrollView: UIScrollView) {
            let offsetX = scrollView.contentOffset.x
    
            if (offsetX > scrollView.frame.size.width * 1.5) {
                // 1. モデルをアップデート。n-1 ページ目を削除して, n+2 ページ目を追加
                let newImage = fetcher.fetchRandomImage()
                images.remove(at: 0)
                images.append(newImage)
                // 2. 後述。n ページ目から n+2 ページのフレーム設定
                layoutImages()
                // 3. ビューポートの調整
                scrollView.contentOffset.x -= scrollViewSize.width
            }
    
            if (offsetX < scrollView.frame.size.width * 0.5) {
                // 1. モデルをアップデート。n+1 ページ目を削除して, n-2 ページ目を追加
                let newImage = fetcher.fetchRandomImage()
                images.removeLast()
                images.insert(newImage, at: 0)
                // 2. 後述。n-2 ページ目から n ページのフレーム設定
                layoutImages()
                // 3. ビューポートの調整
                scrollView.contentOffset.x += scrollViewSize.width
            }
        }
    
    각 페이지의 프레임을 설정할 코드는 다음과 같습니다.
        private func layoutImages() {
            imageViews.enumerated().forEach { (index: Int, imageView: UIImageView) in
                imageView.image = images[index]
                imageView.frame = CGRect(x: scrollViewSize.width * CGFloat(index),
                                         y: 0,
                                         width: scrollViewSize.width,
                                         height: scrollViewSize.height)
            }
        }
    

    총결산

    scrollViewDidScroll(...)에서 무한 스크롤을 실현하려면 붙일 필요가 없을 때UIScrollView에서 매번 조정UIScrollViewDelegate.scrollViewDidScroll(...)과ContentView의 프레임워크로 실현할 수 있다.
    그러나 붙여넣기가 필요하더라도 조정하는 시간을 단축해 같은 방법을 사용할 수 있다.
    아마도 contentOffset 같은 것을 사용해도 될 것 같지만, 나는 UIPageViewController 세계에서만 실현할 수 있는 이 방법을 좋아한다.자원으로서 현재의 페이지 + 정도의 페이지를 준비하면 됩니다. 친환경 w에 가장 적합합니다.
    그리고 지원 장치의 회전은 좀 복잡해지지만 이 점코드 여기 있어요.에도 포함된다.
    이번 안드로이드에서 비슷한 일을 하는 절차를 알아보고 싶습니다.

    좋은 웹페이지 즐겨찾기