Tab의 Item 을 클릭하여 위로 스크롤

22603 단어 iOSSwifttech

개요


탭 아이콘을 눌렀을 때 자동으로 위로 스크롤

이루어지다


미리 준비하다


UItabBarController의viewController에 임의의 수량의 UINavigationController를 설정합니다
여기는 상관없으니 적당히 주십시오

스크롤 박스


우선 어떤 상태에서 스크롤하는지 정리
다음 중 하나만 스크롤 가능
  • navigationController의 루트에서 이tab의 아이콘을 클릭한 경우
  • 태그에 있는 아이콘을 클릭해도 위 이외의 경우에는 스크롤되지 않는다는 것이다.상술한 이외의 상황
  • navigationController의 루트에서 다른 탭
  • 으로 이동
  • navigationController의 루트 이외의 화면에서 같은 탭의 루트
  • 로 되돌아오기
    잠깐만, 구르는 상자가 하나밖에 없으니까 그 상자가 움직일 수 있는 조건만 적으면 돼
    스크롤 조건은
  • 현재 화면은navigationController의 루트
  • 입니다.
  • 현재 표시된 탭의 아이콘
  • 을 클릭
    그러면 하나씩 해보도록 하겠습니다.
    class ItemTapScrollTabController: UITabBarController {  //アイコンタップでスクロールさせるためのラッパークラス
        private var isRoot: Bool = false  //表示中のviewControllerがrootかどうかのフラグ
        private var currentItemIndex: Int = -1  //表示中のviewControllerのTabから見たときのインデックス
        private var nextItemIndex: Int = -1  //遷移先のviewControllerのTabから見たときのインデックス
        
        override func loadView() {
            super.loadView()
            delegate = self
        }
    }
    
    extension ItemTapScrollTabController: UITabBarControllerDelegate {
        func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
            //アイコンをタップする時に呼ばれる
            return true
        }
        func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
            //画面遷移後に呼ばれる
        }
    }
    
    로고용 속성을 만들어 내용을 넣었다
    class ItemTapScrollTabController: UITabBarController {
        private var isRoot: Bool = false
        private var currentItemIndex: Int = -1
        private var nextItemIndex: Int = -1
        
        override func loadView() {
            super.loadView()
            delegate = self
        }
    }
    
    extension ItemTapScrollTabController: UITabBarControllerDelegate {
        func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
            currentItemIndex = tabBarController.selectedIndex
            return true
        }
        func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
            nextItemIndex = tabBarController.selectedIndex
        }
    }
    
    tabBarController.selectedIndexshouldSelect에서 현재 보이는viewController의 UItabBarController를 볼 때의 인덱스,didSelect에서 이전 목적지의viewController의 UItabBarController를 볼 때의 인덱스를 가져옵니다
    class ItemTapScrollTabController: UITabBarController {
        private var isRoot: Bool = false
        private var currentItemIndex: Int = -1
        private var nextItemIndex: Int = -1
        
        override func loadView() {
            super.loadView()
            delegate = self
        }
    }
    
    extension ItemTapScrollTabController: UITabBarControllerDelegate {
        func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
            currentItemIndex = tabBarController.selectedIndex
    	if let nav = viewController as? UINavigationController,
               let current = nav.visibleViewController,
               let currentStackIdx = nav.viewControllers.firstIndex(of: current) {
                isRoot = currentStackIdx == 0
            }
            return true
        }
        func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
            nextItemIndex = tabBarController.selectedIndex
    	guard currentItemIndex == nextItemIndex, isRoot else { return }
    	//currntItemIndex == nextItemIndex → 表示中のviewControllerのタブから見たインデックスと遷移先のviewControllerのタブから見たインデックスが同じ, 表示中のタブと同じタブを選択
            //isRoot → 表示中のviewControllerがnavigationControllerのrootである
        }
    }
    
    shouldSelect의if let nav...에서 먼저
  • UINaviation Controller에 역할 할당
  • 현재 표시된viewController
  • 가져오기
  • 이view Controller가 UINaviation Controller에서 볼 때의 인덱스 가져오기
  • 진행 중
    그리고 이 인덱스가 0이면 UINaviagationController의 루트를 나타낸다. 즉, 표시된viewController는 UINavian Controller의 루트ViewController이기 때문에 isRoot을 진짜로 한다.
    다음 didSelect의 guard currentItemIndex == ...에서 상기 두 조건을 코드에 입력하십시오
    navigationController.visibleViewController입니다.
  • 다른 태그로 이동할 경우
  • shouldSelect,didSelect: 목적지를 이전하는viewController
  • 동일한 레이블의 루트로 반환되는 경우
  • shoulldSelect:viewController
  • didSelect: 목적지를 이전하는viewController
  • 이런 행위는 매우 이상하니 주의해야 한다.
    shouldSelect에서 보이는viewController를 찾으려고 하기 때문에 다른 옵션으로 이동할 때viewController를 정확하게 찾을 수 없습니다
    이 코드에서 shouldSelectvisibleViewController에서 얻은viewController도 상황에 따라 달라지지만 currentItemIndex == nextItemIndex 부분에서는 같은 탭의 이동만 처리하기 때문에 동작에 문제가 없습니다
    다시 말아서 스크롤 처리만 할게요.스크롤 처리는 UIScrollView, UItableView, UICollectionView 등 여러 구성 요소로 이루어질 수 있습니다
    protocol Scrollable {
        func scrollToTop()
    }
    
    class ViewController: UIViewController {
        private let tableView: UITableView = .init()
    }
    
    extension ViewController: Scrollable {
        func scrollToTop() {
            tableView.scrollToRow(at: .init(row: 0, section: 0), at: .top, animated: true)
        }
    }
    
    extension ItemTapScrollTabController: UITabBarControllerDelegate {
        func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
            currentItemIndex = tabBarController.selectedIndex
            if let nav = viewController as? UINavigationController,
               let current = nav.visibleViewController,
               let currentStackIdx = nav.viewControllers.firstIndex(of: current) {
                isRoot = currentStackIdx == 0
            }
            return true
        }
        func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
            nextItemIndex = tabBarController.selectedIndex
            guard currentItemIndex == nextItemIndex, isRoot else { return }
            if let nav = viewController as? UINavigationController,
               let current = nav.visibleViewController,
               let scrollable = current as? Scrollable {
                scrollable.scrollToTop()
            }
        }
    }
    

    끝맺다


    생각보다 행동이 번거롭고 대단하지만 자신이 먼저 위의 코드로 실현한다.별로 테스트를 안 해서 이상한 행동을 할 수도 있어요.
    샘플을 담고 싶은 Gif가 용량이 너무 커서 담을 수가 없어요. 그래서 GiitHub 링크를 먼저 넣을게요.
    https://github.com/hara-94/TabItemTapScroll

    참고 자료


    https://qiita.com/s_higeru/items/0fc28a890e39777d73e9

    좋은 웹페이지 즐겨찾기