I'm trying to create several UITableViews programmatically in the same scroll view. I'm correctly loading the tables' data into each array, but for some reason the table is populating every other cell. I added a print statement in cellForRowAt: to make sure it wasn't skipping data somehow and it doesn't seem to.
Also, didSelectRowAt: isn't being called when I click on a row, but didHighlightRowAt: is called correctly. And using that the table cells seem to load properly, it's just skipping every other cell when populating them.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cellIdentifier = ""
switch tableView {
case tableView1:
cellIdentifier = "AddOnTableViewCell1"
case tableView2:
cellIdentifier = "AddOnTableViewCell2"
case tableView3:
cellIdentifier = "AddOnTableViewCell3"
case tableView4:
cellIdentifier = "AddOnTableViewCell4"
default:
print("Too many tables")
}
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? AddOnTableViewCell else {
fatalError("Dequed cell error")
}
let titleLabel = UILabel(frame: CGRect(x: 16, y: cell.frame.minY + 10, width: view.frame.width - 30, height: 30))
titleLabel.textColor = .black
titleLabel.textAlignment = .left
switch tableView {
case tableView1:
titleLabel.text = addOnContents1[indexPath.row]
print("\(indexPath.row), \(addOnContents1[indexPath.row])")
case tableView2:
titleLabel.text = addOnContents2[indexPath.row]
print("\(indexPath.row), \(addOnContents2[indexPath.row])")
case tableView3:
titleLabel.text = addOnContents3[indexPath.row]
print("\(indexPath.row), \(addOnContents3[indexPath.row])")
case tableView4:
titleLabel.text = addOnContents4[indexPath.row]
print("\(indexPath.row), \(addOnContents4[indexPath.row])")
default:
print("Too many tables")
}
cell.addSubview(titleLabel)
return cell
}
The print statements above show that the data added correctly corresponds to the indexRow.path, i.e. 0 is item00, 1 is item01, 2 is item02, 3 is item03, ...
Then here are the other two methods mentioned.
func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) {
switch tableView {
case tableView1:
print(addOnContents1[indexPath.row])
case tableView2:
print(addOnContents2[indexPath.row])
case tableView3:
print(addOnContents3[indexPath.row])
case tableView4:
print(addOnContents4[indexPath.row])
default:
print("Too many tables")
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Pressed")
switch tableView {
case tableView1:
print(indexPath.row)
case tableView2:
print(indexPath.row)
case tableView3:
print(indexPath.row)
case tableView4:
print(indexPath.row)
default:
print("Too many tables")
}
}
Finally, here's my code for setting up the tableViews
func loadAddOnViews() {
var count = 1
for item in addOns {
var contentSize: CGFloat = 0
switch count {
case 1:
let label = UILabel(frame: CGRect(x: 16, y: yCoordinateForNewContent, width: scrollView.frame.width - 32, height: 50))
label.text = addOns[0].title
yCoordinateForNewContent += 50
scrollView.addSubview(label)
contentSize = CGFloat(addOnContents1.count)
print("content size: \(contentSize)")
contentSize = contentSize * cellSize
tableView1 = UITableView(frame: CGRect(x: 0, y: yCoordinateForNewContent, width: scrollView.frame.width, height: contentSize))
scrollView.addSubview(tableView1)
tableView1.delegate = self
tableView1.dataSource = self
self.tableView1.register(AddOnTableViewCell.self, forCellReuseIdentifier: "AddOnTableViewCell1")
yCoordinateForNewContent += contentSize + 20
tableView1.reloadData()
case 2:
let label = UILabel(frame: CGRect(x: 16, y: yCoordinateForNewContent, width: scrollView.frame.width - 32, height: 50))
label.text = addOns[1].title
yCoordinateForNewContent += 50
scrollView.addSubview(label)
contentSize = CGFloat(addOnContents2.count)
print("content size: \(contentSize)")
contentSize = contentSize * cellSize
tableView2 = UITableView(frame: CGRect(x: 0, y: yCoordinateForNewContent, width: scrollView.frame.width, height: contentSize))
scrollView.addSubview(tableView2)
tableView2.delegate = self
tableView2.dataSource = self
self.tableView2.register(AddOnTableViewCell.self, forCellReuseIdentifier: "AddOnTableViewCell2")
yCoordinateForNewContent += contentSize + 20
tableView2.reloadData()
case 3:
let label = UILabel(frame: CGRect(x: 16, y: yCoordinateForNewContent, width: scrollView.frame.width - 32, height: 50))
label.text = addOns[2].title
yCoordinateForNewContent += 50
scrollView.addSubview(label)
contentSize = CGFloat(addOnContents3.count)
print("content size: \(contentSize)")
contentSize = contentSize * cellSize
tableView3 = UITableView(frame: CGRect(x: 0, y: yCoordinateForNewContent, width: scrollView.frame.width, height: contentSize))
scrollView.addSubview(tableView3)
tableView3.delegate = self
tableView3.dataSource = self
self.tableView3.register(AddOnTableViewCell.self, forCellReuseIdentifier: "AddOnTableViewCell3")
yCoordinateForNewContent += contentSize + 20
tableView3.reloadData()
case 4:
let label = UILabel(frame: CGRect(x: 16, y: yCoordinateForNewContent, width: scrollView.frame.width - 32, height: 50))
label.text = addOns[3].title
yCoordinateForNewContent += 50
scrollView.addSubview(label)
contentSize = CGFloat(addOnContents4.count)
print("content size: \(contentSize)")
contentSize = contentSize * cellSize
tableView4 = UITableView(frame: CGRect(x: 0, y: yCoordinateForNewContent, width: scrollView.frame.width, height: contentSize))
scrollView.addSubview(tableView4)
tableView4.delegate = self
tableView4.dataSource = self
self.tableView4.register(AddOnTableViewCell.self, forCellReuseIdentifier: "AddOnTableViewCell4")
yCoordinateForNewContent += contentSize + 20
tableView4.reloadData()
default:
print("too many tables")
}
count += 1
}
}
And here's the screen with example data:
SimulatorScreen
Any help is greatly appreciated!
Thanks #Naresh for bringing my attention to this. I had declared the label in the AddOnTableViewCell class, but I was creating a label in the cellForRowAt: method, which I was adding as a subview to the cell. I simplified the tables to a single table with an array of arrays to hold the data. I made the following change to my AddOnTableViewCell class:
class AddOnTableViewCell: UITableViewCell {
var titleLabel: UILabel!
init(frame: CGRect, title:String) {
super.init(style: .default, reuseIdentifier: "AddOnTableViewCell")
titleLabel = UILabel(frame: CGRect(x: 16 , y: self.frame.minY + 10, width: self.frame.width - 32, height: 40))
titleLabel.textColor = UIColor.black
titleLabel.text = title
addSubview(titleLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}}
and I simplified my cellForRowAt: method:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let title = tableContents[indexPath.section][indexPath.row]
let cell = AddOnTableViewCell(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: cellSize), title: title)
return cell
}
Thanks!
Related
I am trying to implement a method to where I have a tableviewcontroll that has a header where it shows a head picture as well as another section with the User's information and Profile picture. Below the head I want there to be a segment control like twitter that will allow a user to switch between different tableviews. I want that segment control to be below the header view so when a user pulls down, the segment control moves down with the header view, when you scroll up the segment control moves up with the headerview but then sticks below the navigation bar similar to how twitter and instagram's UI works. I have implemented the code below but I am getting an issue to when I scroll up, the segment controller doesn't move but when I pull down on the screen the segment control moves down with the header view. Any Idea why it is doing this?
Here is the code
class RandomTableViewController: UITableViewController {
#IBOutlet weak var trackImage: UIImageView!
private let tableHeaderViewHeight: CGFloat = 320.0
private let tableHeaderViewCutAway: CGFloat = 0.1
var headerView: HeaderView!
var headerMaskLayer: CAShapeLayer!
override func viewDidLoad() {
super.viewDidLoad()
self.automaticallyAdjustsScrollViewInsets = false
tableView.estimatedSectionHeaderHeight = 40.0
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
tableView.tableFooterView = UIView()
headerView = tableView.tableHeaderView as! HeaderView
// headerView.imageView = trackImage
tableView.tableHeaderView = nil
tableView.addSubview(headerView)
tableView.contentInset = UIEdgeInsets(top: tableHeaderViewHeight, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, y: -tableHeaderViewHeight + 64)
//cut away header view
headerMaskLayer = CAShapeLayer()
headerMaskLayer.fillColor = UIColor.black.cgColor
headerView.layer.mask = headerMaskLayer
let effectiveHeight = tableHeaderViewHeight - tableHeaderViewCutAway/2
tableView.contentInset = UIEdgeInsets(top: effectiveHeight, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, y: -effectiveHeight)
updateHeaderView()
}
func updateHeaderView() {
let effectiveHeight = tableHeaderViewHeight - tableHeaderViewCutAway/2
var headerRect = CGRect(x: 0, y: -effectiveHeight, width: tableView.bounds.width, height: tableHeaderViewHeight)
if tableView.contentOffset.y < -effectiveHeight {
headerRect.origin.y = tableView.contentOffset.y
headerRect.size.height = -tableView.contentOffset.y + tableHeaderViewCutAway/2
}
headerView.frame = headerRect
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y:0))
path.addLine(to: CGPoint(x: headerRect.width, y: 0))
path.addLine(to: CGPoint(x: headerRect.width, y: headerRect.height))
path.addLine(to: CGPoint(x: 0, y: headerRect.height - tableHeaderViewCutAway))
headerMaskLayer?.path = path.cgPath
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
self.tableView.decelerationRate = UIScrollView.DecelerationRate.fast
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return UITableView.automaticDimension
}
#IBAction func backButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
extension RandomTableViewController {
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let v = UIView()
v.backgroundColor = .white
let segmentedControl = UISegmentedControl(frame: CGRect(x: 10, y: 5, width: tableView.frame.width - 20, height: 30))
segmentedControl.insertSegment(withTitle: "One", at: 0, animated: false)
segmentedControl.insertSegment(withTitle: "Two", at: 1, animated: false)
segmentedControl.insertSegment(withTitle: "Three", at: 2, animated: false)
v.addSubview(segmentedControl)
return v
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
100
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell! = tableView.dequeueReusableCell(withIdentifier: "CellID")
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
}
extension RandomTableViewController {
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
updateHeaderView()
}
}
I have custom HeaderView code which is
import UIKit
class HeaderView: UIView {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var trackImage: UIImageView!
#IBOutlet weak var backButton: UIButton!
}
Here is what it is doing
UPDATE:
I implemented the grouped tableview and setting the estimatedSectioHeaderHeight in the viewForSectionInHeader and now the segmented control moves up and down but it is not sticking below the navigation bar when scrolling up. Also there seems to be a formatting issue now. Here is how the simulator looks
change the table style to grouped and set height of the segment view in heightForHeaderInSection.
Check whether it works.
My scenario, I am trying to create UITableview with card effects and top banner. I have added It will work like stretchable tableview header. Everything I am done by using storyboard but I am stuck in showing half of tableview first index cell show on banner head. I tried multiple ideas but I didn’t completed. Provide some idea for achieve this design.
Current Output:
Expected Output:
From your demo project HERE I have made some changes to you existing code like your scrollViewDidScroll will be:
var lastContentOffset: CGFloat = 0
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.lastContentOffset = scrollView.contentOffset.y
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if self.lastContentOffset < scrollView.contentOffset.y {
//Up
let y = 220 - (scrollView.contentOffset.y + 220)
let height = min(max(y, 60), 220)
if height >= 128 {
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height + 70)
}
} else if self.lastContentOffset > scrollView.contentOffset.y {
//Down
let y = 300 - (scrollView.contentOffset.y + 300)
let height = min(max(y, 60), 400)
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height + 80)
}
}
With above code I have added different conditions for up and down as per your requirement and from storyboard I have change top constraint to 84 so that your table will not scroll to top.
So your full code will look like:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
let imageView = UIImageView()
var lastContentOffset: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 50
tableView.contentInset = UIEdgeInsetsMake(220, 0, 0, 0)
tableView.backgroundColor = UIColor.darkGray
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 300)
imageView.image = UIImage.init(named: "poster")
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
view.addSubview(imageView)
self.tableView.backgroundColor = .clear
self.view.bringSubview(toFront: tableView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomTableViewCell
switch indexPath.row % 2 {
case 0:
cell.titleLabel.text = "Lorem Ipsum is simply dummy text ."
cell.contentView.backgroundColor = UIColor.darkGray
default:
cell.contentView.backgroundColor = UIColor.black
cell.titleLabel.text = "There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain..."
cell.titleLabel.textColor = .white
}
return cell
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.lastContentOffset = scrollView.contentOffset.y
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if self.lastContentOffset < scrollView.contentOffset.y {
let y = 220 - (scrollView.contentOffset.y + 220)
let height = min(max(y, 60), 220)
if height >= 128 {
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height + 70)
}
} else if self.lastContentOffset > scrollView.contentOffset.y {
let y = 300 - (scrollView.contentOffset.y + 300)
let height = min(max(y, 60), 400)
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height + 80)
}
}
}
And result will be:
HERE is the link for your updated project.
I have a static tableView that I am creating like so....
override func viewDidLoad() {
super.viewDidLoad()
usernameLabel.text = "Username"
usernameDisplay.text = "placeholder"
usernameDisplay.textColor = self.view.tintColor
usernameLabel.frame = CGRect(x: self.view.bounds.minX, y: self.usernameCell.bounds.minY, width: self.view.frame.width, height: self.usernameCell.bounds.height)
usernameDisplay.frame = CGRect(x: self.usernameCell.bounds.minX, y: self.usernameCell.bounds.minY, width: self.view.frame.width, height: self.usernameCell.bounds.height)
usernameDisplay.textAlignment = .right
usernameCell.addSubview(usernameLabel)
usernameCell.addSubview(usernameDisplay)
membershipTierLabel.text = "Membership Status"
membershipTierDisplay.text = "Free (0-1GB)"
membershipTierDisplay.textColor = self.view.tintColor
membershipTierLabel.frame = CGRect(x: self.view.bounds.minX, y: self.membershipTierCell.bounds.minY, width: self.view.frame.width, height: self.membershipTierCell.bounds.height)
membershipTierDisplay.frame = CGRect(x: self.view.bounds.minX, y: self.membershipTierCell.bounds.minY, width: self.view.frame.width, height: self.membershipTierCell.bounds.height)
membershipTierDisplay.textAlignment = .right
membershipTierCell.addSubview(membershipTierLabel)
membershipTierCell.addSubview(membershipTierDisplay)
dataUsedLabel.text = "Data Used"
dataUsedDisplay.text = String(UserDefaults.standard.integer(forKey: "total_storage"))
dataUsedDisplay.textColor = self.view.tintColor
dataUsedLabel.frame = CGRect(x: self.view.bounds.minX, y: self.dataUsedCell.bounds.minY, width: self.view.frame.width, height: self.dataUsedCell.bounds.height)
dataUsedDisplay.frame = CGRect(x: self.view.bounds.minX, y: self.membershipTierCell.bounds.minY, width: self.view.frame.width, height: self.membershipTierCell.bounds.height)
dataUsedDisplay.textAlignment = .right
dataUsedCell.addSubview(dataUsedLabel)
dataUsedCell.addSubview(dataUsedDisplay)
tipsText.text = "You can change the color of a progression tag by long-pressing it on the Progressions homepage"
tipsText.frame = CGRect(x: tipsCell.bounds.minX,y: self.tipsCell.bounds.minY,width: tipsCell.bounds.width,height:self.tipsCell.bounds.height)
//tipsText.textColor = UIColor.white
//tipsText.textAlignment = .center
tipsText.backgroundColor = self.view.tintColor
tipsText.font = tipsText.font?.withSize(15)
tipsText.autoresizingMask = [.flexibleWidth, .flexibleHeight]
// tipsText.centerYAnchor.constraint(equalTo: tipsCell.centerYAnchor, constant:0).isActive = true
// tipsText.centerXAnchor.constraint(equalTo: tipsCell.centerXAnchor, constant:0).isActive = true
//tipsText.textContainerInset = UIEdgeInsets(top: 10, left: 5, bottom: 10, right: 5)
tipsCell.backgroundColor = self.view.tintColor
tipsCell.addSubview(tipsText)
tipsText.center = CGPoint(x: tipsCell.bounds.midX, y: tipsCell.bounds.midY)
feedbackText.text = "Feedback is loved! Please email with any issues, comments, ideas, or concerns"
feedbackText.frame = CGRect(x: self.feedbackCell.bounds.minX,y: self.feedbackCell.bounds.minY,width: self.feedbackCell.bounds.width,height:self.feedbackCell.bounds.height)
feedbackText.font = feedbackText.font?.withSize(15)
feedbackCell.addSubview(feedbackText)
//let bytes = UserDefaults.standard.integer(forKey: "total_storage")
//storageAmount.text = format(bytes:Double(bytes))
// Do any additional setup after loading the view.
//myTableView.register(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
myTableView.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height)
myTableView.dataSource = self
myTableView.delegate = self
self.view.addSubview(myTableView)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section != 0 {
return 100
} else {
return UITableViewAutomaticDimension
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch(section) {
case 0: return 3 // section 0 has 2 rows
case 1: return 1
case 2: return 1// section 1 has 1 row
default: fatalError("Unknown number of sections")
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch(indexPath.section) {
case 0:
switch(indexPath.row){
case 0:
print("username")
return self.usernameCell
case 1:
return self.membershipTierCell
case 2:
return self.dataUsedCell
default: fatalError("Unknown row")
}
case 1:
switch(indexPath.row){
case 0:
return self.tipsCell
default: fatalError("Unknown row")
}
case 2:
print("feedback")
switch(indexPath.row){
case 0:
print("feedback")
return self.feedbackCell
default: fatalError("Unknown row")
}
default: fatalError("Unknown section")
}
}
}
Right now it looks like
As you can see I am trying to set the tipsText (UITextView) in the exact center of the tipsCell using: tipsText.center = CGPoint(x: tipsCell.bounds.midX, y: tipsCell.bounds.midY)
As you can see, this isn't working as the tipsText is still on the top of the tipsCell. How can I center it like I want here?
I think you have two ways to fulfill your wish.
One way is to set the heights of tipsCell and feedBackCell to 100 in IB if you have.
The other way is to add the codes as the following:
tipsText.textAlignment = .center
tipsText.numberOfLines = 0
tipsText.autoresizingMask = [.flexibleWidth, .flexibleHeight]
feedbackText.textAlignment = .center
feedbackText.numberOfLines = 0
feedbackText.autoresizingMask = [.flexibleWidth, .flexibleHeight]
Hopefully it is helpful.
If it is TextView, you may get estimated frames like this:
tipsText.textContainer.maximumNumberOfLines = 0
tipsText.textContainer.heightTracksTextView = true
tipsText.attributedText = NSAttributedString.init(string: "You can change the color of a progression tag by long-pressing it on the Progressions", attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 15) ])
tipsText.textAlignment = .center
let size = tipsText.textContainer.size
tipsText.frame = CGRect(x: tipsCell.bounds.minX,y: self.tipsCell.bounds.minY,width: tipsCell.bounds.width, height :size.height )
tipsText.backgroundColor = self.view.tintColor
tipsText.autoresizingMask = [.flexibleWidth, .flexibleHeight]
tipsCell.backgroundColor = self.view.tintColor
tipsCell.addSubview(tipsText)
tipsText.center = CGPoint(x: tipsCell.bounds.midX, y: tipsCell.bounds.midY)
feedbackText.textContainer.maximumNumberOfLines = 0
feedbackText.textContainer.heightTracksTextView = true
feedbackText.attributedText = NSAttributedString.init(string: "Feedback is loved! Please email with any issues, comments, ideas, or concerns", attributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 15) ])
feedbackText.textAlignment = .justified
let feedbackSize = feedbackText.textContainer.size
feedbackText.frame = CGRect(x: feedbackCell.bounds.minX,y: self.feedbackCell.bounds.minY,width: feedbackCell.bounds.width, height :feedbackSize.height )
feedbackText.backgroundColor = self.view.tintColor
feedbackText.autoresizingMask = [.flexibleWidth, .flexibleHeight]
feedbackCell.backgroundColor = self.view.tintColor
feedbackCell.addSubview(feedbackText)
feedbackText.center = CGPoint(x: feedbackCell.bounds.midX, y: feedbackCell.bounds.midY)
I assume you know how to use custom view classes.
There a custom class for UITextView;
class VerticallyCenteredTextView: UITextView {
override var contentSize: CGSize {
didSet {
var topCorrection = (bounds.size.height - contentSize.height * zoomScale) / 2.0
topCorrection = max(0, topCorrection)
contentInset = UIEdgeInsets(top: topCorrection, left: 0, bottom: 0, right: 0)
}
}
}
I am trying to create a collectionView which slides up when the user swipes up. For now I am using a button instead of the scroll gesture to trigger the animation. When the animation Begins I want the collectionView to expand in height but the cells to stay where they are and then as the user scrolls slide up. How do I animate the collectionView without moving the cells? Is this possible to do? I would like for the collectionView to expand up and show the hidden cells that were covered up during the scroll not or show a blank space from the collectionView not just move all of the cells higher on the screen.
Function of Code in Question
var buttonPressed:Bool = true
#IBAction func changeView(_ sender: Any) {
if buttonPressed{
UIView.animate(withDuration: 0.05){
self.animateCollectionView.frame = CGRect(x: 0, y: 100, width: 600, height: 1000)
// self.animateCollectionView.transform = CGAffineTransform(translationX: 0, y: -20)
self.view.sendSubview(toBack: self.animateCollectionView)
self.buttonPressed = !self.buttonPressed
print("Ive been expanded")
}
}
else{
UIView.animate(withDuration: 0.05){
self.animateCollectionView.frame = CGRect(x: 0, y: 20, width: 600, height: 1000)
// self.animateCollectionView.transform = CGAffineTransform(translationX: 0, y: 20)
self.buttonPressed = !self.buttonPressed
}
}
}
Code as whole:
import UIKit
class ViewController: UIViewController,UICollectionViewDataSource,UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 200
}
var counter:Int = 0
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.animateCollectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! customCell
counter+=1
cell.cellLabel.text = "\(counter)"
cell.backgroundColor = UIColor.orange
return cell
}
#IBOutlet weak var animateCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
animateCollectionView.dataSource = self
animateCollectionView.delegate = self
animateCollectionView.backgroundColor = UIColor.blue
animateCollectionView.frame = CGRect(x: 0, y: 100, width: 600, height: 1000)
self.view.sendSubview(toBack: self.animateCollectionView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var buttonPressed:Bool = true
#IBAction func changeView(_ sender: Any) {
if buttonPressed{
UIView.animate(withDuration: 0.05){
self.animateCollectionView.frame = CGRect(x: 0, y: 100, width: 600, height: 1000)
// self.animateCollectionView.transform = CGAffineTransform(translationX: 0, y: -20)
self.view.sendSubview(toBack: self.animateCollectionView)
self.buttonPressed = !self.buttonPressed
print("Ive been expanded")
}
}
else{
UIView.animate(withDuration: 0.05){
self.animateCollectionView.frame = CGRect(x: 0, y: 20, width: 600, height: 1000)
// self.animateCollectionView.transform = CGAffineTransform(translationX: 0, y: 20)
self.buttonPressed = !self.buttonPressed
}
}
}
}
class customCell :UICollectionViewCell{
#IBOutlet weak var cellLabel: UILabel!
}
My issue is that the last cell in my TableView is below the screen view and to see it you must scroll up and hold your position. At a neutral position where you dont scroll up, you cant see the last cell. Everything seemed fine until i changed the size of the cells. Here is my code:
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
//MARK : Properties
var tableView = UITableView()
var items: [String] = ["Age", "Gender", "Smoking Hx", "Occup. -Ag", "Family Hx", "Chronic Lung Disease Radiology", "Chronic Lung Disease Hx", "Nodule Border", "Nodule Location", "Satellite Lesions", "Nodule Pattern Cavity", "Nodule Size"]
var navigationBar = NavigationBar()
var gender = GenderView()
override func viewDidLoad() {
super.viewDidLoad()
//Create TableView
tableView.frame = CGRectMake(0, self.view.bounds.height * 0.097, self.view.bounds.width, self.view.bounds.height);
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
self.view.addSubview(tableView)
//Create Navigation Bar with custom class
self.navigationBar = NavigationBar(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height * 0.097))
self.view.addSubview(navigationBar)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
//Cell wont turn grey when selected
cell.selectionStyle = UITableViewCellSelectionStyle.None
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return self.view.bounds.height * 0.095
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
}
}
The only thing i could think of causing this issue is that instead of me creating a navigation bar, i created a "navigationBar" using a custom UIView() class. I then start the table view at the bottom of the navigation bar. Any idea how to fix this?
Here is the NavigationBar.swift:
class NavigationBar: UIView {
var navigationBar = UIView()
var header = UILabel()
var lineBorder = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
self.frame = frame
setUpView()
}
func setUpView(){
//Create Navigation Bar
navigationBar.frame = CGRectMake(0, 0, self.bounds.width, self.bounds.height)
navigationBar.backgroundColor = UIColor.whiteColor()
self.addSubview(navigationBar)
//Create Line Border
lineBorder.frame = CGRectMake(0, self.bounds.height, self.bounds.width, self.bounds.height * 0.005)
lineBorder.backgroundColor = UIColor.grayColor()
self.addSubview(lineBorder)
header.frame = CGRectMake(0, 0, 200, 200)
header.font = UIFont(name: "Helvetica", size: 17)
header.text = "Nodule Risk Calculator"
//header.backgroundColor = UIColor.blackColor()
self.addSubview(header)
header.translatesAutoresizingMaskIntoConstraints = false
header.centerHorizontallyTo(navigationBar, padding: 0)
header.centerVerticallyTo(navigationBar, padding: 9)
}
func hide(){
self.removeFromSuperview()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
tableView.frame = CGRectMake(0, self.view.bounds.height * 0.097, self.view.bounds.width, self.view.bounds.height);
has problem. The origin.y is not 0, and you still feed the whole height. So the table view will have some area below the screen
Try this:
tableView.frame = CGRectMake(0, self.view.bounds.height * 0.097, self.view.bounds.width,
self.view.bounds.height - self.view.bounds.height * 0.097);
self.navigationBar = NavigationBar(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height * 0.097))
self.view.addSubview(navigationBar)
var yAxis : Float = self.navigationBar.frame.height
var tblHeight : Float = self.view.bounds.height - yAxis
tableView.frame = CGRectMake(0, yAxis, self.view.bounds.width, tblHeight)
self.view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")