質問編集履歴

2 誤字

Kesth

Kesth score 81

2015/09/28 22:05  投稿

【iOS,Swift】UICollectionViewControllerのsizeForItemAtIndexPathでレイアウトが崩れる
UICollectionViewControllerを使用した
レイアウトに関して質問させてください。
現在下記の様なレイアウトの画面を作成していまして、indexPath.section == 0の方は
高さがカスタムセルの高さによって動的に変化するセル、indexPath.section == 1の方は
高さ固定のセルになります。
![イメージ説明](57e994eac61b49138870d45b7befe705.jpeg)
その上で、今回問題が発生しているのが高さ可変の方の
indexPath.section == 0のセルになります。
セルの高さを動的に可変にしたいと思い、下記のような形で
実装しているのですがビルドしてみると上の画像の右側のように
実際のカスタムセルの高さの数倍ほどの高さになっており
ガッツリと余白が空いてしまいます。
カスタムセルを作成
UICollectionViewController上でカスタムセルのインスタンスを生成し
カスタムセル内の要素をすべて内包している要素である
UIView(後述)の高さの値を持つ変数を生成
その変数をsizeForItemAtIndexPathの中で
returnし、高さを返す
なお、カスタムセルは下記のような構成となっています。
UIView(以下の要素を内包し、高さが変動する)
 UIImage(高さ固定)
 UILabel(高さ可変)
 UIButton(高さ固定)
カスタムセル自体の表示では、カスタムセル内の
UIViewの高さは正常に調整されており、レイアウトも
キレイになっているので、UICollectionViewController上で
高さを取得した際に何らかの原因でおかしくなってしまっているのかと
思います。
考えられる原因について、ご教授頂ければ幸いです。
※カスタムセルおよびUICollectionViewControllerの
ソースコードはそれぞれ下記になります。
(文字数の関係上、必要な部分のみ記載します)
```Swift
import UIKit
class CollectionViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout,UICollectionViewDataSource{
   var collectionView : UICollectionView!
   let sectionInsetsTop = UIEdgeInsets(top:0, left: 0, bottom: 60.0, right: 0)
   let sectionInsets = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)
 
   
   override func viewDidLoad(){
       super.viewDidLoad()
             
       let layout = UICollectionViewFlowLayout()
       layout.scrollDirection = .Vertical
       
       collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height), collectionViewLayout: layout)
       
       //問題のカスタムセル
       collectionView.registerClass(MycustomCell.self, forCellWithReuseIdentifier: "customCell")
       collectionView.registerClass(customCell.self, forCellWithReuseIdentifier: "customCell")
       
       collectionView.delegate = self
       collectionView.dataSource = self
       self.view.addSubview(collectionView)
   }
   
   func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
       return 2
   }
   
   func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
       
       switch section{
       case 0:
           return 1
       case 1:
           return 10 
       default:
           return 0
       }
   }
   
   func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
       
       let customCell = collectionView.dequeueReusableCellWithReuseIdentifier("customCell",forIndexPath: indexPath) as! CustomCell
       
       switch indexPath.section {         
       case 0:   
          return customCell
       case 1:
         //以下、省略   
       }
   }
   
   
   func collectionView(collectionView: UICollectionView,
       layout collectionViewLayout: UICollectionViewLayout,
       insetForSectionAtIndex section: Int) -> UIEdgeInsets {
           
           switch section{
           case 0:
               return sectionInsetsTop
           case 1:
               return sectionInsets
           default:
               return sectionInsets
           }
   }
   
   
   func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
       
       let customCell = CustomCell()
       
    //ここでカスタムセルのUIViewの高さを取得
       let height = customCell.container.frame.size.height
       
       switch indexPath.section{
           
           case 0:
      //カスタムセルのUIViewの高さをセット
               return CGSize(width: self.view.frame.size.width,height: height)
           
           case 1:
               return CGSize(width: (self.view.frame.size.width-10*2)/2, height: 200)
           
           default:
               return CGSizeMake(0,0)
       }
   }
       
}
```
```Swift
import UIKit
class CustomCell:UICollectionViewCell{
   
   var container = UIView()
   var image = UIImageView()
   var label = UILabel()
   var button = UIButton()
   
   required init?(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)
   }
   
   override init(frame: CGRect) {
       super.init(frame: frame) 
       setupView()
   }
   
   private func setupView(){
       
       let screenWidth = self.bounds.width
     
     self.addSubview(container)
     
       let imageWidth:CGFloat = 69
       let imageHeight:CGFloat = 69
       image.frame = CGRectMake((screenWidth - imageWidth)/2, 10, imageWidth, imageHeight)
       self.container.addSubview(image)
       
       let labelWidth:CGFloat = screenWidth - 40
       label.frame = CGRectMake((screenWidth - labelWidth)/2 ,10 + imageHeight + 10, 10)
       label.text = "変動します"
       label.lineBreakMode = NSLineBreakMode.ByCharWrapping
       label.numberOfLines = 0
       label.font = UIFont(name: "Helvetica Neue", size: 13.5)
       label.sizeToFit()
       let labelHeight = self.label.frame.height
       self.container.addSubview(label)
       
       let buttonWidth:CGFloat = screenWidth - 90
       let buttonHeight:CGFloat = 26
       button.frame = CGRectMake((screenWidth - buttonWidth)/2,10 + imageHeight + 10 + labelHeight + 10, buttonWidth, buttonHeight)
       self.container.addSubview(button)
       //内包するviewの合計height
       let subviewsHeight:CGFloat = 10 + imageHeight + 10 + labelHeight + 10 + buttonHeight + 10
       //subviewsHeightをcontainerのHeightに設定
       container.frame = CGRectMake(0, 0, screenWidth,subviewsHeight)
       
   }
       
}
```
  • Swift

    11267 questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • iOS 8

    118 questions

    iOS 8(アイ・オーエス8)は、アップル社が2014年9月に発表したオペレーティングシステムです。iPhone 4sより対応しています。デザイン性の変更はなく、アプリや各種機能が強化されています。また、サードパーティ開発者のために、多くのAPIが開放されています。

  • iOS 9

    216 questions

    iOS 9は、アップル社のモバイルOSであるiOSシリーズのバージョン。特徴として検索機能の強化、Siriの機能改良、iPad向けマルチタスクなどがあります。マルチウィンドウ機能をサポートし、iPad向けマルチタスクもサポートされています。

1 修正

Kesth

Kesth score 81

2015/09/28 21:48  投稿

【iOS,Swift】UICollectionViewControllerのsizeForItemAtIndexPathでレイアウトが崩れる
UICollectionViewControllerを使用した
レイアウトに関して質問させてください。
現在下記の様なレイアウトの画面を作成していまして、indexPath.section == 0の方は
高さがカスタムセルの高さによって動的に変化するセル、indexPath.section == 1の方は
高さ固定のセルになります。
![イメージ説明](57e994eac61b49138870d45b7befe705.jpeg)
その上で、今回問題が発生しているのが高さ可変の方の
indexPath.section == 0のセルになります。
セルの高さを動的に可変にしたいと思い、下記のような形で
実装しているのですがビルドしてみると上の画像の右側のように
実際のカスタムセルの高さの数倍ほどの高さになっており
ガッツリと余白が空いてしまいます。
カスタムセルを作成
UICollectionViewController上でカスタムセルのインスタンスを生成し
カスタムセル内の要素をすべて内包している要素である
UIView(後述)の高さの値を持つ変数を生成
その変数をsizeForItemAtIndexPathの中で
returnし、高さを返す
なお、カスタムセルは下記のような構成となっています。
UIView(以下の要素を内包し、高さが変動する)
 UIImage(高さ固定)
 UILabel(高さ可変)
 UIButton(高さ固定)
カスタムセル自体の表示では、カスタムセル内の
UIViewの高さは正常に調整されており、レイアウトも
キレイになっているので、UICollectionViewController上で
高さを取得した際に何らかの原因でおかしくなってしまっているのかと
思います。
考えられる原因について、ご教授頂ければ幸いです。
※カスタムセルおよびUICollectionViewControllerの
ソースコードはそれぞれ下記になります。
(文字数の関係上、必要な部分のみ記載します)
```Swift
import UIKit
class CollectionViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout,UICollectionViewDataSource{
   var collectionView : UICollectionView!
   let sectionInsetsTop = UIEdgeInsets(top:0, left: 0, bottom: 60.0, right: 0)
   let sectionInsets = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)
 
   
   override func viewDidLoad(){
       super.viewDidLoad()
             
       let layout = UICollectionViewFlowLayout()
       layout.scrollDirection = .Vertical
       
       collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height), collectionViewLayout: layout)
       
       //問題のカスタムセル
       collectionView.registerClass(MycustomCell.self, forCellWithReuseIdentifier: "customCell")
       
       collectionView.delegate = self
       collectionView.dataSource = self
       self.view.addSubview(collectionView)
   }
   
   func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
       return 2
   }
   
   func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
       
       switch section{
       case 0:
           return 1
       case 1:
           return 10 
       default:
           return 0
       }
   }
   
   func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
       
       let customCell = collectionView.dequeueReusableCellWithReuseIdentifier("customCell",forIndexPath: indexPath) as! CustomCell
       
       switch indexPath.section {         
       case 0:   
          return customCell
       case 1:
         //以下、省略   
       }
   }
   
   
   func collectionView(collectionView: UICollectionView,
       layout collectionViewLayout: UICollectionViewLayout,
       insetForSectionAtIndex section: Int) -> UIEdgeInsets {
           
           switch section{
           case 0:
               return sectionInsetsTop
           case 1:
               return sectionInsets
           default:
               return sectionInsets
           }
   }
   
   
   func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
       
       let customCell = CustomCell()
       
    //ここでカスタムセルのUIViewの高さを取得
       let height = customCell.container.frame.size.height
       
       switch indexPath.section{
           
           case 0:
      //カスタムセルのUIViewの高さをセット
               return CGSize(width: self.view.frame.size.width,height: height)
           
           case 1:
               return CGSize(width: (self.view.frame.size.width-10*2)/2, height: 200)
           
           default:
               return CGSizeMake(0,0)
       }
   }
       
}
```
```Swift
import UIKit
class CustomCell:UICollectionViewCell{
   
   var container = UIView()
   var image = UIImageView()
   var label = UILabel()
   var button = UIButton()
   
   required init?(coder aDecoder: NSCoder) {
       super.init(coder: aDecoder)
   }
   
   override init(frame: CGRect) {
       super.init(frame: frame) 
       setupView()
   }
   
   private func setupView(){
       
       let screenWidth = self.bounds.width
     
     self.addSubview(container)
     
       let imageWidth:CGFloat = 69
       let imageHeight:CGFloat = 69
       image.frame = CGRectMake((screenWidth - imageWidth)/2, 10, imageWidth, imageHeight)
       self.container.addSubview(image)
       
       let labelWidth:CGFloat = screenWidth - 40
       label.frame = CGRectMake((screenWidth - labelWidth)/2 ,10 + imageHeight + 10, 10)
       label.text = "変動します"
       label.lineBreakMode = NSLineBreakMode.ByCharWrapping
       label.numberOfLines = 0
       label.font = UIFont(name: "Helvetica Neue", size: 13.5)
       label.sizeToFit()
       let labelHeight = self.label.frame.height
       self.container.addSubview(label)
       
       let buttonWidth:CGFloat = screenWidth - 90
       let buttonHeight:CGFloat = 26
       button.frame = CGRectMake((screenWidth - profileEditWidth)/2,10 + imageHeight + 10 + labelHeight + 10, buttonWidth, buttonHeight)
       button.frame = CGRectMake((screenWidth - buttonWidth)/2,10 + imageHeight + 10 + labelHeight + 10, buttonWidth, buttonHeight)
       self.container.addSubview(button)
       //内包するviewの合計height
       let subviewsHeight:CGFloat = 10 + imageHeight + 10 + labelHeight + 10 + buttonHeight + 10
       //subviewsHeightをcontainerのHeightに設定
       container.frame = CGRectMake(0, 0, screenWidth,subviewsHeight)
       
   }
       
}
```
  • Swift

    11267 questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • iOS 8

    118 questions

    iOS 8(アイ・オーエス8)は、アップル社が2014年9月に発表したオペレーティングシステムです。iPhone 4sより対応しています。デザイン性の変更はなく、アプリや各種機能が強化されています。また、サードパーティ開発者のために、多くのAPIが開放されています。

  • iOS 9

    216 questions

    iOS 9は、アップル社のモバイルOSであるiOSシリーズのバージョン。特徴として検索機能の強化、Siriの機能改良、iPad向けマルチタスクなどがあります。マルチウィンドウ機能をサポートし、iPad向けマルチタスクもサポートされています。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る