web-dev-qa-db-fra.com

Slide Sidebar Menu IOS 8 Swift

Existe-t-il un moyen d'implémenter le menu latéral de la diapositive (comme l'application Facebook) dans IOS Swift sans bibliothèque tierce? Je cherche des solutions mais je ne les ai que fondées fonctionnalité implémentée dans Objective-C.

38
Naldo Lopes

Je crois que vous pouvez commencer à utiliser le formulaire UISplitViewController, qui a été mis à jour de manière drastique dans iOS8. Observez les sessions Afficher les avancées du contrôleur dans iOS8 et Création d'applications adaptatives avec UIKit pour plus de détails. Ils fournissent exemple de code de la seconde session (mais pas la première: /). À ce stade, il me semble naturel de créer ce type d’UI basé sur le contrôleur de vue fractionnée sous iOS8.

Mise à jour: il semble que toutes les API dont ils parlent ne sont pas encore terminées. Dans la version bêta actuelle mentionnée dans la vidéo condensesBarsOnSwipe n'est pas présenté, par exemple.

17
Ilya Belikin

Mise à jour : Veuillez envisager d’utiliser ma réponse mise à jour plutôt que celle-ci. De nombreux cas Edge avec l'approche Vue de défilement/Vue de conteneur peuvent être évités en utilisant plutôt les transitions Contrôleur de vues personnalisées.

J'ai cherché partout une solution de menu Swift qui ne nécessitait pas de bibliothèque. J'ai fini par créer mon propre tutoriel, ce qui est assez similaire à l'approche de Fengson:

enter image description here

Voici quelques points principaux:

  • Créez un scrollview qui gérera le mouvement de glissement du menu, ainsi que le mouvement de panoramique
  • Placez deux container vues côte à côte, à l'intérieur de la scrollview. Les conteneurs vous permettent d'intégrer des contrôleurs de niveau supérieur.
  • Sur le scrollview, définissez paging enabled mais désactive bounces. Cela contraindra le coulisseau à un état ouvert ou fermé
  • embed a UITableViewController dans le conteneur de gauche
  • embed a UITabBarController dans le bon conteneur
  • A droite container, ajoutez un attribut d'exécution layer.shadowOpacity de 0,8. Cela vous donne un séparateur d'ombre libre sans code.
  • Ajouter un bouton de menu. Vous pouvez utiliser NSNotificationCenter pour communiquer avec le scrollview
  • Pour l'ingrédient secret: utilisez scrollView.setContentOffset.x s'occuper de l'ouverture et de la fermeture du menu

Voici un exemple de projet de travail d’une application de barre d’onglet avec un menu déroulant de gauche, y compris des captures d’écran et des instructions.

https://github.com/ThornTechPublic/LeftSlideoutMen

Avec une explication plus générique de la façon dont cela fonctionne:

http://www.thorntech.com/2015/06/want-to-implement-a-slideout-menu-in-votre-Swift-app-heres-how/

16
Robert Chen

Faites glisser les menus de la barre latérale pour iOS7 et iOS8, Swift codé.).

Si vous le voulez au niveau de NavigationController (cela signifie, pour tous les contrôleurs View situés derrière):

https://github.com/evnaz/ENSwiftSideMen

Si vous le souhaitez en un seul ViewController :

Vidéo: https://www.youtube.com/watch?v=qaLiZgUK2T

Code source: http://goo.gl/ULWxJh

Dans ce cas, pour la compatibilité iOS7, ajoutez simplement cette condition "si" où le commentaire "Ajouter une vue floue" est placé, comme ceci:

if (NSClassFromString("UIVisualEffectView") != nil) {        
    // Add blur view
    let blurView:UIVisualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.Light))
    blurView.frame = sideBarContainerView.bounds
    sideBarContainerView.addSubview(blurView)
}
9
Luismi

Je pense que l’utilisation de Custom View Controller Transitions est une approche solide pour créer des menus coulissants:

  • Vous pouvez personnaliser l'animation.
  • La transition est interactive, vous pouvez donc faire glisser pour avancer et revenir en arrière. La transition se termine ou s'annule toujours et ne se coince jamais entre les États.
  • Vous utilisez les gestes panoramiques et les gestes panoramiques au bord de l'écran pour piloter l'interaction. Cela signifie que vous pouvez les placer de manière stratégique pour minimiser les conflits avec le contenu gesté horizontalement.
  • Vous n'avez pas à recourir aux vues de conteneur. Cela signifie que l'architecture de votre application est plus plate et que vous pouvez utiliser un délégué de protocole au lieu de NSNotifications.
  • Un seul ViewController est actif à la fois. Les instantanés sont utilisés pour donner l’illusion qu’il y a une seconde VC à l’écran.

interactive slide out animated GIF

Les transitions de contrôleur de vue personnalisées sont difficiles à apprendre au début (elles l'étaient pour moi, du moins). J'ai écrit un article de blog sur la création d'un menu coulissant interactif, et j'ai essayé de mon mieux pour le rendre aussi facile à comprendre que possible.

Vous pouvez également sauter directement dans le code sur GitHub .

Voici comment cela fonctionne à un très haut niveau:

  1. Vous ouvrez le menu coulissant en tant que modal.
  2. Vous créez des animations personnalisées pour les transitions présentes et ignorees à l'aide du protocole UIViewControllerAnimatedTransitioning. Vous utilisez un instantané pour représenter le contrôleur de vue principal pendant les animations.
  3. Vous créez des reconnaisseurs de mouvement de panoramique pour présenter/rejeter le modal de manière interactive.
  4. Vous câblez les événements Pan Gesture à un objet UIPercentDrivenInteractiveTransition pour que la transition reste synchronisée avec les mouvements de l'utilisateur.
  5. Le contrôleur de présentation adopte le protocole UIViewControllerTransitioningDelegate et connecte toutes les animations personnalisées et les transitions interactives.

J'ai en fait une réponse précédente sur ce fil qui utilise une vue Scrollview/Container. Cette approche convient à un prototype, mais rencontre de nombreux cas et bogues Edge lors de la préparation de la production de votre application. Ce qui m'a motivé à rédiger un deuxième article de blog sur le sujet, c'est de passer chaque semaine à répondre aux commentaires des blogs et à résoudre les problèmes qui se présentent à Edge.

8
Robert Chen

Voici une autre bibliothèque SideMenu que j'ai créée pour ajouter au mélange: https://github.com/jonkykong/SideMen .

Contrôle de menu latéral simple pour iOS dans Swift inspiré de Facebook. Côtés droit et gauche. Aucun codage requis.

  • Il peut être implémenté dans le storyboard sans une seule ligne de code.
  • Quatre styles d'animation standard au choix (même la parallaxe si vous voulez devenir bizarre).
  • Très personnalisable sans avoir besoin d'écrire des tonnes de code personnalisé.
  • Prend en charge le balayage continu entre les menus latéraux des deux côtés en un seul geste.
  • Configuration globale du menu. Installez-le une fois pour tous les écrans.
  • Les menus peuvent être présentés et supprimés de la même manière que n'importe quel autre contrôleur de vue, car ce contrôle utilise des transitions personnalisées.

6
jonkykong

Voici un petit exemple de la façon dont je le fais. Ce contrôle de tiroir a des contrôleurs uiview pour la gauche, le centre et la droite. Celui-ci fonctionne comme l'application Slack IPad où l'un ou l'autre côté est ouvert.

/*
 To use simply instantiate SlidingDrawerController as your root view in your AppDelegate, or in the
 StoryBoard.
 Once SlidingDrawerController is instantiated, set the drawerSize of the SlidingDrawerController,
 and its leftViewControllerIdentifier, centerViewControllerIdentifier, and
 rightViewControllerIdentifier to the Storyboard Identifier of the UIViewController
 you want in the different locations.
 */

class SlidingDrawerController: UIViewController {
    var drawerSize:CGFloat = 4.0
    var leftViewControllerIdentifier:String = "leftViewController"
    var centerViewControllerIdentifier:String = "centerViewController"
    var rightViewControllerIdentifier:String = "rightViewController"

    enum Drawers {
        case left
        case right
    }

    private var _leftViewController:UIViewController?
    var leftViewController:UIViewController {
        get{
            if let vc = _leftViewController {
                return vc;
            }
            return UIViewController();
        }
    }
    private var _centerViewController:UIViewController?
    var centerViewController:UIViewController {
        get{
            if let vc = _centerViewController {
                return vc;
            }
            return UIViewController();
        }
    }
    private var _rightViewController:UIViewController?
    var rightViewController:UIViewController {
        get{
            if let vc = _rightViewController {
                return vc;
            }
            return UIViewController();
        }
    }

    static let SlidingDrawerOpenLeft = 1
    static let SlidingDrawerOpenRight = 2
    var openSide:SlidingDrawerController.Drawers {
        get{
            return _openSide;
        }
    }
    private var _openSide = SlidingDrawerController.Drawers.left

    override func viewDidLoad() {
        super.viewDidLoad()

        // Instantiate VC's with storyboard ID's
        self._leftViewController = self.instantiateViewControllers(storyboardID: self.leftViewControllerIdentifier)
        self._centerViewController = self.instantiateViewControllers(storyboardID: self.centerViewControllerIdentifier)
        self._rightViewController = self.instantiateViewControllers(storyboardID: self.rightViewControllerIdentifier)

        self.drawDrawers(size: UIScreen.main.bounds.size)

        self.view.addSubview(self.leftViewController.view)
        self.view.addSubview(self.centerViewController.view)
        self.view.addSubview(self.rightViewController.view)
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        coordinator.animateAlongsideTransition(in: self.view, animation: { (UIViewControllerTransitionCoordinatorContext) -> Void in
            // This is for beginning of transition
            self.drawDrawers(size: size)
        }, completion: { (UIViewControllerTransitionCoordinatorContext) -> Void in
            // This is for after transition has completed.
        })

    }

    // MARK: - Drawing View

    func drawDrawers(size:CGSize) {
        // Calculate Center View's Size
        let centerWidth = (size.width/drawerSize) * (drawerSize - 1)
        // Left Drawer
        self.leftViewController.view.frame = CGRect(x: 0.0, y: 0.0, width: size.width/self.drawerSize, height: size.height)

        // Center Drawer
        self.centerViewController.view.frame = CGRect(x: self.leftViewController.view.frame.width, y: 0.0, width: centerWidth, height: size.height)

        // Right Drawer
        self.rightViewController.view.frame = CGRect(x: self.centerViewController.view.frame.Origin.x + self.centerViewController.view.frame.size.width, y: 0.0, width: size.width/self.drawerSize, height: size.height)

        // Capture the Swipes
        let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.swipeRightAction(rec:)))
        swipeRight.direction = .right
        centerViewController.view.addGestureRecognizer(swipeRight)

        let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(self.swipeLeftAction(rec:)))
        swipeLeft.direction = .left
        centerViewController.view.addGestureRecognizer(swipeLeft)

        openDrawer(openSide)
    }

    // MARK: - Open Drawers
    func openDrawer(_ side:Drawers) {
        self._openSide = side
        var rect:CGRect
        switch side{
        case .left:
            rect = CGRect(
                x: 0.0,
                y: 0.0,
                width: self.view.bounds.width,
                height: self.view.bounds.height
            )
        case .right:
            rect = CGRect(
                x: self.view.bounds.Origin.x - self.leftViewController.view.bounds.size.width,
                y: 0.0,
                width: self.view.bounds.width,
                height: self.view.bounds.height
            )
        }
        UIView.animate(withDuration: 0.1, delay: 0, options: UIViewAnimationOptions.curveEaseIn, animations:
            { () -> Void in
                // move views here
                self.view.frame = rect
        }, completion:
            { finished in
        })
    }

    // MARK: - Swipe Handling

    @objc func swipeRightAction(rec: UISwipeGestureRecognizer){
        self.openDrawer(.left)
    }

    @objc func swipeLeftAction(rec:UISwipeGestureRecognizer){
        self.openDrawer(.right)
    }

    // MARK: - Helpers

    func instantiateViewControllers(storyboardID: String) -> UIViewController {
        return UIStoryboard(name: "Main", bundle: nil)
                .instantiateViewController(withIdentifier: "\(storyboardID)")

    }
}

Source ici .

Image ici .

Vidéo ici .

5
Popmedic

Je l'ai mis en œuvre de 2 manières.
D'abord en utilisant Scroll View et second avec Container Views.

Vous pouvez avoir TableViewController agir en tant que menu dans un conteneur et un TabBarController avec des onglets masqués dans un second conteneur. En appuyant sur un Cell dans une vue de tableau, vous accédez à un nième onglet de la barre d'onglets.

Tout ce que vous avez à faire est d’animer le conteneur en haut à la droite sur un clic de bouton ou un geste. Cela peut alors ressembler à ceci:

enter image description here

Ce qui est bien, c’est que vous pouvez ensuite facilement ajouter des effets sympas, tels que l’animation d’UIView à l’aide de l’amortissement printanier, à l’aide des méthodes intégrées permettant d’obtenir un effet dynamique et rebondissant. Vous pouvez également ajouter une ombre à votre vue principale (non ajoutée dans l'image) pour la faire ressembler à une page au-dessus du menu.

3
Fengson