UICollectionViewListCell Accessory TopTrailing Placement - swift

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.

Related

How can I add two images (one at the left and one on the right side) in a button in Xcode programaticly? I need also a title of a button

func setupButtonUI() {
if let detailsImage = UIImage(named: "detalji_icon") {
setImage(detailsImage, for: .normal)
contentHorizontalAlignment = .left
contentVerticalAlignment = .center
}
if let arrowImage = UIImage(named: "posalji_zahtev_black_icon") {
setImage(arrowImage, for: .normal)
contentHorizontalAlignment = .right
contentVerticalAlignment = .center
}
}/this is one of the things I tried, but whit this I get only the second image and its set in the center not right and the left image is hot even there/
UIButton has only one imageView, you can create custom button like in this answer
https://stackoverflow.com/a/43112735/13628690
Found the next solution: Made a custom UIView and added two images and label as a subview of customView. Did the constraints programaticly. Just added UITapGestureRecognizer (addGestureRecognizer) at the entire view and its all elements are clickable. The design and functionality are satisfied.

Swift - Custom cell width and height for textlabel and detailTextLabel

I wanna manage the long text in textlabel and detailtextlabel for the cells in UITableview because if the textlabel has a long text the detailedtextlabel truncate with "..." and viceversa.
Here's the problem:
So I wanna know if there's a way to manage the space between textlabel and detailtextlabel so there's no truncate and give them more lines. I tried with:
...
if tableData[indexPath.row].clave.count > 6 {
cell?.detailTextLabel?.numberOfLines = 5
cell?.textLabel?.numberOfLines = 5
} else {
cell?.detailTextLabel?.numberOfLines = 1
}
cell?.textLabel?.text = nueva_cadena_string
cell?.detailTextLabel?.text = tableData[indexPath.row].clave
cell?.textLabel?.textColor = UIColor.brown
cell?.textLabel?.font = UIFont.boldSystemFont(ofSize: 15.0)
cell?.textLabel?.lineBreakMode = .byWordWrapping
return cell!;
But it doesn't work very well, it seems to give them just 2 lines, not 5 and I can't change the width for the textlabel and detailtextlabel.
Try making your cell custom as this:
Try setting the tableviews row dimension to automatic
yourTableView.rowHeight = UITableViewAutomaticDimension
yourTableView.estimatedRowHeight = 80.0
try setting both textlabels number of lines either in the storyboard or in code to 0 as then they will all have the amount of lines they need.
You can subclass UITableViewCell and override the layoutSubviews() method. You will need to change the layout of textLabel and detailTextLabel there. Remember that these elements lie inside contentView, not in the cell itself.
But better you add two custom labels on the Storyboard and configure them as you want. It's easier.

How do I actually create a custom UISearchBar?

I have been banging my head against a wall for a day now trying to figure out how to create a custom UISearchBar so I can get rid of the stock black search bar UIKit thinks I want. I've tried a few 'solutions':
1. Customizing the appearance in the AppDelegate
//default background color for search bars
UISearchBar.appearance(whenContainedInInstancesOf: [UISearchController.self]).tintColor = UIColor(hexString: "#394C53")
This didn't work
2. Subclassing UISearchController and UISearchBar
I followed this tutorial which didn't work
3. Looping through subviews
let results = DestinationSearchResultsTableViewController()
results.mapView = map
results.handleMapSearchDelegate = self
destinationSearch = UISearchController(searchResultsController: results)
destinationSearch!.searchBar.placeholder = "Where do you want to go?"
if #available(iOS 11, *) {
navigationItem.searchController = destinationSearch
if let textfield = destinationSearch!.searchBar.value(forKey: "searchField") as? UITextField {
if let backgroundview = textfield.subviews.first {
// Below is not what I want but it works
backgroundview.backgroundColor = UIColor.white
backgroundview.layer.cornerRadius = 10
backgroundview.clipsToBounds = true;
}
}
} else {
self.navigationController?.pushViewController(destinationSearch!, animated: true)
}
destinationSearch!.delegate = self
destinationSearch!.searchResultsUpdater = results as UISearchResultsUpdating
This actually kinda works. It works really well if I use the UIColor predefined colors like UIColor.white UIColor.red etc. but it works really terribly if I want to use a specific color like this: I tried using RGB and hex representations of the color above, but all I get is black.
Here is what I want:
I want to create my own UISearchBar with a left-aligned label and content textfield to the right as I have shown above.
Thanks

TableView Cells / Visual Format Language / Keeps adding same constraints?

Creating UITableViewCells including elements programmatically seems to be working except for the constraints. Or maybe it is. Everytime the cell reappears the same constraints will be added to the element. I'll have 20 of the same constraints added to a uiLabel after scrolling tableView. Here is my sublcass (condensed):
class TimeSlotCell: UITableViewCell {
let lblTime = UILabel()
var viewCons = [String:AnyObject]()
var previousCageView:UIView!
var myConstraints = [NSLayoutConstraint]()
func configureCell(row:Int,cageCount:Int) {
lblTime.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(lblTime)
placeConstraint("H:|-5-[time\(row)]", view:"time\(row)")
placeConstraint("V:|-17-[time\(row)]", view: "time\(row)
}
func placeConstraint(format:String, view:String) {
viewCons[view] = lblTime
let navViewConstraint = NSLayoutConstraint.constraintsWithVisualFormat(format, options: [], metrics: nil, views: viewCons)
myConstraints += navViewConstraint
NSLayoutConstraint.activateConstraints(myConstraints)
}
And in my VC i'm calling the configureCell func within my cellForRowAtIndexPath.
Is there a way to check if an existing constraint exists? Is there a way to make sure only one of my constraints can be added? Or is there a person out there with a much better solution? Thanks in advance.
There is a dataSource for your tableView, when you configure your cell, you send the cell model to your cell. Whenever the dataSource changes, the cell model sent to the cell will change as well. So what you need to do is move most of 'addSubview' to the cell`s initialization. If you have to do cell.contentView.addSubview with the cell model. You have to judge if the cell model you send to the cell is the same as the former one. If it is equal, do nothing, else reset the view config.

Can card be restricted to width of view?

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?