Aligning right to left on UICollectionView

2019-01-16 16:09发布

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:

Example

Any help is greatly appreciated!

8条回答
Animai°情兽
2楼-- · 2019-01-16 16:19

you can use this since iOS 11

extension UICollectionViewFlowLayout {

open override var flipsHorizontallyInOppositeLayoutDirection: Bool {
    return true
}

}

查看更多
孤傲高冷的网名
3楼-- · 2019-01-16 16:26

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)];
查看更多
我只想做你的唯一
4楼-- · 2019-01-16 16:28

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:

Through interface builder

I ended up making a couple modifications to the library, but overall it works great.

查看更多
看我几分像从前
5楼-- · 2019-01-16 16:28

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.

查看更多
迷人小祖宗
6楼-- · 2019-01-16 16:30

In addition to Tawfik's answer:

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

Storyboard

More about this property: in this question

查看更多
祖国的老花朵
7楼-- · 2019-01-16 16:34

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

enter image description here

When you build to Simulator, text will be right-aligned, and your Collection View will be ordered from Right to Left.

enter image description here

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.

enter image description here

查看更多
登录 后发表回答