I've added long press programmatically but it does nothing.
What am I doing wrong? Thanks in advance.
import UIKit
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UIGestureRecognizerDelegate {
@IBOutlet weak var monthLabel: UILabel!
@IBOutlet weak var collectionView: UICollectionView!
var selectedDate = Date()
var totalSquares = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setCellView()
setMonthView()
func setupLongGestureRecognizerOnCollection() {
let longPressedGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongPress(gestureRecognizer:)))
longPressedGesture.minimumPressDuration = 0.5
longPressedGesture.delegate = self
longPressedGesture.delaysTouchesBegan = true
collectionView?.addGestureRecognizer(longPressedGesture)
}
}
func setCellView() {
let width = (collectionView.frame.size.width - 2) / 8
let height = (collectionView.frame.size.height - 2) / 8
let flowLayout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
flowLayout.itemSize = CGSize(width: width, height: height)
}
func setMonthView(){
totalSquares.removeAll()
let daysInMonth = CalendarHelper().daysInMonth(date: selectedDate)
let firstDayOfMonth = CalendarHelper().firstOfMonth(date: selectedDate)
let startingSpaces = CalendarHelper().weekDay(date: firstDayOfMonth)
var count: Int = 1
while(count <= 42) {
if(count <= startingSpaces || count - startingSpaces > daysInMonth)
{
totalSquares.append("")
}
else
{
totalSquares.append(String(count - startingSpaces))
}
count += 1
}
monthLabel.text = CalendarHelper().monthString(date: selectedDate) + " " + CalendarHelper().yearString(date: selectedDate)
collectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return totalSquares.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "calCell", for: indexPath) as! CalendarCell
cell.dayOfMonth.text = totalSquares [indexPath.item]
return cell
}
@objc func handleLongPress(gestureRecognizer: UILongPressGestureRecognizer) {
if (gestureRecognizer.state != .began) {
return
}
let p = gestureRecognizer.location(in: collectionView)
if let indexPath = collectionView?.indexPathForItem(at: p) {
print("Long press at item: \(indexPath.row)")
}
}
@IBAction func previousMonthButton(_ sender: Any) {
selectedDate = CalendarHelper().minusMonth(date: selectedDate)
setMonthView()
}
@IBAction func nextMonthButton(_ sender: Any) {
selectedDate = CalendarHelper().plusMonth(date: selectedDate)
setMonthView()
}
override open var shouldAutorotate: Bool {
return false
}
}
The GitHub source is here:
github.com/codeWithCal/CalendarExampleTutorial
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
I have a collectionview of UILabels.
when you tap a cell it should display its detail onto a pop up modal view.
How do you display it onto that modal view in the same View controller?
2a. How can you cycle (loop) a group of arrays via UILabel forward and backwards in cells?
2b. How do you filter the arrays so that it always shows with a specific cell? (eg: Cell 2 will always have "D, E, F" when scrolling through)
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return totalSquares.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "calCell", for: indexPath) as! CalendarCell
cell.dayOfMonth.text = totalSquares[indexPath.item]
return cell
}
// Cell 1 Cell 2 Cell 3
let myArray: String = [[" A, B, C"], ["D, E, F"], ["G, H, I"]] etc..
I have a ViewController that calls a Xib view to popup (as a PressentationController). I need to put a single cell collectonview on that Xib view. How can I go about doing that because I cannot embed a collectionview in a Xib via storyboard. Is there a way to do that programmatically?
Not sure what Im doing wrong here. Says "Cannot convert value of type 'String' to expected argument type 'Int'".
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "calCell", for: indexPath) as! CalendarCell
cell.dayOfMonth.text = totalSquares[indexPath.item]
//show the weekend days in different color
switch indexPath.item {
case 0,6,7,13,14,20,21,27,28,34,35,41:
if Int(cell.dayOfMonth.text = "\(indexPath.item)" > 0 {
cell.dayOfMonth.textColor = UIColor.lightGray
}
default:
break
}
return cell
}
I embedded a vertical scrollview to a calendar that was originally horizontally navigation with buttons. But its isn't scrolling changing months. What am I missing?
let days = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"]
@State private var selectedMonth = 0
@State private var selectedDate = Date()
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
ScrollView {
VStack {
Rectangle()
.frame(height: 1)
.foregroundColor(.gray)
VStack(spacing: 20) {
// Month Selection
HStack {
Spacer()
Button {
withAnimation {
selectedMonth -= 1
}
} label: {
Image(systemName: "lessthan.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 32, height: 32)
.foregroundColor(.gray)
}
Spacer()
Text(selectedDate.monthYearFormat())
.font(.title2)
Spacer()
Button {
withAnimation {
selectedMonth += 1
}
} label: {
Image(systemName: "greaterthan.circle.fill")
.resizable()
.scaledToFit()
.frame(width: 32, height: 32)
.foregroundColor(.gray)
}
Spacer()
}
HStack {
ForEach(days, id:\.self) { day in
Text(day)
.font(.system(size: 12, weight: .medium))
.frame(maxWidth: .infinity)
}
}
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 7), spacing: 20) {
ForEach(fetchDates()) { value in
ZStack {
if value.day != -1 {
let hasAppts = manager.days.contains(value.date.monthDayYearFormat())
NavigationLink(value: AppRouter.day(date: value.date)) {
Text("\(value.day)")
.foregroundColor(hasAppts ? .blue : .black)
.fontWeight(hasAppts ? .bold : .none)
.background {
ZStack(alignment: .bottom) {
Circle()
.frame(width: 48, height: 48)
.foregroundColor(hasAppts ? .blue.opacity(0.1) : .clear)
if value.date.monthDayYearFormat() == Date().monthDayYearFormat() {
Circle()
.frame(width: 8, height: 8)
.foregroundColor(hasAppts ? .blue : .gray)
}
}
}
}
.disabled(!hasAppts)
} else {
Text("")
}
}
.frame(width: 32, height: 32)
}
}
}
.padding()
}
}
.navigationDestination(for: AppRouter.self) { router in
switch router {
case .day(let date):
DayView(path: $path, currentDate: date)
.environmentObject(manager)
case .booking(let date):
BookingView(path: $path, currentDate: date)
.environmentObject(manager)
case .confirmation(let date):
ConfirmationView(path: $path, currentDate: date)
}
}
.frame(maxHeight: .infinity, alignment: .top)
.onChange(of: selectedMonth) { _ in
selectedDate = fetchSelectedMonth()
}
}
}
func fetchDates() -> [CalendarDate] {
let calendar = Calendar.current
let currentMonth = fetchSelectedMonth()
var dates = currentMonth.datesOfMonth().map({ CalendarDate(day: calendar.component(.day, from: $0), date: $0) })
let firstDayOfWeek = calendar.component(.weekday, from: dates.first?.date ?? Date())
for _ in 0..<firstDayOfWeek - 1 {
dates.insert(CalendarDate(day: -1, date: Date()), at: 0)
}
return dates
}
func fetchSelectedMonth() -> Date {
let calendar = Calendar.current
let month = calendar.date(byAdding: .month, value: selectedMonth, to: Date())
return month!
}
}
HStack {
ForEach(days, id:\.self) { day in
Text(day)
.font(.system(size: 12, weight: .medium))
.frame(maxWidth: .infinity)
}
}
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 7), spacing: 20) {
ForEach(fetchDates()) { value in
ZStack {
if value.day != -1 {
let hasAppts = manager.days.contains(value.date.monthDayYearFormat())
NavigationLink(value: AppRouter.day(date: value.date)) {
Text("\(value.day)")
.foregroundColor(hasAppts ? .blue : .black)
.fontWeight(hasAppts ? .bold : .none)
.background {
ZStack(alignment: .bottom) {
Circle()
.frame(width: 48, height: 48)
.foregroundColor(hasAppts ? .blue.opacity(0.1) : .clear)
if value.date.monthDayYearFormat() == Date().monthDayYearFormat() {
Circle()
.frame(width: 8, height: 8)
.foregroundColor(hasAppts ? .blue : .gray)
}
}
}
}
.disabled(!hasAppts)
} else {
Text("")
}
}
.frame(width: 32, height: 32)
}
}
}
.padding()
}
can't see what the problem is .. Im getting the error:
Type '()' cannot conform to 'View'
struct CalendarView: View {
@StateObject private var viewModel = CalendarViewModel()
@State private var selectedDate: CalendarDate?
@State private var showModal = false
var body: some View {
VStack {
Text("Calendar App")
.font(.largeTitle)
.padding()
GridStack(rows: 5, columns: 7) { row, col in
let index = row * 7 + col
if index < viewModel.calendarDates.count {
let calendarDate = viewModel.calendarDates[index]
Text("\(Calendar.current.component(.day, from: calendarDate.date))")
.frame(width: 40, height: 40)
.background(calendarDate.isSelected ? Color.blue : Color.clear)
.cornerRadius(10)
.foregroundColor(calendarDate.isSelected ? Color.white : Color.black)
.onLongPressGesture {
selectedDate = calendarDate
showModal = true
}
}
}
}
.background(Color.gray)
.sheet(isPresented: $showModal) {
if let date = selectedDate {
DateSelectionModal(selectedDate: date)
}
}
}
}
struct GridStack<Content: View>: View {
let rows: Int
let columns: Int
let content: (Int, Int) -> Content
var body: some View {
VStack {
ForEach(0..<rows) { row in
HStack {
ForEach(0..<columns) { column in
content(row, column)
}
}
}
}
}
}
#Preview {
CalendarView()
}
Topic:
UI Frameworks
SubTopic:
SwiftUI