点击标签栏以滚动到UITableViewController的顶部

Jon*_*and 30 iphone objective-c uitabbarcontroller uitableview ios

点击当前导航控制器的标签栏图标已经将用户返回到根视图,但如果它们向下滚动,如果再次点击它我想要它滚动到顶部(与点击状态栏相同的效果).我该怎么做?

一个很好的例子是Instagram的feed,向下滚动然后点击标签栏中的主页图标以滚动回到顶部.

滚动回到顶部很容易,但将它连接到标签栏控制器是我坚持的.

Dru*_*erB 36

实现用户选择选项卡时要通知的UITabBarControllerDelegate方法tabBarController:didSelectViewController:.即使已选择该选项卡,再次点击相同的选项卡按钮时也会调用此方法.

实现这个的好地方delegate可能是你的AppDelegate.或逻辑上"拥有"标签栏控制器的对象.

我会声明并实现一个可以在视图控制器上调用的方法来滚动UICollectionView.

- (void)tabBarController:(UITabBarController *)tabBarController 
 didSelectViewController:(UIViewController *)viewController
{
    static UIViewController *previousController = nil;
    if (previousController == viewController) {
        // the same tab was tapped a second time
        if ([viewController respondsToSelector:@selector(scrollToTop)]) {
            [viewController scrollToTop];
        }
    }
    previousController = viewController;
}
Run Code Online (Sandbox Code Playgroud)

  • [viewController performSelector:@selector(scrollToTop)] (2认同)

小智 21

SWIFT 3

开始..

首先UITabBarControllerDelegate在类中实现,并确保在viewDidLoad中设置委托

class DesignStoryStreamVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UITabBarControllerDelegate {

 @IBOutlet weak var collectionView: UICollectionView!

 override func viewDidLoad() {
        super.viewDidLoad()

        self.tabBarController?.delegate = self

        collectionView.delegate = self
        collectionView.dataSource = self
    }
}
Run Code Online (Sandbox Code Playgroud)

接下来,将此委托函数放在您的类中的某个位置.

func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {

    let tabBarIndex = tabBarController.selectedIndex

    print(tabBarIndex)

    if tabBarIndex == 0 {
        self.collectionView.setContentOffset(CGPoint.zero, animated: true)
    }
}
Run Code Online (Sandbox Code Playgroud)

确保在"if"语句中选择正确的索引.我包含了打印功能,因此您可以仔细检查.


Jam*_*ang 6

您可以使用shouldSelect而不是didSelect,这样就不需要外部变量来跟踪前一个视图控制器。

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
    if ([viewController isEqual:self] && [tabBarController.selectedViewController isEqual:viewController]) {
        // Do custom stuff here
    }
    return YES;
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*ute 6

Swift 5:不需要在UITabBarController.

MyTabBarController.swift 中,实现tabBarController(_:shouldSelect)检测用户何时重新选择标签栏项:

protocol TabBarReselectHandling {
    func handleReselect()
}

class MyTabBarController: UITabBarController, UITabBarControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
    }

    func tabBarController(
        _ tabBarController: UITabBarController,
        shouldSelect viewController: UIViewController
    ) -> Bool {
        if tabBarController.selectedViewController === viewController,
            let handler = viewController as? TabBarReselectHandling {
            // NOTE: viewController in line above might be a UINavigationController,
            // in which case you need to access its contents
            handler.handleReselect()
        }

        return true
    }
}
Run Code Online (Sandbox Code Playgroud)

MyTableViewController.swift 中,通过将 table view 滚动到顶部来处理重新选择:

class MyTableViewController: UITableViewController, TabBarReselectHandling {
    func handleReselect() {
        tableView?.setContentOffset(.zero, animated: true)
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,您只需实现TabBarReselectHandling.


Mic*_*ael 5

我正在使用此View层次结构.

UITabBarController > UINavigationController > UIViewController


我有一个参考UITabBarControllerUIViewController

tabBarControllerRef = self.tabBarController as! CustomTabBarClass
tabBarControllerRef!.navigationControllerRef = self.navigationController as! CustomNavigationBarClass
tabBarControllerRef!.viewControllerRef = self
Run Code Online (Sandbox Code Playgroud)

然后我创建了一个Bool在正确的时间调用的方法,以及一个允许滚动到顶部的方法

var canScrollToTop:Bool = true

// Called when the view becomes available
override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    canScrollToTop = true
}

// Called when the view becomes unavailable
override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    canScrollToTop = false
}

// Scrolls to top nicely
func scrollToTop() {
    self.collectionView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}
Run Code Online (Sandbox Code Playgroud)

然后在我的UITabBarController自定义类我调用了这个

func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {

    // Allows scrolling to top on second tab bar click
    if (viewController.isKindOfClass(CustomNavigationBarClass) && tabBarController.selectedIndex == 0) {
        if (viewControllerRef!.canScrollToTop) {
            viewControllerRef!.scrollToTop()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果与Instagram和Twitter的Feed相同:)


Ale*_*tin 5

 extension UIViewController {    
    func scrollToTop() {
        func scrollToTop(view: UIView?) {
            guard let view = view else { return }

            switch view {
            case let scrollView as UIScrollView:
                if scrollView.scrollsToTop == true {
                    scrollView.setContentOffset(CGPoint(x: 0.0, y: -scrollView.contentInset.top), animated: true)
                    return
                }
            default:
                break
            }

            for subView in view.subviews {
                scrollToTop(view: subView)
            }
        }

        scrollToTop(view: self.view)
    }

}
Run Code Online (Sandbox Code Playgroud)

这是我在Swift 3中的答案。它使用辅助函数进行递归调用,并自动滚动到调用顶部。在嵌入在UITabBarController中嵌入的UINavigationController中的UICollectionViewController上测试


小智 5

Swift 3 方法::

//MARK: Properties
var previousController: UIViewController?

func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
    if self.previousController == viewController || self.previousController == nil {
        // the same tab was tapped a second time
        let nav = viewController as! UINavigationController

        // if in first level of navigation (table view) then and only then scroll to top
        if nav.viewControllers.count < 2 {
            let tableCont = nav.topViewController as! UITableViewController
            tableCont.tableView.setContentOffset(CGPoint(x: 0.0, y: -tableCont.tableView.contentInset.top), animated: true)
        }
    }
    self.previousController = viewController;
    return true
}
Run Code Online (Sandbox Code Playgroud)

这里有一些注意事项:“shouldSelect”而不是“didSelect”,因为后者是在转换之后发生的,这意味着 viewController 本地变量已经改变了。2. 我们需要在改变控制器之前处理事件,以便获得关于滚动(或不滚动)动作的导航视图控制器的信息。

说明:: 如果当前视图实际上是一个列表/表格视图控制器,我们要滚动到顶部。如果导航已经前进并且我们点击相同的标签栏,则所需的操作是仅弹出一个步骤(默认功能)而不是滚动到顶部。如果导航没有进步意味着我们仍然在表格/列表控制器中,只有这样我们才想在再次点击时滚动到顶部。(Facebook 在从用户的个人资料中点击“Feed”时所做的事情也是如此。它只会返回到 Feed 而不会滚动到顶部。