Меню боковой панели слайдов IOS 8 Swift

Есть ли способ реализовать меню боковой панели слайдов (например, приложение Facebook) в IOS Swift без какой-либо сторонней библиотеки? Я ищу решения, но я только основал эту функцию, реализованную в Objective-C.

Ответ 1

Я считаю, что вы можете запустить форму UISplitViewController, которая была резко обновлена ​​в iOS8. Наблюдайте за сеансами Просмотр улучшений контроллера в iOS8 и Создание адаптивных приложений с помощью UIKit. Они обеспечивают пример кода со второго сеанса (но не образуют первую:/). На данный момент для меня естественно создать такой пользовательский интерфейс, основанный на контроллере разделенного вида в iOS8.

Обновление: похоже, что не все API, о которых они говорят, все еще приземляются. В текущем бета-версии 4, упомянутой в видеоконденсатах, BarsOnSwipe не представляется, например.

Ответ 2

Обновить. Пожалуйста, используйте мой обновленный ответ, а не этот. Там много крайних случаев с помощью подхода Scrollview/Container View, которого можно избежать, используя вместо этого Custom Transiler Transitions.

Я смотрел повсюду для решения меню Swift, которое не требовало библиотеки. Закончилось создание собственного учебника, которое довольно похоже на подход Fengson:

введите описание изображения здесь

Вот некоторые из основных моментов:

  • Создайте scrollview, который будет обрабатывать перемещение меню, а также жест панорамы
  • Поместите два представления container рядом друг с другом, внутри scrollview. Контейнеры позволяют встроить контроллеры верхнего уровня.
  • На scrollview установите paging enabled, но отключите bounces. Это приведет к принудительному выходу в открытое или закрытое состояние.
  • embed a UITableViewController в левом контейнере
  • embed a UITabBarController в правом контейнере
  • Справа container добавьте атрибут runtime layer.shadowOpacity 0,8. Это дает вам свободный разделитель теней без кода.
  • Добавить кнопку меню. Вы можете использовать NSNotificationCenter для связи с scrollview
  • Для секретного ингредиента: используйте scrollView.setContentOffset.x, чтобы позаботиться о фактическом открытии и закрытии меню.

Вот пример рабочего проекта приложения панели вкладок с левым меню выведения, включая скриншоты и инструкции.

https://github.com/ThornTechPublic/LeftSlideoutMenu

Наряду с более общим объяснением того, как это работает:

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

Ответ 3

Меню боковой панели слайдов для iOS7 и iOS8, Swift.

Если вы хотите, чтобы он находился на уровне NavigationController (это означает, что для него все остальные контроллеры):

https://github.com/evnaz/ENSwiftSideMenu

Если вы хотите его просто в одном ViewController:

Видео: https://www.youtube.com/watch?v=qaLiZgUK2T0

Исходный код: http://goo.gl/ULWxJh

В этом случае для совместимости с iOS7 просто добавьте это условие "если", где размещен комментарий "Добавить размытие", например:

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

Ответ 4

Я думаю, что использование Custom View Controller Transitions - прочный подход для создания меню выноса:

  • Вы можете настроить анимацию.
  • Переход является интерактивным, поэтому вы можете перемещаться вперед и назад. Переход всегда заканчивается или откатывается назад и никогда не застревает между состояниями.
  • Для управления взаимодействием используются жесты и жесты экрана. Это означает, что вы можете разместить их стратегически, чтобы минимизировать конфликт с горизонтальным жестовым контентом.
  • Вам не нужно прибегать к Container Views. Это означает, что ваша архитектура приложения более плоская, и вы можете использовать протокол-делегат вместо NSNotifications.
  • Только один монитор ViewController активен одновременно. Снимки используются, чтобы дать иллюзию, что на экране есть второй VC.

интерактивный слайд анимированный GIF

Пользовательский контроллер просмотра Переходы трудно освоить сначала (они были для меня, по крайней мере). Я написал сообщение в блоге о том, как создать интерактивное меню выноса и старался изо всех сил сделать его максимально понятным.

Вы также можете перейти прямо в код на GitHub.

На очень высоком уровне, вот как это работает:

  • Вы открываете меню слайдов как модальное.
  • Вы создаете пользовательские анимации для настоящих и отклоняете переходы с использованием протокола UIViewControllerAnimatedTransitioning. Вы используете моментальный снимок для представления главного контроллера представления во время анимации.
  • Вы создаете распознаватели жеста, чтобы представить/отклонить модально интерактивно.
  • Вы переносите события "Жест" в объект UIPercentDrivenInteractiveTransition, чтобы синхронизация осуществлялась с помощью движений пользователя.
  • Представляющий контроллер использует протокол UIViewControllerTransitioningDelegate и подключает все пользовательские анимации и интерактивные переходы.

На самом деле у меня есть предыдущий ответ в этом потоке, который использует Scrollview/Container View. Этот подход подходит для прототипа, но он запускается во множество случаев и ошибок при создании готового приложения. Проводя каждую неделю, отвечая на комментарии в блоге и фиксируя крайние случаи, мотивировал меня написать вторую запись в блоге по этому вопросу.

Ответ 5

Здесь другая библиотека SideMenu, которую я добавил, чтобы добавить в микс: https://github.com/jonkykong/SideMenu.

Простое управление боковым меню для iOS в Swift, вдохновленное Facebook. Правильно и левой стороны. Кодирование не требуется.

  • Он может быть реализован в раскадровке без единой строки кода.
  • Четыре стандартных стили анимации на выбор (даже параллакс, если вы хотите получить странный).
  • Высоко настраиваемый без необходимости писать тонны настраиваемого кода.
  • Поддерживает непрерывную прокрутку между боковыми меню с обеих сторон одним жестом.
  • Глобальная конфигурация меню. Настройте один раз и сделайте все экраны.
  • Меню могут быть представлены и отклонены так же, как и любой другой контроллер просмотра, поскольку этот элемент управления использует настраиваемые переходы.

Ответ 6

Вот небольшой пример того, как я это делаю, этот элемент управления ячеек имеет uiviewcontrollers для левого, центрального и правого. Это работает как приложение Slack IPad, где открыта одна или другая сторона.

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

    // This is where you set the drawer size (i.e. for 1/3rd use 3.0, for 1/5 use 5.0)
    var drawerSize:CGFloat = 4.0
    var leftViewControllerIdentifier:String = "LeftController"
    var centerViewControllerIdentifier:String = "CenterController"
    var rightViewControllerIdentifier:String = "RightController"

    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 NVMDrawerOpenLeft = 0
    static let NVMDrawerOpenRight = 1
    var openSide:Int {
        get{
            return _openSide;
        }
    }
    private var _openSide:Int = NVMDrawerOpenLeft

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

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

        // Call configDrawers() and pass the drawerSize variable.
        drawDrawers(UIScreen.mainScreen().bounds.size)

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

    }

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

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - Drawing View

    func drawDrawers(size:CGSize) {
        // Calculate Center View Size
        let centerWidth = (size.width/drawerSize) * (drawerSize - 1)

        // Left Drawer
        leftViewController.view.frame = CGRect(x: 0.0, y: 0.0, width: size.width/drawerSize, height: size.height)

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

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

        // Capture the Swipes
        let swipeRight = UISwipeGestureRecognizer(target: self, action: Selector("swipeRightAction:"))
        swipeRight.direction = .Right
        centerViewController.view.addGestureRecognizer(swipeRight)

        let swipeLeft = UISwipeGestureRecognizer(target: self, action: Selector("swipeLeftAction:"))
        swipeLeft.direction = .Left
        centerViewController.view.addGestureRecognizer(swipeLeft)

        if(openSide == NVMDrawerController.NVMDrawerOpenLeft){
            openLeftDrawer()
        }
        else{
            openRightDrawer()
        }
    }

    // MARK: - Open Drawers

    func openLeftDrawer() {
        _openSide = NVMDrawerController.NVMDrawerOpenLeft
        UIView.animateWithDuration(0.1, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations:
            { () -> Void in
                // move views here
                self.view.frame = CGRect(x: 0.0, y: 0.0, width: self.view.bounds.width, height: self.view.bounds.height)
            }, completion:
            { finished in
        })
    }

    func openRightDrawer() {
        _openSide = NVMDrawerController.NVMDrawerOpenRight
        UIView.animateWithDuration(0.1, delay: 0, options: UIViewAnimationOptions.CurveEaseIn, animations:
            { () -> Void in
                // move views here
                self.view.frame = 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)
            }, completion:
            { finished in
        })
    }

    // MARK: - Swipe Handling

    func swipeRightAction(rec: UISwipeGestureRecognizer){
        self.openLeftDrawer()
    }

    func swipeLeftAction(rec:UISwipeGestureRecognizer){
        self.openRightDrawer()
    }

    // MARK: - Helpers

    func instantiateViewControllers(storyboardID: String) -> UIViewController {
        if let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("\(storyboardID)") as? UIViewController{
            return viewController;
        }

        return UIViewController();
    }
}

Ответ 7

Я реализовал его двумя способами.
Сначала используйте Scroll View и второй, используя Container Views.

Вы можете использовать TableViewController как меню в одном контейнере и TabBarController со скрытыми вкладками во втором контейнере. Нажатие a Cell в представлении таблицы перемещает вас на n-ю вкладку в панели вкладок.

Все, что вам нужно сделать, - это анимировать верхний контейнер прямо при нажатии кнопки или в жесте. Тогда это может выглядеть так:

enter image description here

То, что аккуратно, - это то, что вы можете легко добавить интересные эффекты, такие как анимация UIView с помощью демпфирования spring, используя встроенные методы, чтобы придать ему реалистичный бодрый эффект. Вы также можете добавить тень к своему основному представлению (не добавленному на картинке), чтобы сделать его похожим на страницу над меню.