Does anyone know what's happening here? I've configured a UITableView with CollectionViewCells, and each of these cells is supposed to operate independently of each other, yet when I swipe one it controls another cell which is 3 cells underneath it.
Tried to reconfigure my UITableViewCells and the CollectionViewCells. But I'm not exactly sure what to do
//TableView controler
import UIKit
import CardsLayout
import CHIPageControl
class eventsFeed: UIViewController, UITableViewDelegate, UITableViewDataSource{
// Global Variable
var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
tableView = UITableView(frame: CGRect(x: self.view.bounds.minX, y: self.view.bounds.minY+UIApplication.shared.statusBarFrame.height, width: self.view.bounds.width, height: self.view.bounds.height))
tableView.delegate = self
tableView.separatorStyle = .none
tableView.dataSource = self
tableView.showsVerticalScrollIndicator = false
self.view.addSubview(tableView)
tableView.register(TableViewCell.self, forCellReuseIdentifier: "TableViewCell")
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TableViewCell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
cell.backgroundColor = UIColor.white
cell.selectionStyle = .none
return cell
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 430.0;//Choose your custom row height
}
}
//CollectionViewCell for TableView
import UIKit
import CardsLayout
class TableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate {
var collectionView: UICollectionView!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.scrollDirection = UICollectionViewScrollDirection.horizontal
collectionView = UICollectionView(frame: CGRect(x: 0, y:0, width: UIScreen.main.bounds.width, height: 410.0), collectionViewLayout: layout)
collectionView.center = CGPoint(x: 187.5, y: 180)
collectionView.collectionViewLayout = CardsCollectionViewLayout()
collectionView.delegate = self
collectionView.dataSource = self
collectionView.isPagingEnabled = true
collectionView.showsHorizontalScrollIndicator = false
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
collectionView.backgroundColor = UIColor.white
self.addSubview(collectionView)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
var colors: [UIColor] = [
UIColor(red: 237, green: 37, blue: 78),
UIColor(red: 249, green: 220, blue: 92),
UIColor.blue,
UIColor(red: 1, green: 25, blue: 54),
UIColor(red: 255, green: 184, blue: 209),
UIColor(red: 237, green: 37, blue: 78),
UIColor(red: 249, green: 220, blue: 92)
]
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath)
cell.layer.cornerRadius = 12.0
cell.backgroundColor = colors[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return colors.count
}
}
Video of issue: https://www.reddit.com/r/iOSProgramming/comments/btcok4/does_anyone_know_whats_happening_here_ive/
Cells are reused. That means that you have to choose different strategy of working with them.
Save somewhere current state for each table view cell (for example in structs in an array) and then configure cell based on this state in cellForRowAt delegate's method.
Related
I have a collection view, I'd like to render the following layout
I tried to restrict the number of cells but I am unsure how to force the different count per row as you can see in the design
class ViewController: UIViewController {
private(set) lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: view.frame, collectionViewLayout: UICollectionViewFlowLayout())
collectionView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
collectionView.backgroundColor = .systemBackground
collectionView.dataSource = self
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "CustomCell")
return collectionView
}()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = #colorLiteral(red: 0.1215686275, green: 0.1294117647, blue: 0.1490196078, alpha: 1)
collectionView.contentInset = .init(top: 24, left: 24, bottom: 24, right: 24)
view.addSubview(collectionView)
}
}
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (5 * 5) + 6
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath)
cell.backgroundColor = #colorLiteral(red: 0.1647058824, green: 0.1764705882, blue: 0.2117647059, alpha: 1)
cell.layer.cornerRadius = cell.frame.width / 2
return cell
}
}
My attempt only renders
The colors aren't important only the layout.
If you can define the height / width for your collection view you can calculate the position
class ViewController: UIViewController {
private(set) lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
collectionView.translatesAutoresizingMaskIntoConstraints = false
collectionView.backgroundColor = .systemBackground
collectionView.dataSource = self
collectionView.delegate = self
collectionView.isScrollEnabled = false
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "CustomCell")
return collectionView
}()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = #colorLiteral(red: 0.1215686275, green: 0.1294117647, blue: 0.1490196078, alpha: 1)
collectionView.contentInset = .init(top: 24, left: 24, bottom: 24, right: 24)
view.addSubview(collectionView)
NSLayoutConstraint.activate([
collectionView.heightAnchor.constraint(equalToConstant: 340),
collectionView.widthAnchor.constraint(equalToConstant: 300),
collectionView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
collectionView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
}
}
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 48
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath)
switch indexPath.item {
case 0, 5, 42, 47: cell.backgroundColor = #colorLiteral(red: 0.1215686275, green: 0.1294117647, blue: 0.1490196078, alpha: 1)
default: cell.backgroundColor = #colorLiteral(red: 0.1647058824, green: 0.1764705882, blue: 0.2117647059, alpha: 1)
}
cell.layer.cornerRadius = cell.frame.width / 2
return cell
}
}
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return .init(width: 28, height: 28)
}
}
I have a UITableView with custom cells, one cell per section for spacing. I’d like to add an image as the cell background, but I’m not sure how to do so. If I set the cell background image it is obscured by the containerView, and doesn’t have the curved corners. Any suggestions? I’m working with Playgrounds on iPad, so I’d like to do this programmatically. Here’s what I have so far:
import UIKit
import PlaygroundSupport
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(CardCell.self, forCellReuseIdentifier: "CardCell")
tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
tableView.contentInset = UIEdgeInsets(top: 0, left: 30, bottom: 0, right: -30)
tableView.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
}
}
extension ViewController {
override func numberOfSections(in tableView: UITableView) -> Int {
return(5)
}
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.contentView.layer.masksToBounds = true
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section : Int) -> Int{
tableView.rowHeight = 200
// There is one row in each section
return 1
}
// Setup spacing between sections
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
// Make headers transparent (fill with UIView, set as transparent)
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = UIColor.clear
return headerView
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "CardCell", for: indexPath) as! CardCell
return cell
}
}
class CardCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
layer.masksToBounds = false
layer.shadowOpacity = 0.23
layer.shadowRadius = 12
layer.shadowOffset = CGSize(width: 0, height: 0)
layer.shadowColor = UIColor.black.cgColor
layer.cornerRadius = 6
contentView.backgroundColor = .white
contentView.layer.cornerRadius = 8
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
PlaygroundPage.current.liveView = ViewController()
You can set background image of any cell like this:
cell.selectedBackgroundView = UIImageView(image: UIImage(named: "cellBgImage.png")?.stretchableImage(withLeftCapWidth: Int(0.0), topCapHeight: Int(5.0)))
I’ve implemented a custom cell for a UITableView, but when I run the Playground it’s just a standard table. It’s probably something stupid simple, but I’m very new to UIKit and somewhat new to Swift.
Also, I’ve tried to implement a “sticky header”, but no matter what I try the header scrolls with the rest of the table.
import UIKit
import PlaygroundSupport
class ViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 19
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: CardCell = tableView.dequeueReusableCell(withIdentifier: "CardCell", for: indexPath) as! CardCell
cell.messageLabel.text = "yo"
return cell
}
var convoTableView = UITableView()
override func viewDidLoad(){
super.viewDidLoad()
convoTableView = UITableView(frame: self.view.bounds, style:
UITableView.Style.plain)
convoTableView.backgroundColor = UIColor.white
convoTableView.register(CardCell.self, forCellReuseIdentifier: "CardCell")
let header = UIView(frame: CGRect(x: 0, y: 0, width: convoTableView.frame.width, height: 100))
header.backgroundColor = .red
self.convoTableView.delegate = self
self.convoTableView.dataSource = self
let yourLabel = UILabel(frame: CGRect(x: 10, y: 0, width: 100, height: 100))
yourLabel.textColor = UIColor.black
yourLabel.backgroundColor = UIColor.white
yourLabel.text = "mylabel text"
header.addSubview(yourLabel)
convoTableView.tableHeaderView = header
convoTableView.estimatedSectionHeaderHeight = 40.0
self.view.addSubview(convoTableView)
}
}
class CardCell: UITableViewCell {
let messageLabel:UILabel = {
let label = UILabel()
label.font = UIFont.boldSystemFont(ofSize: 14)
label.clipsToBounds = true
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let dateLabel:UILabel = {
let label = UILabel()
label.font = UIFont.boldSystemFont(ofSize: 8)
label.clipsToBounds = true
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let containerView:UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.clipsToBounds = true
return view
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
containerView.addSubview(messageLabel)
containerView.addSubview(dateLabel)
self.contentView.addSubview(containerView)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
PlaygroundPage.current.liveView = ViewController()
Here's all the code you need here to make a custom cell and sticky header:
import UIKit
import PlaygroundSupport
class ViewController: UITableViewController {
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView()
view.backgroundColor = .purple
return view
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
50
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
19
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CardCell", for: indexPath) as! CardCell
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
override func viewDidLoad(){
super.viewDidLoad()
tableView.register(CardCell.self, forCellReuseIdentifier: "CardCell")
}
}
class CardCell: UITableViewCell { }
PlaygroundPage.current.liveView = ViewController()
To make the header sticky and non-scrollable with the table view you need to take a different UIView above the table view and give the frames of the table just below the UiView.
customView = MyCustomView(frame: CGRect(x: 0, y: 0, width: 200, height: 50))
self.view.addSubview(customView
I am trying to make this, as in the first picture:
Image 1
Image 2
But the view somehow does not show up like I want it to. Here you can see my full project code:
import UIKit
import RealmSwift
import CVCalendar
class Test: UIViewController, UITableViewDelegate, UITableViewDataSource {
var myTableView: UITableView = UITableView()
var itemsToLoad: [String] = ["One", "Two", "Three"]
var myView = UIView()
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(red: 4/255, green: 4/255, blue: 4/255, alpha: 1.0)
self.navigationController?.navigationBar.barStyle = .black
self.navigationController?.navigationBar.tintColor = UIColor.white
self.navigationItem.title = "Test"
self.navigationController?.navigationBar.prefersLargeTitles = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Get main screen bounds
let screenSize: CGRect = UIScreen.main.bounds
let screenWidth = screenSize.width
let screenHeight = screenSize.height
myView.frame = CGRect(x: 0, y: 0, width: screenWidth, height: 150)
myView.backgroundColor = .black
self.view.addSubview(myView)
myTableView.frame = CGRect(x: 0, y: 50, width: screenWidth, height: screenHeight-50);
myTableView.dataSource = self
myTableView.delegate = self
myTableView.backgroundColor = .blue
myTableView.layer.borderWidth = 3
myTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
self.view.addSubview(myTableView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return itemsToLoad.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = self.itemsToLoad[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("User selected table row \(indexPath.row) and item \(itemsToLoad[indexPath.row])")
}
}
Why won't it show up? The first picture is how I want it, then second picture is how it looks now.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if self.itemsToLoad[indexPath.row] != nil {
cell.textLabel?.text = self.itemsToLoad[indexPath.row]
cell.backgroundColor = .white
}else {
cell.backgroundColor = .blue
}
return cell
}
When the user tries scrolling down the table (goes past the keyboard height), it automatically scrolls back to the top of table, leaving the user unable to press any of the keys in the bottoms rows of the table. How do I disable this autoscroll to top? Note this is different from the scrollsToTop property.
import UIKit
class KeyboardViewController: UIInputViewController, UITableViewDelegate, UITableViewDataSource {
var tableView: UITableView = UITableView()
let screenSize: CGRect = UIScreen.mainScreen().bounds
let buttonTitles = [
"XX",
"YY"
]
override func viewDidLoad() {
super.viewDidLoad()
let screenWidth = screenSize.width
let screenHeight = screenSize.height
tableView.frame = CGRectMake(0,0,screenWidth,screenHeight - 40)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.self,forCellReuseIdentifier: "cell")
self.view.addSubview(tableView)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.buttonTitles.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
cell.textLabel?.text = self.buttonTitles[indexPath.row]
cell.textLabel?.textAlignment = .Center
cell.textLabel?.font = UIFont(name: "Helvetica Neue", size: 14)
cell.textLabel?.textColor = UIColor.whiteColor()
cell.textLabel?.numberOfLines = 0
cell.backgroundColor = UIColor(red: 176/255, green: 15/255, blue: 15/255, alpha: 1.0)
cell.preservesSuperviewLayoutMargins = false
cell.layoutMargins = UIEdgeInsetsZero
cell.separatorInset = UIEdgeInsetsZero
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var string = buttonTitles[indexPath.row]
(textDocumentProxy as! UIKeyInput).insertText("\(string)")
}
Move your code except
tableView.delegate = self
tableView.dataSource = self
to viewWillAppear