質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • Swift

    8706questions

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

CollectionViewCell間の間隔を詰める方法,コードでラベルの配置を調整する方法

受付中

回答 0

投稿

  • 評価
  • クリップ 0
  • VIEW 1,120

info_1616

score 2

前提・実現したいこと

初めまして,iOSアプリの開発をしている者です.
TODOアプリの開発途中で,機能の一つであるカレンダーの枠組みを作成しています.

発生している問題・エラーメッセージ

以下のコードでビルドしたところ,シミュレーターでの表示が次のようになりました.

イメージ説明

このように,左から5本目の縦線と上から5本目の縦線に小さな隙間ができます.
この隙間を詰めたいのですが,どうすればよろしいでしょうか.

また,次のコードで上から1段目のラベルを中央に,それ以外の段のラベルを左上に配置したいのですが,それが反映されません.

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath)
        let label = cell.viewWithTag(1) as! UILabel

        cell.layer.borderColor = UIColor.blackColor().CGColor
        cell.layer.borderWidth = 1.0

        if indexPath.section == 0{
            label.layer.position.x = cell.layer.position.x + (cell.frame.size.width - label.frame.size.width) / 2
            label.layer.position.y = cell.layer.position.y + (cell.frame.size.height - label.frame.size.width) / 2
        }else{
            label.layer.position.x = cell.layer.position.x
            label.layer.position.y = cell.layer.position.y
        }

        return cell
    }

StoryBoard上では,ラベルはセルの左上に配置していて,AutoLayoutは設定していない状態です.
ラベル配置を調整するコードはcollectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath)に書いていますが,レイアウト関係の処理なので viewDidLayoutSubviews内に書いた方がいいかとも思ったのですが,その場合indexPathの取得をどのようにすればいいかが分からない状態となっています.

回答いただけるとありがたいです...

該当のソースコード

import UIKit

class Test: UIViewController,UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    let dateManager = DateManager()
    let daysPerWeek = 7

    @IBOutlet weak var calendarCollectionView: UICollectionView!



    override func viewDidLoad() {
        super.viewDidLoad()

        //collection viewの設定
        calendarCollectionView.delegate = self
        calendarCollectionView.dataSource = self
        calendarCollectionView.backgroundColor = UIColor.whiteColor()

        //collectionViewはスクロールさせない
        calendarCollectionView.scrollEnabled = false
    }

    //レイアウトに関する処理
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        self.view.layoutIfNeeded()

        //collectionViewの高さを,セルの大きさに応じて調節する
        //高さ=ステータスバーの高さ+ナビゲーションバーの高さ+曜日セルの高さ+日付セルの高さ*週の数
        let cellSize = self.view.frame.size.width / CGFloat(daysPerWeek)
        calendarCollectionView.frame = CGRectMake(0, 0, self.view.frame.size.width, UIApplication.sharedApplication().statusBarFrame.height + (self.navigationController?.navigationBar.frame.size.height)! + CGFloat(30) + cellSize * CGFloat(dateManager.weeksPerMonth) )
    }

    /*collectionViewの処理(ここから)*/
    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 2
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        switch section {
        case 0:
            return 7
        default:
            return dateManager.daysAcquisition()
        }
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath)
        let label = cell.viewWithTag(1) as! UILabel

        cell.layer.borderColor = UIColor.blackColor().CGColor
        cell.layer.borderWidth = 1.0

        if indexPath.section == 0{
            label.layer.position.x = cell.layer.position.x + (cell.frame.size.width - label.frame.size.width) / 2
            label.layer.position.y = cell.layer.position.y + (cell.frame.size.height - label.frame.size.width) / 2
        }else{
            label.layer.position.x = cell.layer.position.x
            label.layer.position.y = cell.layer.position.y
        }

        return cell
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        let width:CGFloat = collectionView.frame.size.width / CGFloat(daysPerWeek)
        let height:CGFloat = indexPath.section == 0 ? 30 : width * 1.0

        return CGSizeMake(width, height)
    }

    /*セルの隙間を詰めるための処理(ここから)*/
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets {
        return UIEdgeInsetsMake(0.0, 0.0, 0.0, 0.0)
    }

    //セルの垂直方向のマージンを設定
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
        return 0.0//cellMargin
    }

    //セルの水平方向のマージンを設定
    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
        return 0.0//cellMargin
    }
    /*セルの隙間を詰めるための処理(ここまで)*/

    /*collectionViewの処理(ここまで)*/
}
import Foundation

extension NSDate {
    func monthAgoDate() -> NSDate {
        let addValue = -1
        let calendar = NSCalendar.currentCalendar()
        let dateComponents = NSDateComponents()
        dateComponents.month = addValue
        return calendar.dateByAddingComponents(dateComponents, toDate: self, options: NSCalendarOptions(rawValue: 0))!
    }

    func monthLaterDate() -> NSDate {
        let addValue: Int = 1
        let calendar = NSCalendar.currentCalendar()
        let dateComponents = NSDateComponents()
        dateComponents.month = addValue
        return calendar.dateByAddingComponents(dateComponents, toDate: self, options: NSCalendarOptions(rawValue: 0))!
    }

}

class DateManager: NSObject {
    var currentMonthOfDates = [NSDate]() //表記する月の配列
    var selectedDate = NSDate()
    let daysPerWeek: Int = 7
    var numberOfItems: Int!
    var weeksPerMonth: Int! //月あたりの週の数

    //月ごとのセルの数を返すメソッド
    internal func daysAcquisition() -> Int {
        let rangeOfWeeks = NSCalendar.currentCalendar().rangeOfUnit(NSCalendarUnit.WeekOfMonth, inUnit: NSCalendarUnit.Month, forDate: firstDateOfMonth())
        weeksPerMonth = rangeOfWeeks.length //月が持つ週の数
        numberOfItems = weeksPerMonth * daysPerWeek //週の数×列の数
        return numberOfItems
    }

    //月の初日を取得
    private func firstDateOfMonth() -> NSDate {
        let components = NSCalendar.currentCalendar().components([.Year, .Month, .Day],
                                                                 fromDate: selectedDate)
        components.day = 1
        let firstDateMonth = NSCalendar.currentCalendar().dateFromComponents(components)!
        return firstDateMonth
    }

    // ⑴表記する日にちの取得
    private func dateForCellAtIndexPath(numberOfItems: Int) {
        // ①「月の初日が週の何日目か」を計算する
        let ordinalityOfFirstDay = NSCalendar.currentCalendar().ordinalityOfUnit(NSCalendarUnit.Day, inUnit: NSCalendarUnit.WeekOfMonth, forDate: firstDateOfMonth())
        for i in 0 ..< numberOfItems {
            // ②「月の初日」と「indexPath.item番目のセルに表示する日」の差を計算する
            let dateComponents = NSDateComponents()
            dateComponents.day = i - (ordinalityOfFirstDay - 1)
            // ③ 表示する月の初日から②で計算した差を引いた日付を取得
            let date = NSCalendar.currentCalendar().dateByAddingComponents(dateComponents, toDate: firstDateOfMonth(), options: NSCalendarOptions(rawValue: 0))!
            // ④配列に追加
            currentMonthOfDates.append(date)
        }
    }

    // ⑵表記の変更
    internal func conversionDateFormat(indexPath: NSIndexPath) -> String {
        //currentMonthOfDatesが空の場合,新たに取得する
        if currentMonthOfDates.count != numberOfItems!{
                dateForCellAtIndexPath(numberOfItems)
        }
        let formatter: NSDateFormatter = NSDateFormatter()
        formatter.dateFormat = "d"
        return formatter.stringFromDate(currentMonthOfDates[indexPath.row])
    }

    //前月の表示
    func prevMonth(date: NSDate) -> NSDate {
        currentMonthOfDates = []
        selectedDate = date.monthAgoDate()
        return selectedDate
    }
    //次月の表示
    func nextMonth(date: NSDate) -> NSDate {
        currentMonthOfDates = []
        selectedDate = date.monthLaterDate()
        return selectedDate
    }
}

試したこと

Testクラス中にcollectionViewCell間の間隔を詰めるために関数collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int), collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int), collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int)を挿入していますが,挿入前に比べてセル間の間隔は詰められましたが上のシミュレーターのように一部のセルの間隔が半端に空いている状態となっています.

補足情報

Xcode 7.3.1
シミュレーター iPhone6s Plus
OSX ElCapitan 10.11.6

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

同じタグがついた質問を見る

  • Swift

    8706questions

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