Reputation: 3
I'm making a calendar.
I put the collection view in the table view, but the cell of the collection view is not selected.
I just added the collection view to the table view cell and set all the dataSource settings.
TableView allowSelection is turned off, and tableViewCell isUserInteractionEnabled is set to false.
here for my code
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")
}
}
Upvotes: 0
Views: 643
Reputation: 535915
This is wrong:
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)
})
}
}
Never add a subview to a cell. Say
self.contentView.addSubview(self._day)
Otherwise it is impossible to touch the _day
interface.
Upvotes: 1