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

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

ただいまの
回答率

90.53%

  • Swift

    8581questions

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

  • iOS

    4592questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

collectionViewで無限スクロールを実装する際、セル内のラベルにテキストがきちんと入らない

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,375

KazutakaShimizu

score 152

現在iosアプリを作っており、collectionViewを使った無限にスクロールできるメニューを実装しようとしています(メルカリのカテゴリメニューのようなものです)
collectionViewのセル一つ一つがメニューとなっていて
ここにメニューのタイトルを入れようとすると下記のようにうまく表示されません。
イメージ説明

//メニュー部分全体のView
class MenuBarView: UIView {
    var pageTabItemsWidth: CGFloat = 0.0
    var collectionView:UICollectionView!
    var titles: [String] = Constant.menuTitle
    override init(frame: CGRect) {
        super.init(frame: frame)
        setUpCollectionView()
    }
    ![

文字列ではなくセルの背景色をセルごとに変えようとするとうまくいきます。
ソースコードは下記](358ec05119a0e16055670e7bdfef2f88.gif)
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension MenuBarView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    fileprivate func setUpCollectionView(){
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width:100, height:30)
        layout.scrollDirection = .horizontal
        collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height), collectionViewLayout: layout)
        // Cellに使われるクラスを登録.
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.showsHorizontalScrollIndicator = false
        collectionView.register(MenuBarViewCell.self, forCellWithReuseIdentifier: "MyCell")
        self.addSubview(collectionView)

    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        print("items")
        return titles.count * 3
    }

    /*
     Cellに値を設定する
     */
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell : MenuBarViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell",for: indexPath) as! MenuBarViewCell
        configureCell(cell: cell, indexPath: indexPath)
        return cell
    }

    private func configureCell(cell:MenuBarViewCell, indexPath: IndexPath){
        let fixedIndex = indexPath.item % titles.count
        cell.title = titles[fixedIndex]
    }
}

extension MenuBarView: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if pageTabItemsWidth == 0.0 {
            pageTabItemsWidth = floor(scrollView.contentSize.width / 3.0) // 表示したい要素群のwidthを計算
        }

        if (scrollView.contentOffset.x <= 0.0) || (scrollView.contentOffset.x > pageTabItemsWidth * 2.0) { // スクロールした位置がしきい値を超えたら中央に戻す
            scrollView.contentOffset.x = pageTabItemsWidth
        }
    }
}
//MenuBarViewで表示しているcollectionViewCell
class MenuBarViewCell: UICollectionViewCell {
    var title:String!{
        didSet{
            setUpUi()
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    private func setUpUi(){
        self.backgroundColor = .white
        var label = UILabel(frame: self.bounds)
        label.text = title
        label.textColor = .black
        label.textAlignment = .center
        self.contentView.addSubview(label)
    }
}

足りてない情報等ございましたら、お手数ですがコメントをください。
どんたか教えていただけると大変助かります。よろしくお願い申し上げます。

【追記】
MenuBarViewCellのsetUpUi()内のUILabel(frame: self.frame)部分の記述を
UILabel(frame: self.bounds)に切り替えたところ表示はされるが
素早くスクロールすると一つのセルの中に複数のメニューのタイトルが重なって表示されてしまうようになりました。
イメージ説明

【解決方法】
MenuBarViewCellの記述を下記のようにして、addSubViewが呼び出されるのを一度だけにしたところなおりました。

class MenuBarViewCell: UICollectionViewCell {
    var isCompletedSetUpUI: Bool = false
    var title:String!{
        didSet{
            if !isCompletedSetUpUI {
                setUpUi()
            }
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    private func setUpUi(){
        self.backgroundColor = .white
        var label = UILabel(frame: self.bounds)
        print(title)
        label.text = title
        label.textAlignment = .center
        self.contentView.addSubview(label)
        isCompletedSetUpUI = true
    }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • fuzzball

    2017/06/13 15:50

    MenuBarViewCellのlabelはStoryboard上で乗せているのではないのでしょうか?

    キャンセル

  • KazutakaShimizu

    2017/06/13 15:54 編集

    申し訳ございません
    先ほど修正いたしまして、現在はStoryBoardもXibも使わず、labelをソースコードから生成して乗せています

    キャンセル

  • fuzzball

    2017/06/13 16:02

    なぜStoryboard(xib)をやめたのか謎ですが‥。それはそれとして、現在のコードだとsetUpUi()が呼ばれるたびにUILabelが積み重なっていきます。(私の回答でaddSubviewを削除するように書いたのはそのためです)

    キャンセル

  • KazutakaShimizu

    2017/06/15 07:31

    MenuBarViewCellの記述を下記のようにして、addSubViewが呼び出されるのを一度だけにしたところなおりました。アドバイスありがとうございました。

    キャンセル

回答 2

checkベストアンサー

+1

setUpUi()内のUILabel(frame: self.frame)が問題なんだと思います。
self.frameを指定するとセルの位置に影響されてしまうので、最初のセル以外はセルをはみ出て配置されてしまっているため表示されなくなっているのかと思います。

解決策としてはUILabel(frame: self.bounds)なんかを指定すればとりあえず表示されるようになるのではないでしょうか。

 質問とは関係ない指摘

  • UICollectionView はコードで生成しているので MenuBarViewCell の @IBOutlet は不要
  • setUpUi()が呼ばれるたびに毎回ラベル生成されているので、初期化と一緒に生成するかifで囲うかする

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

MenuBarViewCellの、

label = UILabel(frame: self.frame)

これだとOutletで繋いだUILabelではなく、新規にインスタンスを作成することになりますので削除して下さい。

self.contentView.addSubview(label)

これも不要です。

質問の症状とは関係ないような気もしますが、とりあえず。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/06/13 12:10

    セルの幅を可変にしたり、メニューに入れる文字列を一桁の数字などにしたのですが、改善されません・・・。

    キャンセル

  • 2017/06/13 12:51

    画像がガクガクして分かりづらいのですが、テキストが途切れるという問題ではないのでしょうか?
    「きちんと入らない」とか「うまく表示されません」ではなく、もう少し具体的に書いて下さい。

    キャンセル

  • 2017/06/13 14:16

    スクロールするたびにテキストが入ったり入らなかったり、一つのセルに二つのテキストが重なって入ってしまったりします。
    画像を変更いたしましたので、改めてご確認いただけると幸いです。

    キャンセル

  • 2017/06/13 14:46

    回答を更新しました。

    キャンセル

  • 2017/06/13 14:51 編集

    ありがとうございます。
    ご指摘いただいたところを修正いたしましたが、おっしゃるとおり症状とは無関係の部分だったようです。

    キャンセル

  • 2017/06/13 15:03

    UICollectionViewのスクロール制御と、scrollViewDidScroll内のスクロール制御が干渉してないですかね?UICollectionViewを使う必要性も感じないので、UIScrollViewnの上にUILabelを並べた方が良いのでは?

    キャンセル

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

  • Swift

    8581questions

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

  • iOS

    4592questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

  • トップ
  • iOSに関する質問
  • collectionViewで無限スクロールを実装する際、セル内のラベルにテキストがきちんと入らない