I would like to use NSDirectionalEdgeInsets
to UIButton
's contentEdgeInsets
and titleEdgeInsets
. Is that possible?
For localization purposes, an iOS application may be required to adapt to both Left-To-Right and Right-To-Left languages when setting up a component's insets.
Apple introduced NSDirectionalEdgeInsets
with iOS11, unfortunately this was applied to few properties only like directionalLayoutMargins
, deprecating UIEdgeInsets
which is used for layoutMargins
.
NSDirectionalEdgeInsets
honors interface layout direction using leading and trailing modifiers instead of left and right which is used by its counterpart UIEdgeInsets
.
Using the following code for every button/view with every modified UIEdgeInsets
property is quite cumbersome and prone to errors when making changes:
let isRTL: UIUserInterfaceLayoutDirection = // logic to determine language direction
if isRTL == .leftToRight {
nextButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 0)
} else {
nextButton.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 10)
}
import UIKit
extension UIView {
// Returns `UIEdgeInsets` set using `leading` and `trailing` modifiers adaptive to the language direction
func getDirectionalUIEdgeInsets(top: CGFloat, leading: CGFloat, bottom: CGFloat, trailing: CGFloat) -> UIEdgeInsets {
// NOTE: this wil be deprecated when Apple use `NSDirectioanlEdgeInsets` (https://developer.apple.com/documentation/uikit/nsdirectionaledgeinsets) for your insets property instead of `UIEdgeInsets`
if self.userInterfaceLayoutDirection == .leftToRight {
return UIEdgeInsets(top: top, left: leading, bottom: bottom, right: trailing)
} else {
return UIEdgeInsets(top: top, left: trailing, bottom: bottom, right: leading)
}
}
/// Returns text and UI direction based on current view settings
var userInterfaceLayoutDirection: UIUserInterfaceLayoutDirection
{
if #available(iOS 9.0, *) {
return UIView.userInterfaceLayoutDirection(for: self.semanticContentAttribute)
} else {
return UIApplication.shared.userInterfaceLayoutDirection
}
}
}
nextButton.contentEdgeInsets = nextButton.getDirectionalUIEdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 0)
I looked for an answer on Stackoverflow and found nothing. Thus I am sharing my answer.
Thanks to this Stackoverflow answer by David Rysanek for userInterfaceLayoutDirection
extension.