this is a pretty straightforward question, but I haven't been able to find a definitive answer to it on SO (if I missed it, please correct me).
Basically, my question is: Is it possible to align UICollectionView
row contents from right to left instead of from left to right?
In my research I've seen answers suggesting subclassing UICollectionViewFlowLayout
, but I haven't been able to find an example where one was created for right-alignment.
My goal is to have 2 collection views set up like this:
Any help is greatly appreciated!
You can get similar result by performing a transform on the collection view and reverse the flip on its content:
First when creating the UICollectionView I performed a horizontal flip on it:
[collectionView_ setTransform:CGAffineTransformMakeScale(-1, 1)];
Then subclass UICollectionViewCell
and in here do the same horizontal flip on its contentView:
[self.contentView setTransform:CGAffineTransformMakeScale(-1, 1)];
Without doing any Xtransform to the collection view, simply forced RTL:
YourCollectionView.semanticContentAttribute = UISemanticContentAttribute.forceRightToLeft
In addition to Tawfik's answer:
You can also set UICollectionView's Semantic
property via Interface Builder:
More about this property: in this question
For anybody trying to achieve Right to Left layout of UICollectionView
in Swift
//in viewDidLoad
YourCollectionView.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
//in cellForItemAtIndexPath
cell.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
As of iOS 9, Collection Views support RTL according to this WWDC video. So it's no longer necessary to create an RTL flow layout (unless you're already using a custom layout).
Select: Edit Scheme... > Options > Run > Application Language > Right to Left Pseudolanguage
When you build to Simulator, text will be right-aligned, and your Collection View will be ordered from Right to Left.
There's a problem though. When contentOffset.x == 0
, the Collection View scroll position is at the Left
edge (wrong) instead of the Right
edge (correct). See this stack article for details.
One workaround is to simply scroll the First
item to the .Left
(There's a gotcha -- .Left
is actually on the Right, or Leading edge):
override func viewDidAppear(animated: Bool) {
if collectionView?.numberOfItemsInSection(0) > 0 {
let indexPath = NSIndexPath(forItem: 0, inSection: 0)
collectionView?.scrollToItemAtIndexPath(indexPath, atScrollPosition: .Left, animated: false)
}
}
In my test project, my Collection View was nested inside a Table View Cell, so I didn't have access to viewDidAppear()
. So instead, I ended up hooking into drawRect()
:
class CategoryRow : UITableViewCell {
@IBOutlet weak var collectionView: UICollectionView!
override func drawRect(rect: CGRect) {
super.drawRect(rect)
scrollToBeginning()
}
override func prepareForReuse() {
scrollToBeginning()
}
func scrollToBeginning() {
guard collectionView.numberOfItems(inSection: 0) > 0 else { return }
let indexPath = IndexPath(item: 0, section: 0)
collectionView.scrollToItem(at: indexPath, at: .left, animated: false)
}
}
To see this in action, check out the RTL branch on this git repo. And for context, see this blog post and its comments.
For anyone who has the same question:
I ended up using the UICollectionViewRightAlignedLayout library that @chinttu-roxen-ramani recommended. You can either set it with code:
self.collectionView.collectionViewLayout = [[UICollectionViewRightAlignedLayout alloc] init];
or through interface builder:
I ended up making a couple modifications to the library, but overall it works great.
you can use this since iOS 11
extension UICollectionViewFlowLayout {
open override var flipsHorizontallyInOppositeLayoutDirection: Bool {
return true
}
}
Solution for Swift 4.2 and iOS 9+ in 2 simple steps
reverse your collectionView in viewDidLoad() like this :
myCollectionView.transform = CGAffineTransform(scaleX: -1, y: 1)
reverse back your cell (because all things is reversed) in cellForItemAt like this :
cell.transform = CGAffineTransform(scaleX: -1, y: 1)
now content is on right side and scroll starts from right.