これは非常に簡単な質問ですが、SO(見逃した場合は修正してください)で決定的な答えを見つけることができませんでした。
基本的に、私の質問は次のとおりです。_UICollectionView
行の内容を左から右ではなく右から左に揃えることは可能ですか?
私の研究では、サブクラス化UICollectionViewFlowLayout
を示唆する答えを見ましたが、右揃え用に作成された例を見つけることができませんでした。
私の目標は、次のように2つのコレクションビューを設定することです。
どんな助けも大歓迎です!
コレクションビューで変換を実行し、そのコンテンツの反転を逆にすることで、同様の結果を得ることができます。
最初に、UICollectionViewを作成するときに、水平方向のフリップを実行しました。
[collectionView_ setTransform:CGAffineTransformMakeScale(-1, 1)];
次に、サブクラスUICollectionViewCell
で、ここでcontentViewで同じ水平反転を行います。
[self.contentView setTransform:CGAffineTransformMakeScale(-1, 1)];
コレクションビューに対してXtransformを実行せずに、RTLを強制します。
YourCollectionView.semanticContentAttribute = UISemanticContentAttribute.forceRightToLeft
IOS 9の時点で、コレクションビューはこの WWDCビデオ に従ってRTLをサポートします。そのため、RTLフローレイアウトを作成する必要はなくなりました(カスタムレイアウトを既に使用している場合を除く)。
選択:スキームの編集...>Options>Run>Application Language>右から左への擬似言語
Simulatorにビルドすると、テキストは右揃えになり、コレクションビューは右から左に並べられます。
ただし、問題があります。 _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ブランチ を確認してください。コンテキストについては、こちらをご覧ください ブログ投稿とそのコメント 。
SwiftでUICollectionView
の右から左へのレイアウトを達成しようとしている人向け
//in viewDidLoad
YourCollectionView.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
//in cellForItemAtIndexPath
cell.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)
同じ質問がある人には:
結局、@-chinttu-roxen-ramaniが推奨した ICollectionViewRightAlignedLayoutライブラリ を使用しました。コードで設定できます:
self.collectionView.collectionViewLayout = [[UICollectionViewRightAlignedLayout alloc] init];
または、インターフェースビルダーを介して:
最終的にライブラリにいくつかの変更を加えましたが、全体的にはうまくいきます。
iOS 11以降、これを使用できます。
extension UICollectionViewFlowLayout {
open override var flipsHorizontallyInOppositeLayoutDirection: Bool {
return true
}
}
bothflipsHorizontallyInOppositeLayoutDirection
とdevelopmentLayoutDirection
を変更することで、最初のアイテムが右端まで移動するフルスクリーンRTLスクロールを実現し、最後のセルでは、ユーザーは左にスクロールする必要があります。
そのようです:
class RTLCollectionViewFlowLayout: UICollectionViewFlowLayout {
override var flipsHorizontallyInOppositeLayoutDirection: Bool {
return true
}
override var developmentLayoutDirection: UIUserInterfaceLayoutDirection {
return UIUserInterfaceLayoutDirection.rightToLeft
}
}
IOSの場合9 +
これでviewDidLoad()のcollectionViewを反転します:
myCollectionView.transform = CGAffineTransform(scaleX:-1、y:1)
cellForItemAtでこれを使用してセルをリバースバックします(すべてのものがミラーリングされているため):
cell.transform = CGAffineTransform(scaleX:-1、y:1)
現在、コンテンツは右側にあり、スクロールは右から始まります。
上記の答えのどれも私にとってはうまくいきませんでした。主な理由は、それらのほとんどが完全ではないということでした。しかし、私は 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);
}
}