pestañas los este con cargan asocian ios iphone objective-c uitabbarcontroller

ios - los - Toque la barra de pestañas para desplazarse hasta la parte superior de UITableViewController



los safari de este iphone se cargan y asocian con los de icloud (10)

En esta implementación no necesita variable estática y estado de controlador de vista anterior

Si su UITableViewController en UINavigationController puede implementar el protocolo y la función:

protocol ScrollableToTop { func scrollToTop() } extension UIScrollView { func scrollToTop(_ animated: Bool) { var topContentOffset: CGPoint if #available(iOS 11.0, *) { topContentOffset = CGPoint(x: -safeAreaInsets.left, y: -safeAreaInsets.top) } else { topContentOffset = CGPoint(x: -contentInset.left, y: -contentInset.top) } setContentOffset(topContentOffset, animated: animated) } }

Luego en tu UITableViewController:

class MyTableViewController: UITableViewController: ScrollableToTop { func scrollToTop() { if isViewLoaded { tableView.scrollToTop(true) } } }

Luego en UITabBarControllerDelegate:

extension MyTabBarController: UITabBarControllerDelegate { func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { guard tabBarController.selectedViewController === viewController else { return true } guard let navigationController = viewController as? UINavigationController else { assertionFailure() return true } guard navigationController.viewControllers.count <= 1, let destinationViewController = navigationController.viewControllers.first as? ScrollableToTop else { return true } destinationViewController.scrollToTop() return false } }

Al tocar el icono de la barra de pestañas del controlador de navegación actual, el usuario regresa a la vista raíz, pero si se desplazan hacia abajo, si lo tocan nuevamente, quiero que se desplace hacia la parte superior (el mismo efecto que al tocar la barra de estado). ¿Cómo haría esto?

Un buen ejemplo es la información de Instagram, desplácese hacia abajo y luego toque el ícono de inicio en la barra de pestañas para regresar a la parte superior.

El desplazamiento de vuelta a la parte superior es fácil, pero conectarlo al controlador de la barra de pestañas es lo que me atasca.


Encontré que el método scrollRectToVisible funciona mejor que setContentOffset .

Rápido:

Después de capturar el clic en la barra de pestañas del delegado, algo como a continuación:

func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) { if (viewController.isKindOfClass(SomeControllerClass) && tabBarController.selectedIndex == 0) { viewController.scrollToTop() } }

Ahora para la función scrollToTop dentro del controlador:

func scrollToTop() { self.tableView.scrollRectToVisible(CGRectMake(0,0,CGRectGetWidth(self.tableView.frame), CGRectGetHeight(self.tableView.frame)), animated: true) }


Enfoque 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 }

Algunas notas aquí: "shouldSelect" en lugar de "didSelect" porque esto último se está produciendo después de la transición, lo que significa que la variable local de viewController ya cambió. 2. Necesitamos manejar el evento antes de cambiar el controlador, para tener la información de los controladores de vista de navegación con respecto a la acción de desplazamiento (o no).

Explicación: queremos desplazarnos hacia arriba, si la vista actual es en realidad un controlador de vista de Lista / Tabla. Si la navegación ha avanzado y tocamos la misma barra de pestañas, la acción deseada sería simplemente abrir un paso (funcionalidad predeterminada) y no desplazarse hacia arriba. Si la navegación no tiene un significado avanzado, todavía estamos en el controlador de tabla / lista y solo entonces queremos desplazarnos hacia arriba al tocar de nuevo. (Lo mismo que hace Facebook al tocar "Feed" en el perfil de un usuario. Solo vuelve a feed sin desplazarse hacia arriba.


Estaba usando esta jerarquía de vistas.

UITabBarController > UINavigationController > UIViewController

UITabBarController una referencia al UITabBarController en el UIViewController

tabBarControllerRef = self.tabBarController as! CustomTabBarClass tabBarControllerRef!.navigationControllerRef = self.navigationController as! CustomNavigationBarClass tabBarControllerRef!.viewControllerRef = self

Luego creé un Bool que se llamó en los momentos correctos, y un método que permite desplazarme hacia arriba sin problemas.

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) }

Luego en mi UITabBarController Custom Class lo llamé

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() } } }

El resultado es idéntico al de Instagram y al feed de Twitter :)


He implementado un UITabBarController de plug & play que puedes reutilizar libremente en tus proyectos. Para habilitar la funcionalidad de desplazamiento hacia arriba, solo debe usar la subclase, nada más.

Debe trabajar fuera de la caja con Storyboards también.

Código:

/// A UITabBarController subclass that allows "scroll-to-top" gestures via tapping /// tab bar items. You enable the functionality by simply subclassing. class ScrollToTopTabBarController: UITabBarController, UITabBarControllerDelegate { /// Determines whether the scrolling capability''s enabled. var scrollEnabled: Bool = true private var previousIndex = 0 override func viewDidLoad() { super.viewDidLoad() delegate = self } /* Always call "super" if you''re overriding this method in your subclass. */ func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) { guard scrollEnabled else { return } guard let index = viewControllers?.indexOf(viewController) else { return } if index == previousIndex { dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), { [weak self] () in guard let scrollView = self?.iterateThroughSubviews(self?.view) else { return } dispatch_async(dispatch_get_main_queue(), { scrollView.setContentOffset(CGPointZero, animated: true) }) }) } previousIndex = index } /* Iterates through the view hierarchy in an attempt to locate a UIScrollView with "scrollsToTop" enabled. Since the functionality relies on "scrollsToTop", it plugs easily into existing architectures - you can control the behaviour by modifying "scrollsToTop" on your UIScrollViews. */ private func iterateThroughSubviews(parentView: UIView?) -> UIScrollView? { guard let view = parentView else { return nil } for subview in view.subviews { if let scrollView = subview as? UIScrollView where scrollView.scrollsToTop == true { return scrollView } if let scrollView = iterateThroughSubviews(subview) { return scrollView } } return nil } }

Editar (09.08.2016):

Después de intentar compilar con la configuración de lanzamiento predeterminada (archivo), el compilador no permitiría la posibilidad de crear una gran cantidad de cierres que se capturaron en una función recursiva, por lo que no se compilaría. Se cambió el código para devolver el primer UIScrollView encontrado con "scrollsToTop" establecido en true sin usar cierres.


Puede usar shouldSelect lugar de didSelect , lo que didSelect la necesidad de una variable externa para realizar un seguimiento del controlador de vista anterior.

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


SWIFT 3

Aquí va..

Primero implemente el UITabBarControllerDelegate en la clase y asegúrese de que el delegado esté configurado en 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 } }

A continuación, ponga esta función de delegado en algún lugar de su clase.

func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { let tabBarIndex = tabBarController.selectedIndex print(tabBarIndex) if tabBarIndex == 0 { self.collectionView.setContentOffset(CGPoint.zero, animated: true) } }

Asegúrese de seleccionar el índice correcto en la declaración "if". Incluí la función de impresión para que pueda volver a comprobar.


Tengo una vista de colección incrustada en un controlador de navegación, en Swift esto funciona.

var previousController: UIViewController? func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) { if previousController == viewController { if let navVC = viewController as? UINavigationController, vc = navVC.viewControllers.first as? UICollectionViewController { vc.collectionView?.setContentOffset(CGPointZero, animated: true) } } previousController = viewController; }


Implemente el método UITabBarControllerDelegate tabBarController: didSelectViewController: para recibir una notificación cuando el usuario seleccione una pestaña. También se llama a este método cuando se vuelve a tocar el mismo botón de pestaña, incluso si esa pestaña ya está seleccionada.

Un buen lugar para implementar este delegado probablemente sería su AppDelegate . O el objeto que lógicamente "posee" el controlador de la barra de pestañas.

Yo declararía e implementaría un método que se puede llamar en sus controladores de vista para desplazarse por la vista de colección.

- (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; }


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) } }

Esta es mi respuesta en Swift 3. Utiliza una función auxiliar para llamadas recursivas y se desplaza automáticamente a la parte superior de la llamada. Probado en un UICollectionViewController integrado en un UINavigationController incorporado en un UITabBarController