簡體   English   中英

不能 Select CollectionView 在 TableView 單元格中

[英]Can not Select CollectionView in TableView Cell

我正在制作日歷。

我把collection view放在table view中,但是collection view的單元格沒有被選中。

我剛剛將集合視圖添加到表格視圖單元格並設置了所有數據源設置。

TableView allowSelection 關閉,tableViewCell isUserInteractionEnabled 設置為 false。

這里是我的代碼

CalanderView.swift

import Foundation
import UIKit

class CalendarView: UIView {
    private var increaseYear: Int = 0
    
    internal lazy var tableView: UITableView = {
        let table = UITableView()
        table.showsVerticalScrollIndicator = false
        table.translatesAutoresizingMaskIntoConstraints = false
//        table.allowsSelection = false
        table.register(CalendarCell.self, forCellReuseIdentifier: CalendarCell.reuseIdentifier)
        table.delegate = self
        table.dataSource = self
        table.bounces = false
        table.tableFooterView = UIView(
            frame: CGRect(
                x: 0,
                y: 0,
                width: self.frame.width,
                height: 120.calculated
            )
        )
//        table.estimatedRowHeight = 600.calculated
        
        return table
    }()
    
    internal lazy var header: CalendarHeader = {
        let header = CalendarHeader(frame: self.frame)
        header.backgroundColor = .white
        
        return header
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)

        setLayoutConstraints()
    }
    
    required init(coder: NSCoder) {
        super.init(coder: coder)!
        
        setLayoutConstraints()
    }
}





// MARK: -CUSTOM FUNCTION
extension CalendarView {
    func getCurrentMonth(_ val: Int) -> Int {
        let obj = CalendarHelper.today.month + val
        let currentMonth = obj % 12 == 0 ? 12 : obj % 12
        let floatVal: Float = Float(obj) / 12.0
        let ceilVal = ceil(floatVal - 1)
        
        self.increaseYear = Int(ceilVal)
        
        return currentMonth
    }
}





// MARK: -DELEGATES, DATASOURCE
extension CalendarView: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 6
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: CalendarCell = tableView.dequeueReusableCell(for: indexPath)
        let currentMonth = getCurrentMonth(indexPath.row)
        let currentYear = CalendarHelper.today.year + self.increaseYear
        let component = DateComponents(year: currentYear, month: currentMonth)
        let days = CalendarHelper.shared.daysOfMonth[currentMonth-1]
        let dayOfMonth = CalendarHelper.dateFrom(component).isLeapMonth ? days + 1 : days
        
        cell.isUserInteractionEnabled = false
        cell.month = currentMonth
        cell.year = currentYear
        cell.dayOfWeek = CalendarHelper.dateFrom(component).weekday
        cell.dayOfMonth = dayOfMonth
        cell.separatorInset = UIEdgeInsets(top: 0, left: 20.calculated, bottom: 0, right: 20.calculated)
        
        cell.bringSubviewToFront(cell.dayCollection)
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

        return 550
    }
    
    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 550
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("tableView didSelectRowAt")
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if let indexPath = self.tableView.indexPathsForVisibleRows {
            if indexPath.indices.contains(1) {
                let cell = tableView.cellForRow(at: indexPath[1]) as! CalendarCell
                if scrollView.contentOffset.y > cell.frame.origin.y - 10 {
                    self.header.month = cell.month
                    self.header.year = cell.year
                }
                
                let beforeCell = tableView.cellForRow(at: indexPath[0]) as! CalendarCell
                if scrollView.contentOffset.y < cell.frame.origin.y - 10 {
                    self.header.month = beforeCell.month
                    self.header.year = beforeCell.year
                }
            }
        }
        
    }
}




// MARK: -SET LAYOUT
extension CalendarView {
    func setLayoutConstraints() {
        setTableViewLayout()
        setHeaderViewLayout()
    }
    
    func setTableViewLayout() {
        self.addSubview(self.tableView)
        self.tableView.snp.makeConstraints({
            $0.top.bottom.left.right.equalTo(self)
        })
    }
    
    func setHeaderViewLayout() {
        self.addSubview(self.header)
        self.header.snp.makeConstraints({
            $0.left.right.top.equalTo(self)
            $0.height.equalTo(90.calculated)
        })
    }
}


class CalendarHeader: UIView {
    var year: Int = 0 {
        willSet(newVal) {
            self._year.attributedText = String(newVal)
                .normal(fontSize: 16, color: Color.customer, spacing: -0.07)
        }
    }
    
    var month: Int = 0 {
        willSet(newVal) {
            let str = String(newVal) + "."
            self._month.attributedText = str
                .systemFont(fontSize: 28, weight: .semibold, color: Color.customer, spacing: -0.12)
        }
    }
    
    private var _year: UILabel = {
        let label = UILabel()
        label.attributedText = "2019"
            .normal(fontSize: 16, color: Color.customer, spacing: -0.07)
        
        return label
    }()
    
    private var _month: UILabel = {
        let label = UILabel()
        label.attributedText = "11."
            .systemFont(fontSize: 28, weight: .semibold, color: Color.customer, spacing: -0.12)
        
        return label
    }()
    
    private var chevron: UIImageView = {
        let imageView = UIImageView()
        imageView.image = #imageLiteral(resourceName: "chevron_bottom")
        imageView.contentMode = .scaleAspectFit
        imageView.clipsToBounds = true
        
        return imageView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setLayoutConstraints()
        
        defer {
            self.year = CalendarHelper.today.year
            self.month = CalendarHelper.today.month
        }
    }
    
    required init(coder: NSCoder) {
        super.init(coder: coder)!
        
        setLayoutConstraints()
        defer {
            self.year = CalendarHelper.today.year
            self.month = CalendarHelper.today.month
        }
    }
    
    func setLayoutConstraints() {
        self.addSubview(self._year)
        self._year.snp.makeConstraints({
            $0.left.equalTo(self).offset(20.calculated)
            $0.top.equalTo(self).offset(41.calculated)
        })
        
        self.addSubview(self._month)
        self._month.snp.makeConstraints({
            $0.left.equalTo(self._year.snp.right).offset(4.calculated)
            $0.top.equalTo(self).offset(28.calculated)
        })
        
        self.addSubview(self.chevron)
        self.chevron.snp.makeConstraints({
            $0.width.height.equalTo(CGSize.ratio(width: 26, height: 14))
            $0.right.equalTo(self).offset(-20.calculated)
            $0.centerY.equalTo(self._month)
        })
    }
}

CalanderCell.swift

import Foundation
import UIKit
import SnapKit

class CalendarCell: UITableViewCell {
    let weekdays = ["S", "M", "T", "W", "T", "F", "S"]
    var dayOfWeek = 0
    var dayOfMonth = 0
    var day = 0
    
    var year: Int = 0 {
        willSet(newVal) {
            self._year.attributedText = String(newVal)
                .normal(fontSize: 16, color: Color.customer, spacing: -0.07)
        }
    }
    
    var month: Int = 0 {
        willSet(newVal) {
            let str = String(newVal) + "."
            self._month.attributedText = str
                .systemFont(fontSize: 28, weight: .semibold, color: Color.customer, spacing: -0.12)
        }
    }
    
    internal var _year: UILabel = {
        let label = UILabel()
        label.attributedText = "2019"
            .normal(fontSize: 16, color: Color.customer, spacing: -0.07)
        
        return label
    }()
    
    internal var _month: UILabel = {
        let label = UILabel()
        label.attributedText = "11."
            .systemFont(fontSize: 28, weight: .semibold, color: Color.customer, spacing: -0.12)
        
        return label
    }()
    
    internal var dayCollection: UICollectionView = {
        let collectionViewLayout = UICollectionViewFlowLayout()
        collectionViewLayout.scrollDirection = .vertical
        
        let collection = UICollectionView(
            frame: CGRect(x: 0, y: 0, width: 0, height: 0),
            collectionViewLayout: collectionViewLayout
        )
        collection.showsVerticalScrollIndicator = false
        collection.showsHorizontalScrollIndicator = false
        collection.isMultipleTouchEnabled = false
        collection.allowsMultipleSelection = false
        collection.isScrollEnabled = false
        collection.isExclusiveTouch = true
        collection.isUserInteractionEnabled = true
        collection.backgroundColor = Color.background
        collection.register(DayCell.self, forCellWithReuseIdentifier: DayCell.reuseIdentifier)
        
        
        return collection
    }()
    
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        setLayoutConstraints()
        
        
        dayCollection.delegate = self
        dayCollection.dataSource = self
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}





extension CalendarCell {

}





extension CalendarCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    /// 지정된 섹션에 표시할 항목의 개수를 묻는 메서드
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if section == 0 {
            return 7
        } else {
            print("dayOfWeek", dayOfMonth)
            return dayOfMonth + dayOfWeek - 1
        }
    }
    
    /// 컬렉션뷰의 지정된 위치에 표시할 셀을 요청하는 메서드.
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell: DayCell = collectionView.dequeueReusableCell(for: indexPath)
        cell.isUserInteractionEnabled = true
        
        if indexPath.section == 0 {
            cell.week = weekdays[indexPath.row]
        } else {
            if dayOfWeek > 1 {
                cell.day = ""
                dayOfWeek -= 1
            } else {
                day += 1
                cell.day = String(day)
                cell.isSunday = indexPath.row % 7 == 0
            }
        }
        
        return cell
    }
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 2
    }
    
    /// 지정된 섹션의 여백을 반환하는 메서드.
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 0, left: 25.calculated, bottom: 25.calculated, right: 25.calculated)
    }
    
    /// 지정된 섹션의 행 사이 간격 최소 간격을 반환하는 메서드
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 25
    }
    
    /// 지정된 섹션의 셀 사이의 최소간격을 반환하는 메서드.
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 25
    }
    
    /// 지정된 셀의 크기를 반환하는 메서드
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize.ratio(width: 30, height: 30)
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("indexPath: ", indexPath)
    }
}



extension CalendarCell {
    func setLayoutConstraints() {
        setHeaderLayout()
        setDayCollectionLayout()
    }
    
    func setHeaderLayout() {
        self.addSubview(self._year)
        self._year.snp.makeConstraints({
            $0.left.equalTo(self).offset(20.calculated)
            $0.top.equalTo(self).offset(61.calculated)
        })
        
        self.addSubview(self._month)
        self._month.snp.makeConstraints({
            $0.left.equalTo(self._year.snp.right).offset(4.calculated)
            $0.top.equalTo(self).offset(48.calculated)
        })
    }
    
    func setDayCollectionLayout() {
        self.addSubview(self.dayCollection)
        self.dayCollection.snp.makeConstraints({
            $0.height.equalTo(400.calculated)
            $0.left.right.equalTo(self)
            $0.top.equalTo(self).offset(116.calculated)
        })
    }
}

DayCell.swift

import Foundation
import UIKit

class DayCell: UICollectionViewCell {
    var isSunday: Bool = false {
        willSet(newVal) {
            self._day.textColor = newVal ? Color.customer : Color.label
        }
    }
    var isReserved: Bool = false {
        willSet(newVal) {
            self._day.textColor = Color.cancle
        }
    }
//    override var isSelected: Bool {
//        willSet(newVal) {
//            self.backgroundColor = newVal
//                ? Color.customer
//                : Color.background
//            self._day.textColor = newVal
//                ? .white
//                : (isSunday ? Color.customer : Color.label)
//        }
//    }
    var day: String = "" {
        willSet(newVal) {
            self._day.attributedText = newVal
                .systemFont(fontSize: 18, weight: .bold, color: Color.label, spacing: -0.07)
        }
    }
    var week: String = "" {
        willSet(newVal) {
            self._day.attributedText = newVal
                .systemFont(fontSize: 20, weight: .medium, color: Color.customer, spacing: -0.08)
        }
    }
    
    internal var _day: UILabel = {
        let label = UILabel()
        label.attributedText = "1"
            .systemFont(fontSize: 18, weight: .bold, color: Color.label, spacing: -0.07)
        
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.layer.cornerRadius = 7.calculated
        self.addSubview(self._day)
        self._day.snp.makeConstraints({
            $0.center.equalTo(self)
        })
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

這是錯誤的:

class DayCell: UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.layer.cornerRadius = 7.calculated
        self.addSubview(self._day) // <-- NO
        self._day.snp.makeConstraints({
            $0.center.equalTo(self)
        })
    }
}

永遠不要向單元格添加子視圖。

self.contentView.addSubview(self._day)

否則無法觸摸_day界面。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM