web-dev-qa-db-ja.com

UICollectionViewで右から左に配置

これは非常に簡単な質問ですが、SO(見逃した場合は修正してください)で決定的な答えを見つけることができませんでした。

基本的に、私の質問は次のとおりです。_UICollectionView行の内容を左から右ではなく右から左に揃えることは可能ですか?

私の研究では、サブクラス化UICollectionViewFlowLayoutを示唆する答えを見ましたが、右揃え用に作成された例を見つけることができませんでした。

私の目標は、次のように2つのコレクションビューを設定することです。

Example

どんな助けも大歓迎です!

49
rebello95

コレクションビューで変換を実行し、そのコンテンツの反転を逆にすることで、同様の結果を得ることができます。

最初に、UICollectionViewを作成するときに、水平方向のフリップを実行しました。

[collectionView_ setTransform:CGAffineTransformMakeScale(-1, 1)];

次に、サブクラスUICollectionViewCellで、ここでcontentViewで同じ水平反転を行います。

[self.contentView setTransform:CGAffineTransformMakeScale(-1, 1)];
83
LK__

コレクションビューに対してXtransformを実行せずに、RTLを強制します。

YourCollectionView.semanticContentAttribute = UISemanticContentAttribute.forceRightToLeft
81
Tawfik Bouabid

Tawfikの答えに加えて:

Interface Builderを介してUICollectionViewのSemanticプロパティを設定することもできます。

Storyboard

このプロパティの詳細: この質問

24
medvedNick

IOS 9の時点で、コレクションビューはこの WWDCビデオ に従ってRTLをサポートします。そのため、RTLフローレイアウトを作成する必要はなくなりました(カスタムレイアウトを既に使用している場合を除く)。

選択:スキームの編集...>Options>Run>Application Language>右から左への擬似言語

enter image description here

Simulatorにビルドすると、テキストは右揃えになり、コレクションビューは右から左に並べられます。

enter image description here

ただし、問題があります。 _contentOffset.x == 0_の場合、コレクションビューのスクロール位置は、Left Edge(正しい)ではなく、Right Edge(間違った)にあります。詳細については、こちらをご覧ください stack article .

回避策の1つは、Firstアイテムを単に_.Left_にスクロールすることです(注意点があります-_.Left_は実際にはRight、またはLeadingEdge):

_override func viewDidAppear(animated: Bool) {
    if collectionView?.numberOfItemsInSection(0) > 0  {
        let indexPath = NSIndexPath(forItem: 0, inSection: 0)
        collectionView?.scrollToItemAtIndexPath(indexPath, atScrollPosition: .Left, animated: false)
    }
}
_

私のテストプロジェクトでは、コレクションビューがテーブルビューセル内にネストされていたため、viewDidAppear()にアクセスできませんでした。その代わりに、私は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)
    }
}
_

この動作を確認するには、 このgitリポジトリのRTLブランチ を確認してください。コンテキストについては、こちらをご覧ください ブログ投稿とそのコメント

enter image description here

13
Robert Chen

SwiftでUICollectionViewの右から左へのレイアウトを達成しようとしている人向け

//in viewDidLoad
    YourCollectionView.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)

//in cellForItemAtIndexPath
    cell.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
11
Saqib Omer

同じ質問がある人には:

結局、@-chinttu-roxen-ramaniが推奨した ICollectionViewRightAlignedLayoutライブラリ を使用しました。コードで設定できます:

self.collectionView.collectionViewLayout = [[UICollectionViewRightAlignedLayout alloc] init];

または、インターフェースビルダーを介して:

Through interface builder

最終的にライブラリにいくつかの変更を加えましたが、全体的にはうまくいきます。

6
rebello95

iOS 11以降、これを使用できます。

extension UICollectionViewFlowLayout {

    open override var flipsHorizontallyInOppositeLayoutDirection: Bool {
        return true
    }

}
6
m.alqadi

bothflipsHorizontallyInOppositeLayoutDirectiondevelopmentLayoutDirectionを変更することで、最初のアイテムが右端まで移動するフルスクリーンRTLスクロールを実現し、最後のセルでは、ユーザーは左にスクロールする必要があります。

そのようです:

class RTLCollectionViewFlowLayout: UICollectionViewFlowLayout {

    override var flipsHorizontallyInOppositeLayoutDirection: Bool {
        return true
    }

    override var developmentLayoutDirection: UIUserInterfaceLayoutDirection {
        return UIUserInterfaceLayoutDirection.rightToLeft
    }
}
5
cohen72

IOSの場合9 +

  1. これでviewDidLoad()のcollectionViewを反転します:

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

  2. cellForItemAtでこれを使用してセルをリバースバックします(すべてのものがミラーリングされているため):

    cell.transform = CGAffineTransform(scaleX:-1、y:1)

現在、コンテンツは右側にあり、スクロールは右から始まります。

1
Mehdico

上記の答えのどれも私にとってはうまくいきませんでした。主な理由は、それらのほとんどが完全ではないということでした。しかし、私は this link by AlexSerdobintsev からこの解決策を見つけました。

AppDelegate.cs内。まず、次の関数をインポートする必要があります

[DllImport(ObjCRuntime.Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSend")]
internal extern static IntPtr IntPtr_objc_msgSend(IntPtr receiver, IntPtr selector, UISemanticContentAttribute arg1);

次に、FinishedLaunching内の関数を呼び出します

        var selector = new ObjCRuntime.Selector("setSemanticContentAttribute:");
        IntPtr_objc_msgSend(UIView.Appearance.Handle, selector.Handle, UISemanticContentAttribute.ForceRightToLeft);

出来上がり!完了です。変更を適用した後のファイルは次のとおりです。

    [Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
    [DllImport(ObjCRuntime.Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSend")]
    internal extern static IntPtr IntPtr_objc_msgSend(IntPtr receiver, IntPtr selector, UISemanticContentAttribute arg1);


    //
    // This method is invoked when the application has loaded and is ready to run. In this 
    // method you should instantiate the window, load the UI into it and then make the window
    // visible.
    //
    // You have 17 seconds to return from this method, or iOS will terminate your application.
    //
    public override bool FinishedLaunching(UIApplication app, NSDictionary options)
    {
        global::Xamarin.Forms.Forms.SetFlags("Shell_Experimental", "Visual_Experimental", "CollectionView_Experimental", "FastRenderers_Experimental");
        global::Xamarin.Forms.Forms.Init();
        LoadApplication(new App());

        ...

        var selector = new ObjCRuntime.Selector("setSemanticContentAttribute:");
        IntPtr_objc_msgSend(UIView.Appearance.Handle, selector.Handle, UISemanticContentAttribute.ForceRightToLeft);

        return base.FinishedLaunching(app, options);
    }
}
0
Ashi