blog

Swift UICollectionViewは、各セクションのパーティションの背景画像や色を設定する

いくつかのアプリケーションは、異なるパーティションが背景画像や色を設定できるようにコレクションビューに示すようにする必要があります。そして、背景は、パーティションヘッダと他の操作、特にアプリケーション...

Mar 21, 2020 · 6 min. read
シェア

  • 一部のアプリケーションでは、図のようにコレクションビューの背景イメージや色で異なるパーティションを設定する必要があります。特にeコマースプラットフォームカテゴリのアプリケーションはそうです。しかし、コレクションビュー自体は背景イメージを直接設定することをサポートしていません、いくつかの研究の後、あなたはこの効果を達成するためにUICollectionViewFlowLayoutを書き換えることができます。

  • 背景Viewを装飾するセクションを登録するカスタムUICollectionReusableViewクラス

class SectionBackgroundReusableView: UICollectionReusableView {
 static let BACKGAROUND_CID = "BACKGAROUND_CID"
 
 private lazy var bg_imageView = UIImageView().then {
 addSubview($0)
 }
 
 override init(frame: CGRect) {
 super.init(frame: frame)
 
 }
 override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
 super.apply(layoutAttributes)
 bg_imageView.frame = bounds
 guard let att = layoutAttributes as? SectionDecorationViewCollectionViewLayoutAttributes else {
 return
 }
 self.backgroundColor = UIColor.clear
 bg_imageView.layer.cornerRadius = 5
 bg_imageView.clipsToBounds = true
 bg_imageView.backgroundColor = att.backgroundColor
 guard let imageName = att.imageName else {
 self.bg_imageView.image = nil
 return
 }
 guard let image_url = URL(string: imageName) else {
 return
 }
 self.bg_imageView.kf.setImage(with: image_url)
 }
 
 required init?(coder aDecoder: NSCoder) {
 fatalError("init(coder:) has not been implemented")
 }
}
class SectionDecorationViewCollectionViewLayoutAttributes: UICollectionViewLayoutAttributes {
 
 // 背景イメージを飾る
 var imageName: String?
 // 背景色
 var backgroundColor = UIColor.white
 /// 定義された属性のタイプは、NSCopyingプロトコルに従う必要がある。
 /// - Parameter zone:
 /// - Returns:
 override func copy(with zone: NSZone? = nil) -> Any {
 let copy = super.copy(with: zone) as! SectionDecorationViewCollectionViewLayoutAttributes
 copy.imageName = self.imageName
 copy.backgroundColor = self.backgroundColor
 return copy
 }
 
 /// 定義された属性の型も等しい判定方法を実装する必要がある。
 /// - Parameter object:
 /// - Returns: 等しいかどうか
 override func isEqual(_ object: Any?) -> Bool {
 guard let rhs = object as? SectionDecorationViewCollectionViewLayoutAttributes else {
 return false
 }
 if self.imageName != rhs.imageName {
 return false
 }
 if !self.backgroundColor.isEqual(rhs.backgroundColor) {
 return false
 }
 return super.isEqual(object)
 }
}
  1. 最初にバックグラウンドビューを登録します。
 override init() {
 super.init()
 // バックグラウンドビューの登録
 self.register(SectionBackgroundReusableView.self, forDecorationViewOfKind: SectionBackgroundReusableView.BACKGAROUND_CID)
 }
  1. 背景の位置とサイズの設定
 // レイアウト設定データ
 override func prepare() {
 super.prepare()
 // collectionViewが現在パーティション化されていない場合は、直接から
 guard let numberOfSections = self.collectionView?.numberOfSections
 else {
 return
 }
 // を終了するcardDecorationDelegateが存在しない。
 guard let delegate = decorationDelegate else {
 return
 }
 if decorationBackgroundAttrs.count > 0 {
 decorationBackgroundAttrs.removeAll()
 }
 for section:Int in 0..<numberOfSections {
 // 最初の下のセクションだけでなく、最後の項目のプロパティのレイアウトを取得する
 guard let numberOfItems = self.collectionView?.numberOfItems(inSection: section),
 numberOfItems > 0,
 let firstItem = self.layoutAttributesForItem(at:
 IndexPath(item: 0, section: section)),
 let lastItem = self.layoutAttributesForItem(at:
 IndexPath(item: numberOfItems - 1, section: section))
 else {
 continue
 }
 var sectionInset:UIEdgeInsets = self.sectionInset
 /// 内側のマージンのセクションを取得する
 let inset:UIEdgeInsets = delegate.collectionView(collectionView: self.collectionView!, layout: self, insetForSectionAt: section)
 if !(inset == .zero) {
 sectionInset = inset
 }
 
 /// セクションヘッダーサイズを取得する
 let headerSize = delegate.collectionView(collectionView: self.collectionView!, layout: self, headerForSectionAt: section)
 var sectionFrame:CGRect = .zero
 if self.scrollDirection == .horizontal {
 let hx = (firstItem.frame.origin.x) - headerSize.width + sectionInset.left
 let hy = (firstItem.frame.origin.y) + sectionInset.top
 let hw = ((lastItem.frame.origin.x) + (lastItem.frame.size.width)) - sectionInset.right
 let hh = ((lastItem.frame.origin.y) + (lastItem.frame.size.height)) - sectionInset.bottom
 sectionFrame = CGRect(x: hx , y: hy, width: hw, height: hh)
 sectionFrame.origin.y = sectionInset.top
 sectionFrame.size.width = sectionFrame.size.width-sectionFrame.origin.x
 sectionFrame.size.height = self.collectionView!.frame.size.height - sectionInset.top - sectionInset.bottom
 
 } else {
 let vx = (firstItem.frame.origin.x)
 let vy = (firstItem.frame.origin.y) - headerSize.height + sectionInset.top
 let vw = ((lastItem.frame.origin.x) + (lastItem.frame.size.width))
 let vh = ( (lastItem.frame.origin.y) + (lastItem.frame.size.height) ) - sectionInset.bottom
 sectionFrame = CGRect(x: vx , y: vy, width: vw, height: vh + 10)
 sectionFrame.origin.x = sectionInset.left
 sectionFrame.size.width = (self.collectionView?.frame.size.width)! - sectionInset.left - sectionInset.right
 sectionFrame.size.height = sectionFrame.size.height - sectionFrame.origin.y
 }
 
 let attrs = SectionDecorationViewCollectionViewLayoutAttributes(forDecorationViewOfKind: SectionBackgroundReusableView.BACKGAROUND_CID, with: IndexPath(item: 0, section: section))
 let backgroundColor = delegate.collectionView(self.collectionView!, layout: self, decorationColorForSectionAt: section)
 attrs.frame = sectionFrame
 attrs.zIndex = -1
 attrs.backgroundColor = backgroundColor
 /// 色を保存する優先順位
 self.decorationBackgroundAttrs[section] = attrs
 
 /// 背景イメージが表示されているかどうかを判断する不可視スキップ
 let backgroundDisplayed = delegate.collectionView(self.collectionView!, layout: self, decorationImgaeDisplayedForSectionAt: section)
 guard backgroundDisplayed == true else {
 continue
 }
 /// nilの背景イメージの名前は、スキップする場合
 guard let imageName = delegate.collectionView(self.collectionView!, layout: self, decorationImageForSectionAt: section) else {
 continue
 }
 attrs.imageName = imageName
 
 
 let displayedFillet = delegate.collectionView(self.collectionView!, layout: self, filletDisplayedForSectionAt: section)
 guard displayedFillet == false else {
 continue
 }
 // セクションのレイアウトプロパティを保存する
 self.decorationBackgroundAttrs[section] = attrs
 }
 
 }
 override func layoutAttributesForDecorationView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
 let section = indexPath.section
 if elementKind == SectionBackgroundReusableView.BACKGAROUND_CID {
 return self.decorationBackgroundAttrs[section]
 }
 return super.layoutAttributesForDecorationView(ofKind: elementKind,
 at: indexPath)
 }
  1. 重要なコードを説明するために行われている、あなたはこの効果を必要とすることが起こる場合は、コードを参照してダウンロードすることができますし、変更するには、独自のニーズと組み合わせることができます。コードのアドレスは、以前の
Read next

35歳のインターネット・デザイナーはこれからどこへ行くのか?キャリアプランの立て方

最近、新卒の時に先輩から「3年で小さなハードル、5年で大きなハードルがある」という話を聞きました。 今年で社会人5年目ですが、仕事では本当に大きなハードルにぶつかり、それを越えられるかどうかはまだ未知数です。昨年のキーワードは「新規開拓」「半知半解」「前途多難」。今日は

Mar 21, 2020 · 3 min read