FSCalendar content getting squished when I switch scope to month - ios

My FSCalendar's content shrinks when I switch its scope from week to month if there is a view that's constrained to its bottom anchor.
Here is a quick gif to show what exactly is happening
I have tried everything at this point. Using calendar.setScope() instead of calendar.scope =, constraining attachedToCalendarView.topAnchor to calendar.bottomAnchor calendar.contentView.bottomAnchor, and calendar.daysContainer.bottomAnchor, even turning attachedToCalendarView 's constraints on and off depending on whether it's week scope or scope month.
Not sure what else to try. Here is the code:
import UIKit
import FSCalendar
class TestController : UIViewController, FSCalendarDataSource, FSCalendarDelegate, FSCalendarDelegateAppearance {
fileprivate weak var calendar: FSCalendar!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setUp()
}
#objc func switchCalendarScope(){
if self.calendar.scope == FSCalendarScope.month {
self.calendar.scope = FSCalendarScope.week
} else {
self.calendar.scope = FSCalendarScope.month
}
}
func setUp(){
let calendar = FSCalendar()
calendar.dataSource = self
calendar.delegate = self
self.calendar = calendar
self.calendar.scope = .week
self.calendar.locale = Locale(identifier: "en_EN")
self.calendar.calendarHeaderView.calendar.locale = Locale(identifier: "en_EN")
self.calendar.adjustsBoundingRectWhenChangingMonths = true
let testingView = UIView()
testingView.backgroundColor = .red
let attachedToCalendarView = UIView()
attachedToCalendarView.backgroundColor = .blue
view.addSubview(calendar)
view.addSubview(testingView)
view.addSubview(attachedToCalendarView)
self.calendar.translatesAutoresizingMaskIntoConstraints = false
self.calendar.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
self.calendar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
self.calendar.widthAnchor.constraint(equalToConstant: view.bounds.size.width).isActive = true
self.calendar.heightAnchor.constraint(equalToConstant: 300).isActive = true
testingView.translatesAutoresizingMaskIntoConstraints = false
testingView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
testingView.widthAnchor.constraint(equalToConstant: view.bounds.size.width).isActive = true
testingView.heightAnchor.constraint(equalToConstant: 20).isActive = true
attachedToCalendarView.translatesAutoresizingMaskIntoConstraints = false
attachedToCalendarView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
// Attaching this view's topAnchor to the calendar's bottom anchor
attachedToCalendarView.topAnchor.constraint(equalTo: self.calendar.contentView.bottomAnchor).isActive = true
attachedToCalendarView.widthAnchor.constraint(equalToConstant: view.bounds.size.width).isActive = true
attachedToCalendarView.heightAnchor.constraint(equalToConstant: 20).isActive = true
// Title and button to toggle the calendar scope
self.navigationItem.title = "Test"
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Toggle", style: .done, target: self, action: #selector(switchCalendarScope))
}
}

Well, I couldn't figure out how to fix the problem itself but I did find a workaround. I placed the calendar inside of an empty container view (just a simple UIView) and attached attachedToCalendarView to the container's bottomAnchor instead of the calendar's itself.
Do note however that using setScope, which animates the transition, still causes the same issue. For it to work you have to set it manually like calendar.scope = x
example:
#objc func switchCalendarScope(){
if self.calendar.scope == FSCalendarScope.month {
// self.calendar.setScope(FSCalendarScope.week, animated: true) // this will cause the calendar to be squished again
self.calendar.scope = .week
movingConstraint.constant = view.safeAreaLayoutGuide.layoutFrame.size.height * -0.20
} else {
// self.calendar.setScope(FSCalendarScope.month, animated: true)
self.calendar.scope = .month
movingConstraint.constant = 0
}
}

Related

view controller storyboard not displaying

I am a beginner on Xcode and I am trying to embed YouTube video to child controllers of a side menu, but I can't connect my view controller file and my UI view controllers on the storyboard.
I am coding a side menu controller and the child views controllers are called using:
class Course2ViewController: UIViewController, MenuControllerDelegate2 {
private var sideMenu: SideMenuNavigationController?
private let abaController = abaViewController()
private let abbController = abbViewController()
private let abcController = abcViewController()
private let abdController = abdViewController()
override func viewDidLoad() {
super.viewDidLoad()
let menu = MenuController2(with: SideMenuItem2.allCases)
menu.delegate = self
sideMenu = SideMenuNavigationController(rootViewController: menu)
sideMenu?.leftSide = true
SideMenuManager.default.leftMenuNavigationController = sideMenu
SideMenuManager.default.addPanGestureToPresent(toView: view)
AddChildControllers()
}
private func AddChildControllers() {
addChild(abaController)
addChild(abbController)
addChild(abcController)
addChild(abdController)
view.addSubview(abaController.view)
view.addSubview(abbController.view)
view.addSubview(abcController.view)
view.addSubview(abdController.view)
abaController.view.frame = view.bounds
abbController.view.frame = view.bounds
abcController.view.frame = view.bounds
abdController.view.frame = view.bounds
abaController.didMove(toParent: self)
abbController.didMove(toParent: self)
abcController.didMove(toParent: self)
abdController.didMove(toParent: self)
abaController.view.isHidden = true
abbController.view.isHidden = true
abcController.view.isHidden = true
abdController.view.isHidden = true
}
#IBAction func didTapMenuButton2() {
present(sideMenu!, animated: true)
}
func didSelectMenuItem2(named: SideMenuItem2) {
sideMenu?.dismiss(animated: true, completion: nil)
title = named.rawValue
switch named {
case.aba:
abaController.view.isHidden = false
abbController.view.isHidden = true
abcController.view.isHidden = true
abdController.view.isHidden = true
case.abb:
abaController.view.isHidden = true
abbController.view.isHidden = false
abcController.view.isHidden = true
abdController.view.isHidden = true
case.abc:
abaController.view.isHidden = true
abbController.view.isHidden = true
abcController.view.isHidden = false
abdController.view.isHidden = true
case.abd:
abaController.view.isHidden = true
abbController.view.isHidden = true
abcController.view.isHidden = true
abdController.view.isHidden = false
}
}
}
then, I tried to connect my abaViewController file to a new view controller on storyboard by giving the later the class "abaViewController", but my view controller on storyboard is not displayed. Any tips/solutions?

Subview containing UITextfield isn't registering tapgesture

I have a subview with a textfield. I'd like the keyboard to be dismissed when I tap anywhere outside of the textfield, but the problem is that taps within the subview aren't being registered and only taps outside of the subview dismiss the keyboard.
My view has a subview (coverView):
var coverView: UIView = {
let cover = UIView()
cover.translatesAutoresizingMaskIntoConstraints = false
cover.backgroundColor = .white
cover.widthAnchor.constraint(equalToConstant: 300).isActive = true
cover.heightAnchor.constraint(equalToConstant: 300).isActive = true
cover.clipsToBounds = true
return cover
}()
This coverView has its own ImageView:
var coverImageView: UIImageView = {
let imageView = UIImageView(image: nil)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.backgroundColor = .white
imageView.contentMode = .scaleAspectFill
imageView.isUserInteractionEnabled = true
return imageView
}()
The coverView has a UITextfield added to it when tapped:
#objc func imageTapped(_ sender: UITapGestureRecognizer) {
guard self.textfield1.text == "" else {return}
self.coverView.addSubview(textfield1)
self.textfield1.centerXAnchor.constraint(equalTo: self.coverView.centerXAnchor).isActive = true
self.textfield1.centerYAnchor.constraint(equalTo: self.coverView.centerYAnchor).isActive = true
self.textfield1.becomeFirstResponder()
}
If the user taps anywhere I'd like the keyboard to dismiss. I do this using the following code:
#objc func keyboardDidShow() {
let exitTapGesture = UITapGestureRecognizer(target: self, action: #selector(exitKeyboardTap(_:)))
exitTapGesture.name = "exitTap"
exitTapGesture.delegate = self
self.view.addGestureRecognizer(exitTapGesture)
}
However, the keyboard only dismisses when I tap outside of the coverView. When I tap anywhere inside of the coverView the keyboard does not dismiss.
Try to add gesture to coverView
private func getTapGesture() -> UITapGestureRecognizer {
let exitTapGesture = UITapGestureRecognizer(target: self, action: #selector(exitKeyboardTap(_:)))
exitTapGesture.delegate = self
return exitTapGesture
}
#objc func keyboardDidShow() {
coverView.addGestureRecognizer(getTapGesture())
self.view.addGestureRecognizer(getTapGesture())
}

UIPasteboard retrieving previous item

I've got the following code:
[[UIApplication sharedApplication] sendAction:#selector(copy:) to:nil from:self forEvent:nil];
NSString *string = [UIPasteboard generalPasteboard].string;
The problem is that the pasteboard is returning what I've copied previously, not currently. Somehow it's hanging onto the previous item I've copied and returning that, and then next time around I get the item that I wanted and copied... strange behaviour.. any ideas?
Edit
I've got a solution using an observer, but not sure how elegant it is.. there seems to be some delay between copy and setting an item.. enough for it not to be set and for the previous one to be still on the UIPasteBoard.
I have composed a little sample to your code for copy/paste behavior and it works as expected: selected text is printed to console after tapping on the button.
class ViewController: UIViewController {
let textField = UITextField()
let copyButton = UIButton(type: .roundedRect)
#objc func copySelectedText() {
UIApplication.shared.sendAction(#selector(UIResponder.copy(_:)), to: nil, from: self, for: nil)
let copiedString = UIPasteboard.general.string
print(copiedString)
}
override func viewDidLoad() {
super.viewDidLoad()
textField.borderStyle = .roundedRect
view.backgroundColor = .darkGray
display(textField, copyButton)
copyButton.setTitle("tap to copy selected text", for: .normal)
copyButton.addTarget(self, action: #selector(copySelectedText), for: .touchUpInside)
}
private func display(_ textField: UITextField, _ copyButton: UIButton) {
copyButton.translatesAutoresizingMaskIntoConstraints = false
textField.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(copyButton)
view.addSubview(textField)
textField.backgroundColor = .white
textField.widthAnchor.constraint(greaterThanOrEqualToConstant: 200).isActive = true
textField.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textField.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
copyButton.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 20).isActive = true
copyButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
}

Eureka Form in UITableView programmatically?

I am using Eureka Forms in my Swift 4 app and I do not use storyboards. Setting up the form programmatically is working fine, however I am using a popoverPresentationController to display a UIViewController with a NavBar in and using the form as a FormViewController means the top of the form is hidden underneath the NavBar.
I'd like make the Class as UIViewController and then add the Eureka form as a Subview so I can using constraints as normal. I understand this is achieved by using UITableView, so I have set it up as follows but I'm not sure how to wire in the Eureka Form and I can't find anything in the documentation about it.
import UIKit
import Eureka
class TestForm: UIViewController, UITableViewDelegate {
let navBar: UINavigationBar = {
let nav = UINavigationBar(frame: .zero)
nav.translatesAutoresizingMaskIntoConstraints = false
return nav
}()
let formTable: UITableView = {
let table = UITableView(frame: .zero, style: .grouped)
table.translatesAutoresizingMaskIntoConstraints = false
table.backgroundColor = .red
return table
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(navBar)
view.addSubview(formTable)
formTable.delegate = self
navBar.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
navBar.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
navBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
navBar.heightAnchor.constraint(equalToConstant: 44).isActive = true
formTable.translatesAutoresizingMaskIntoConstraints = false
formTable.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
formTable.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
formTable.topAnchor.constraint(equalTo: navBar.bottomAnchor).isActive = true
formTable.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
let navItem = UINavigationItem(title: "Add Event")
let cancelItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.cancel, target: nil, action: #selector(dismissView))
navItem.leftBarButtonItem = cancelItem
navBar.setItems([navItem], animated: false)
Form +++ Section("First Section")
<<< TextRow("Section 1 Text"){ row in
row.title = "Text Row"
row.placeholder = "Enter text here"
}
<<< PhoneRow("Section 1 Phone"){
$0.title = "Phone Row"
$0.placeholder = "And numbers here"
}
.onCellSelection({ (cell, row) in
self.saveForm()
})
}
}
Any pointers?

How to scroll my UIViewController content?

I've been trying to search for a swift version of a solution to no avail. I was wondering how I can make my view controller scroll content. Right now it's just static, and there's more content below, which I'm unable to scroll.
class ProfileViewController: UIViewController, UICollectionViewDelegateFlowLayout {
let postsId = "postsId"
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(profileContainerView)
view.addSubview(profileTabCollection)
view.addSubview(containerForCollectionView)
view.addSubview(scrollView)
scrollView.widthAnchor.constraintEqualToConstant(view.frame.size.width).active = true
scrollView.heightAnchor.constraintEqualToConstant(view.frame.size.height).active = true
scrollView.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor).active = true
scrollView.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor).active = true
scrollView.userInteractionEnabled = true
scrollView.scrollEnabled = true
scrollView.delegate = self
containerForCollectionView.widthAnchor.constraintEqualToConstant(scrollView.frame.size.width).active = true
containerForCollectionView.heightAnchor.constraintEqualToConstant(scrollView.frame.size.height).active = true
containerForCollectionView.topAnchor.constraintEqualToAnchor(profileTabCollection.bottomAnchor).active = true
profileContainerView.widthAnchor.constraintEqualToConstant(scrollView.frame.size.width).active = true
profileContainerView.heightAnchor.constraintEqualToConstant(250).active = true
profileContainerView.centerXAnchor.constraintEqualToAnchor(scrollView.centerXAnchor).active = true
profileContainerView.topAnchor.constraintEqualToAnchor(topLayoutGuide.bottomAnchor).active = true
profileTabCollection.widthAnchor.constraintEqualToAnchor(profileContainerView.widthAnchor).active = true
profileTabCollection.heightAnchor.constraintEqualToConstant(50).active = true
profileTabCollection.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor).active = true
profileTabCollection.topAnchor.constraintEqualToAnchor(profileContainerView.bottomAnchor).active = true
}
lazy var scrollView: UIScrollView = {
let sv = UIScrollView(frame: CGRectMake(0,0,1024,768))
sv.contentSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height * 3)
sv.translatesAutoresizingMaskIntoConstraints = false
return sv
}()
let containerForCollectionView: UIView = {
let view = UIView()
view.backgroundColor = UIColor.purpleColor()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
There are numerous reasons why this won't work. Since you don't provide enough information to be sure what it is, i'd recommend reading this (especially Duncan C's answer) carefully.
how do i alter the position of a UIImage inside a imageView in SWIFT
Write these lines in override layoutSubviews() method.
scrollView.widthAnchor.constraintEqualToAnchor(view.widthAnchor).active = true
scrollView.heightAnchor.constraintEqualToAnchor(view.heightAnchor).active = true
Make sure you created UIScrollView in your UIViewController, otherwise it won't work for sure.
If you are using swift 2.0 and you have used "UIScrollViewDelegate"- you need to add this method
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imgview
}
And if you are using swift 3.0 - you need this function
func viewForZooming( in scrollView: UIScrollView) -> UIView? {
return imgview
}

Resources