3

I disable views rotation (process when Hebrew language is selected and all views change their positions from left to right) when phone has RightToLeft localization:

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"9.0")){
    if (RightToLeft) {
        [[UIView appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
        [[UINavigationBar appearance] setSemanticContentAttribute:UISemanticContentAttributeForceLeftToRight];
    }
}

Everything looks fine, but I need to swipe right-to-left to return in previous view controller. How can I set left to right swipe direction for navigation between ViewControllers?

Konstantin.Efimenko
  • 1,242
  • 1
  • 14
  • 38

2 Answers2

6

I finally got one working for those who subclassed the UINavigationController class. You should do something like this :

final class TestNavigationController: UINavigationController, UINavigationControllerDelegate {

    override func viewDidLoad() {
         super.viewDidLoad()
         self.delegate = self
    }

    func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {
         navigationController.view.semanticContentAttribute = UIView.isRightToLeft() ? .forceRightToLeft : .forceLeftToRight
         navigationController.navigationBar.semanticContentAttribute = UIView.isRightToLeft() ? .forceRightToLeft : .forceLeftToRight
    }
}

extension UIView {

    static func isRightToLeft() -> Bool {
        return UIView.appearance().semanticContentAttribute == .forceRightToLeft
    }
}

Dynamically, your NavigationController will adapt to the forced semantic content attribute. I hope it helps. Let me know if you have any problems.

Tom
  • 373
  • 3
  • 13
0

I found the solution for it after searching long time, if someone seeks.

The previous answer may cause the UI to hang / freeze.

The reason that the UI freezes / hangs is because the UINavigationController is missing a check for the root view controller when the gesture is executed on the root view. There a few ways to fix that, the following is what I did.

You should subclass UINavigationController, this is the right way to go and add implement as followed:

class RTLNavController: UINavigationController, UINavigationControllerDelegate, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        //  Adding swipe to pop viewController
        self.interactivePopGestureRecognizer?.isEnabled = true
        self.interactivePopGestureRecognizer?.delegate = self

        //  UINavigationControllerDelegate
        self.delegate = self
    }
    
    func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
        navigationController.view.semanticContentAttribute = UIView.isRightToLeft() ? .forceRightToLeft : .forceLeftToRight
        navigationController.navigationBar.semanticContentAttribute = UIView.isRightToLeft() ? .forceRightToLeft : .forceLeftToRight
    }

    //  Checking if the viewController is last, if not disable the gesture
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        if self.viewControllers.count > 1 {
            return true
        }
        
        return false
    }
}

extension UIView {
    static func isRightToLeft() -> Bool {
        return UIView.appearance().semanticContentAttribute == .forceRightToLeft
    }
}

Resources:

Original question:

The answer is used for the solution:

Other solution which may work better (But it's in Objective-C):

And of course using some of this question ideas.

ytpm
  • 4,962
  • 6
  • 56
  • 113