Aligning right to left on UICollectionView

2019-01-16 15:45发布

问题:

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!

回答1:

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)];


回答2:

Without doing any Xtransform to the collection view, simply forced RTL:

YourCollectionView.semanticContentAttribute = UISemanticContentAttribute.forceRightToLeft


回答3:

In addition to Tawfik's answer:

You can also set UICollectionView's Semantic property via Interface Builder:

More about this property: in this question



回答4:

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)


回答5:

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.



回答6:

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.



回答7:

you can use this since iOS 11

extension UICollectionViewFlowLayout {

open override var flipsHorizontallyInOppositeLayoutDirection: Bool {
    return true
}

}



回答8:

Solution for Swift 4.2 and iOS 9+ in 2 simple steps

  1. reverse your collectionView in viewDidLoad() like this :

    myCollectionView.transform = CGAffineTransform(scaleX: -1, y: 1)

  2. 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.