I am trying to display a card but when the detailTextLabel gets too long, it causes the card to extend beyond the view. I'm not sure if this is a bug or not. I have adjusted the .numberOfLines to various numbers but that seems to have no effect.
// Detail label.
let detailLabel: UILabel = UILabel()
detailLabel.text = "When this text gets too long it does not wrap, it will extend off the page"
detailLabel.font = UIFont(name: "Roboto-Thin", size: 18)
detailLabel.numberOfLines = 0
cardView.detailLabel = detailLabel
EDIT
Here's the full code for the cardView.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cardView: CardView = CardView()
// Title label.
let titleLabel: UILabel = UILabel()
titleLabel.text = self.type[indexPath.row].capitalizedString
titleLabel.textColor = MaterialColor.blue.darken1
titleLabel.font = UIFont(name: "Roboto-Medium", size: 23)
cardView.titleLabel = titleLabel
// Detail label.
let detailLabel: UILabel = UILabel()
detailLabel.text = "When this text gets too long it does not wrap, it will extend off the page"
detailLabel.font = UIFont(name: "Roboto-Thin", size: 18)
detailLabel.numberOfLines = 100
cardView.detailLabel = detailLabel
// Yes button.
let btn1: FlatButton = FlatButton()
btn1.pulseColor = MaterialColor.blue.lighten1
btn1.pulseScale = false
btn1.setTitle("Ok", forState: .Normal)
btn1.setTitleColor(MaterialColor.blue.darken1, forState: .Normal)
// Add buttons to left side.
cardView.leftButtons = [btn1]
// To support orientation changes, use MaterialLayout.
view.addSubview(cardView)
cardView.translatesAutoresizingMaskIntoConstraints = false
MaterialLayout.alignFromTop(view, child: cardView, top: self.view.frame.height / 4)
MaterialLayout.alignToParentHorizontally(view, child: cardView, left: 10, right: 10)
}
}
So the issue is that you are using a UITableViewController. When you add the CardView to your view property, it is actually adding it to the UITableView, which will cause it to scroll when you scroll the tableView. The other issue of it not expanding correctly is due to the "|" value in AutoLayout, that seems to be breaking when placed in a TableView. This is probably a result of how the TableView is setup mathematically.
Either way, to avoid the scrolling issue, you will need to use a UIViewController and add a UITableView as a child view to it, or if you are keen on using the UITableViewController, it should be added as a child ViewController to a parent ViewController that you would add your CardView too. This will ultimately solve your bounds issue as well.
In the Material repo -> Examples/Programmatic/SideViewController example project, you can find a tableView added as a child view, and there, you would be able to place your CardView code as you have already done so in your current project.
I tried your code snippet in an example project and all seems to work. I used this code
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cardView: CardView = CardView()
// Title label.
let titleLabel: UILabel = UILabel()
titleLabel.text = "Activities dhajshd ajshd ashd kjashd jkasd jk asjkd asjk d"
titleLabel.textColor = MaterialColor.blue.darken1
titleLabel.font = UIFont(name: "Roboto-Medium", size: 23)
cardView.titleLabel = titleLabel
// Detail label.
let detailLabel: UILabel = UILabel()
detailLabel.text = "When this text gets too long it does not wrap, it will extend off the page"
detailLabel.font = UIFont(name: "Roboto-Thin", size: 18)
detailLabel.numberOfLines = 100
cardView.detailLabel = detailLabel
// Yes button.
let btn1: FlatButton = FlatButton()
btn1.pulseColor = MaterialColor.blue.lighten1
btn1.pulseScale = false
btn1.setTitle("Ok", forState: .Normal)
btn1.setTitleColor(MaterialColor.blue.darken1, forState: .Normal)
// Add buttons to left side.
cardView.leftButtons = [btn1]
// To support orientation changes, use MaterialLayout.
view.addSubview(cardView)
cardView.translatesAutoresizingMaskIntoConstraints = false
MaterialLayout.alignFromTop(view, child: cardView, top: self.view.frame.height / 4)
MaterialLayout.alignToParentHorizontally(view, child: cardView, left: 10, right: 10)
}
Both the title and detail labels are too long for a single line and the CardView responds appropriately.
So I have a suspicion that your "view" may be to wide. Can you confirm your "width" of the ViewController is at most the width of the device?
Related
I have a viewcontroller with a tableview inside it. At the bottom of the tableview there is some white space that I want to get rid of and be replaced by my background colour.
I have added and customised the tableview programatically so I am looking for a programatic answer, as I did not use storyboard much for this. (I had only used it to setup my TabBarController and link it to navigation and view-controllers.)
Below is the some of the code I used to configure the tableview.
private let tableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .plain)
tableView.register(ProfileTableViewCell.self, forCellReuseIdentifier: ProfileTableViewCell.identifier)
tableView.backgroundColor = Constants.backgroundColor
return tableView
}()
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.frame = view.bounds
}
Im sure the answer is probably just a single line of code, but I couldn't find one that worked. Thanks in advance!
***EDIT
I have found a solution, but I still think there is a better way to solve this problem. The code below sets a UIView as the background of the tableview, then changes the colour of the UIView.
private let tableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .plain)
tableView.register(ProfileTableViewCell.self, forCellReuseIdentifier: ProfileTableViewCell.identifier)
let backgroundView = UIView(frame: CGRect(x: 0,
y: 0,
width: tableView.bounds.size.width,
height: tableView.bounds.size.height))
backgroundView.backgroundColor = Constants.backgroundColor
tableView.backgroundView = backgroundView
return tableView
}()
The default color of the containing view controller is showing, since the table is short. Try setting the view controller's view's background color in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad();
view.backgroundColor = Constants.backgroundColor
}
iOS 14 introduced a bunch of advancements for UICollectionView including the new UICollectionViewListCell. Using the defaultContentConfiguration, you can add accessory views to the cell. I'm looking to recreate an iMessage conversation row (mail is also close) where the date label is in the top trailing corner. Is there anyway to do this using the default configuration? Having to create a custom cell seems like overkill just for this.
Here is what I currently have.
let cellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, Int> { cell, indexPath, item in
var content = cell.defaultContentConfiguration()
content.text = "Title"
content.secondaryText = "This is the body of the message and it's really long. I want to see where it finally truncates because thats what it should do eventually you know?"
content.secondaryTextProperties.numberOfLines = 2
content.image = UIImage(systemName: "star")
let label = UILabel()
label.text = "4/26/7"
label.textColor = .secondaryLabel
label.font = .preferredFont(forTextStyle: .caption1)
let customAccessory = UICellAccessory.CustomViewConfiguration(
customView: label,
placement: .trailing(displayed: .always))
cell.accessories = [.customView(configuration: customAccessory)]
cell.contentConfiguration = content
cell.tintColor = .tertiaryLabel
}
Here is my desired result
Here is mail for another example
The default UICollectionViewListCell has limited customization possibilities.
Your best shot is with a custom UICollectionViewCell subclass. You will instead have the cell registration register your custom class, and dequeue cells the same way you would dequeue a built-in UICollectionViewListCell class object.
I have a CollectionView and a Button inside of an UIView. The purpose of the button is change the theme of the app, and I can change all colors, except for the backgroundColor of a nameContainerView on my TatodexCell (a custom cell).
I can't figure out how to access that property, and then, change the color I want.
THE FOLLOWING CODE IS LOCATED ON MY TatodexController FILE
My button property is:
let buttonChangeTheme: UIButton? = {
let button = UIButton()
button.setTitle("Change to blue theme", for: .normal)
button.addTarget(self, action: #selector(themeButtonClicked), for: .touchUpInside)
button.titleLabel?.adjustsFontSizeToFitWidth = true
button.layer.borderWidth = 3
button.layer.borderColor = Colors.mainBlack?.cgColor
button.backgroundColor = Colors.darkBlue
button.tintColor = Colors.mainWhite
return button
}()
My button-func is this one:
#objc func themeButtonClicked() {
clickCheck = !clickCheck
if clickCheck {
navigationController?.navigationBar.barTintColor = Colors.lightBlue
collectionViewPokemon?.backgroundColor = Colors.darkBlue
buttonChangeTheme?.backgroundColor = Colors.darkRed
buttonChangeTheme?.setTitle("Return to red theme", for: .normal)
}
else {
navigationController?.navigationBar.barTintColor = Colors.lightRed
collectionViewPokemon?.backgroundColor = Colors.darkRed
buttonChangeTheme?.backgroundColor = Colors.darkBlue
buttonChangeTheme?.setTitle("Change to blue theme", for: .normal)
}
}
THE FOLLOWING CODE IS LOCATED ON MY TatodexCell FILE
The nameContainerView I wanna modify it's bg color is:
lazy var nameContainerView: UIView = {
let nameView = UIView()
nameView.backgroundColor = Colors.lightRed
nameView.addSubview(nameLabel)
nameLabel.center(inView: nameView)
return nameView
}()
My goal is to change nameView.backgroundColor = Colors.lightRed to nameView.backgroundColor = Colors.lightBlue, but I can't access that property.
I would really appreciate any help or advice. Perhaps the solution is hiding in plain sight, but I've tried many ways and none of them worked. Let me know if another chunk of code is needed to be shown.
If you implement the tintColorDidChange() method in your custom collection view cell, and in that method, you set the cell's background color to the tint color, then when you change the owning UICollectionView's tint color, the cells's tintColorDidChange() methods will fire and you'll see the change.
I am trying to figure out why my custom styling for table cells disappears after scrolling down in a table view and them back up. What do I need to do to have the style persist?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : CustomTrendingCell = trendingTableView.dequeueReusableCell(withIdentifier: "cell") as! CustomTrendingCell
cell.selectionStyle = .none
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(searchForTrendingTerm(sender:)))
cell.iconView_search.isUserInteractionEnabled = true
cell.iconView_search.tag = indexPath.row
cell.iconView_search.addGestureRecognizer(tapGesture)
cell.trendingLabel.text = trendingSearchTerms[indexPath.row]
cell.elevate(elevation: 4.0) //where my style is being set
return cell
}
extension UIView {
func elevate(elevation: Double) {
self.layer.masksToBounds = false
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOffset = CGSize(width: 0, height: elevation)
self.layer.shadowRadius = abs(CGFloat(elevation))
self.layer.shadowOpacity = 0.4
}
}
The top 2 items in the screenshot below have been scrolled down and up. The drop shadow styling has been removed. The bottom 2 have the correct styling and have not been scrolled down.
Screenshot example
One possible solution here is to explicitly specify the zPosition of each cell's layer.
You would want to ensure that the upper cell has the higher position so that it's content (shadow) lies over the lower cell.
In your cell for row at function add:
cell.layer.zPosition = CGFloat(numberOfRows - indexPath.row)
I have added 2 labels to my cell and setup these constraints with snapkit, issue is I cant get the cell to expand correctly, it stays at its default height:
titleLabel.snp.makeConstraints { (make) -> Void in
make.top.equalTo(contentView.snp.top)
make.bottom.equalTo(descriptionLabel.snp.top)
make.left.equalTo(contentView.snp.left)
make.right.equalTo(contentView.snp.right)
}
descriptionLabel.snp.makeConstraints { (make) -> Void in
make.top.equalTo(titleLabel.snp.bottom)
make.bottom.equalTo(contentView.snp.bottom)
make.left.equalTo(contentView.snp.left)
make.right.equalTo(contentView.snp.right)
}
I mapped the four edges as you can see, however I know height isnt implied by these, how can I apply a height when the content is by nature, dynamic, and could be various heights...
setup for the labels looks like this:
lazy var titleLabel: UILabel = {
let titleLabel = UILabel()
titleLabel.textColor = .green
titleLabel.textAlignment = .center
contentView.addSubview(titleLabel)
return titleLabel
}()
lazy var descriptionLabel: UILabel = {
let descriptionLabel = UILabel()
descriptionLabel.textColor = .dark
descriptionLabel.textAlignment = .center
descriptionLabel.numberOfLines = 0
contentView.addSubview(descriptionLabel)
return descriptionLabel
}()
Give the table view an estimatedRowHeight, and set its rowHeight to UITableViewAutomaticDimension. Now the cells will be self-sizing. Well, if a label is pinned by all four sides to the content view, and if the cell is self-sizing, then that's all you have to do: the label will automatically change its height to accommodate its text, and the cell will automatically change size to accommodate the label.
First of all I think that you should add subviews to contentView in subclassed UITableViewCell class initializer method.
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.contentView.addSubview(titleLabel)
self.contentView.addSubview(descriptionLabel)
}
Secondly, make sure that in your viewDidLoad method (probably in your ViewController) these two lines are added:
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableView.automaticDimension
Of course, you should change estimatedRowHeight to accommodate your needs.
One more thing worth mentioning - you can create these constraints easier (using power of SnapKit):
titleLabel.snp.makeConstraints { (make) -> Void in
make.top.left.right.equalTo(contentView)
}
descriptionLabel.snp.makeConstraints { (make) -> Void in
make.top.equalTo(titleLabel.snp.bottom)
make.bottom.left.right.equalTo(contentView)
}