Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing sliding side menu with XCoordinator #216

Open
DaliborK opened this issue Dec 22, 2021 · 2 comments
Open

Implementing sliding side menu with XCoordinator #216

DaliborK opened this issue Dec 22, 2021 · 2 comments

Comments

@DaliborK
Copy link

DaliborK commented Dec 22, 2021

Hi, I really like this framework and would like to use it for navigating with a side menu, however, I'm stuck with its implementation into a container beside a sideMenu controller. Or would be possible to create an animation style for sliding the existing controller and showing the menu? Can you please advise on a possible way how to implement it?

@jaron-m-lowe
Copy link

You would need to implement your own container view controller (ie. SlideMenuController) that manages two child view controllers: a bottom (menu) and top (current screen) Your container view controller would need to have some ability to open/close the menu.

Once you have that setup you would need to do the following:

  1. Create your own SlideMenuCoordinator inherited from BaseCoordinator. Your rootViewController would be your SlideMenuController type.
  2. Create your own SlideMenuTransition based on Transition, adding open and close options for the transitions types available.
  3. Use your coordinator like normal!

@farshadmb
Copy link

@DaliborK Hi bro

Recently, I developed the feature you want using REFrostedViewController and XCoordinator. so, I want to share with you and the rest of the communities that used this framework.

you have to create one main coordinator and a side menu coordinator.

import XCoordinator
import REFrostedViewController
import RxSwift

enum MainRoute: Route {
    case initial
    case side
    case action(Destination)
}

final class MainCoordinator: BaseCoordinator<MainRoute, Transition<REFrostedViewController>> {

    required init(route: RouteType? = .initial, factory: FactoryType) {
        self.factory = factory
        super.init(rootViewController: REFrostedViewController(), initialRoute: .initial)
        prepareRootViewController()
    }

    override func prepareTransition(for route: RouteType) -> TransitionType {
        do {
            switch route {
            case .initial:
                let mainViewController = MainViewController()
                rootViewController.contentViewController = mainViewController

                mainViewController.sideMenuButton.rx.tap
                    .bind(with: self) { (this, _) in
                        this.trigger(.side)
                    }.disposed(by: disposeBag)

                return .none()
            case .side:

                var sideMenuVC = rootViewController.menuViewController as? SideMenuViewController

                if rootViewController.menuViewController == nil {
                    sideMenuVC = SideMenuViewController()
                    rootViewController.menuViewController = sideMenuVC

                    sideMenuVC?.viewModel?.didSelectItem.debounce(.microseconds(200))
                        .asObservable()
                        .bind(with: self, onNext: { (this, destination) in
                            this.rootViewController.hideMenuViewController {
                                this.trigger(.action(destination))
                            }
                        }).disposed(by: disposeBag)
                }

                rootViewController.presentMenuViewController()

                return .none()
            case .action(let destination):
                let coordinator = SideMenuCoordinator(rootViewController: rootViewController)
                return .route(destination.menuRoute(), on: coordinator)
            }
        }catch let error {
            log.error(error, tag: Self.self)
            return .none()
        }
    }

    private func prepareRootViewController() {
        rootViewController.direction = .left
        rootViewController.liveBlur = false
        rootViewController.animationDuration = 0.25
        rootViewController.liveBlurBackgroundStyle = .dark
        rootViewController.blurRadius = 10.0
        rootViewController.blurTintColor = .primaryGray
        rootViewController.blurSaturationDeltaFactor = 0.5
        let width = UIScreen.main.bounds.width * 0.863_111_1
        rootViewController.limitMenuViewSize = true
        rootViewController.menuViewSize = CGSize(width: width, height: 0)
    }

}

the SideMenuCoordinatoor would be

enum MenuRoute: Route {
    case inbox
    case unknown
}

final class SideMenuCoordinatoor: BaseCoordinator<MenuRoute, Transition<UIViewController>> {

    deinit {
        log.verbose("Deinit \(Self.self)", tag: Self.self)
    }

   override func prepareTransition(for route: MenuRoute) -> TransitionType {
        switch (route) {
        case .inbox:
            let coordinator = InboxCoordinator()
            return .presentOnRoot(coordinator, animation: .default)
        case .unknown:
            return .none()
        }
    }
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants