ユニバーサルUICollectionViewLayoutの作成

UICollectionViewには、ほとんどすべての要素を配置できます。 要素は、固定サイズと動的の両方を持つことができます。 この出版物では、要素サイズが特定のアルゴリズムによって固定および設定されているUICollectionViewLayoutのみに注意が払われます( 典型的な例は、iPhoneのホーム画面上のアイコンの位置です )。 単一のUICollectionViewLayoutの形成へのアプローチを記述する試みも行われます。



このようなUICollectionViewLayoutの主な機能は、そのような各配置で、要素のサイズと位置が繰り返されることによって特定の規則性を区別できることです。 将来、これをテンプレートと呼びます。 したがって、UICollectionViewLayoutを作成するには、テンプレートを形成するアルゴリズムを作成する必要があります。 繰り返しパターンの例:



画像








このようなUICollectionViewLayoutはすべて、コレクションの要素のサイズと位置を形成するためのアルゴリズムのみが異なります。 したがって、このようなUICollectionViewLayoutを作成したいという要望がありますが、これにはテンプレートを形成するためのアルゴリズムのみが必要であり、彼はそれ以降のすべてのアクションを実行します。



前の例を注意深く見ると、テンプレート内には、テンプレートごとに数回繰り返される要素のブロックがあることに気付くでしょう。 テンプレート内でブロックを繰り返す可能性を考慮して、論理的なステップは、テンプレートをブロックの配列に分割することです。



画像






すべてのアイデアをまとめて、プロトコルによるテンプレートの形成に関係するすべてのことを説明すると、次のようなものが得られました。



プロトコル(迅速なコード)
public protocol SquareMosaicBlock { //  CGRect   func frames() -> Int //  [CGRect]         func frames(origin: CGFloat, width: CGFloat) -> [CGRect] } public protocol SquareMosaicPattern { //   var blocks: [SquareMosaicBlock] { get } } public protocol SquareMosaicLayoutDataSource: class { func pattern() -> SquareMosaicPattern }
      
      







-SquareMosaicPattern、SquareMosaicBlockプロトコルは、要素の配置を記述するのに十分ですか?

-上の画像のコレクション要素の配置は、これら2つのプロトコルのみに基づいています。 したがって、ほとんどの場合、これらのプロトコルによってのみ、任意の場所を記述できます



これらのプロトコルを使用したUICollectionViewLayout自体の実装例を示し、詳細なレビューを行うことは、この出版物の計画には含まれていません。 リポジトリにアクセスすることで、誰でも独自にアプローチと実装を分析できますすべてのロジックは、〜100行のコードでのみ説明されています )。 使用例もあります。



ただし、テンプレートとブロックのプロトコルに対応するオブジェクトの形成の例を示す必要があります。 明確にするために、写真に示されているコレクションの要素のレイアウトについて説明します。



プロトコルに準拠したオブジェクト(迅速なコード)
 struct SnakeSquareMosaicPattern: SquareMosaicPattern { var blocks: [SquareMosaicBlock] { return [ OneTwoSquareMosaicBlock(), ThreeRightSquareMosaicBlock(), TwoOneSquareMosaicBlock(), ThreeRightSquareMosaicBlock() ] } } public struct OneTwoSquareMosaicBlock: SquareMosaicBlock { public func frames() -> Int { return 3 } public func frames(origin: CGFloat, width: CGFloat) -> [CGRect] { let sideMin = width / 3.0 let sideMax = width - sideMin var frames = [CGRect]() frames.append(CGRect(x: 0, y: origin, width: sideMax, height: sideMax)) frames.append(CGRect(x: sideMax, y: origin, width: sideMin, height: sideMin)) frames.append(CGRect(x: sideMax, y: origin + sideMax - sideMin, width: sideMin, height: sideMin)) return frames } } public struct TwoOneSquareMosaicBlock: SquareMosaicBlock { public func frames() -> Int { return 3 } public func frames(origin: CGFloat, width: CGFloat) -> [CGRect] { let sideMin = width / 3.0 let sideMax = width - sideMin var frames = [CGRect]() frames.append(CGRect(x: 0, y: origin, width: sideMin, height: sideMin)) frames.append(CGRect(x: 0, y: origin + sideMax - sideMin, width: sideMin, height: sideMin)) frames.append(CGRect(x: sideMin, y: origin, width: sideMax, height: sideMax)) return frames } } public struct ThreeRightSquareMosaicBlock: SquareMosaicBlock { public func frames() -> Int { return 3 } public func frames(origin: CGFloat, width: CGFloat) -> [CGRect] { let side = width / 3.0 var frames = [CGRect]() frames.append(CGRect(x: side + side, y: origin, width: side, height: side)) frames.append(CGRect(x: side, y: origin, width: side, height: side)) frames.append(CGRect(x: 0, y: origin, width: side, height: side)) return frames } }
      
      







その結果、完全にユニバーサルなSquareMosaicLayoutクラスがあります。 それに基づいて、UICollectionView要素のさまざまな場所のセットを構成できます。 あるテンプレートから別のテンプレートにアニメーションで移動します。 さまざまなテンプレートのブロックを再利用して、新しいテンプレートを作成します。



開発の次の段階は、さまざまな要素の場所を備えた事前定義されたブロックとテンプレートのセットの作成と補充です。 また、さまざまな種類のアニメーションとSupplementaryViews / DecorationViewsのサポートを追加したいと思います。



結論:達成された最も重要なことは、SquareMosaicLayoutクラスの内部を変更して要素の新しい配置を作成する必要がないことです。



PSココアポッド経由でインストール可能: ポッド「SquareMosaicLayout」



All Articles