Tint of the image does not want to change - swift

I am trying to set a new color of the image while the cell of the UICollectionView was selected or deselected. Whenever i do not set a tint color of the image it is working, but i do not wanna have default blue color of it. So What I am doing is :
In func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell function, I am inicialazing my images with code :
let borderWidth = itemBorder.frame.width
let borderHeight = itemBorder.frame.height
myImage = UIImageView(frame: CGRect(x: 0, y: 0, width: borderWidth - 1/4 * borderWidth, height: borderHeight - 1/5 * borderHeight))
myImage.image = UIImage(named: myCollection[indexPath.row])?.withRenderingMode(.alwaysTemplate)
myImage.tintColor = UIColor.groupTableViewBackground
myImage.center = CGPoint(x: tmpCell.bounds.width/2, y: tmpCell.bounds.height/2)
myImage.contentMode = .scaleAspectFit
tmpCell.contentView.addSubview(myImage)
and so on in the didselected and deselected function :
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let currentCell: UICollectionViewCell?
switch collectionView {
case myCollectionView:
print("clicked")
currentCell = myCollectionView.cellForItem(at: indexPath)!
currentCell?.tintColor = UIColor.white
case colorsCollectionView:
break
default:
break
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let currentCell: UICollectionViewCell?
switch collectionView {
case vehiclesCollectionView:
print("deselected")
currentCell = myCollectionView.cellForItem(at: indexPath)!
currentCell?.tintColor = UIColor.groupTableViewBackground
case colorsCollectionView:
break
default:
break
}
}
Could someone tell me whats wrong ?
Thanks in advance!
Solution
Solution
Whenever i wanted to update the tint of the color i was pointing on the cell not on the image so basiclly only need to add this into selected or deselected method :
currentCell = myCollectionView.cellForItem(at: indexPath)!
let image = currentCell?.contentView.subviews[1] as! UIImageView
image.tintColor = UIColor.white

I see that you are setting the currentCell?.tintColor but I suppose you will probably have to set the currentCell?.vehicleImageView.image.tintColor
Also I see your code as a bit confusing since you have vehicleImage (which should probably be named vehicleImageView) and myImage which is a UIImage which is being added as a subView to the contentView? I thought it was only possible to add subclasses of UIView as subviews.
I suggest you create an outlet called myImageView in your custom UICollectionViewCell to which you can set the image.tintColor and change cell.myImageView.tintColor in your didSelect and didDeselect
If you do not add them from the storyboard, you can still create a subclass of UICollectionViewCell that has a property called vehicleImageView. You can set the frame and image of this as required in your cellForRow. Now you will have a property which you can refer to in your didSelect and didDeselect as cell.vehicleImageView.image.tintColor.
If you do not want to create a subclass that has a property, you will basically have to loop through all your subviews and find the image view and set the image tintColor there. Setting the tintColor of the UICollectionViewCell WILL NOT solve the problem. You will have to set it to the imageView.image
Hope that helps!

Related

UICollectionViewLayout Not Resizing UIImageViews Within Cells [duplicate]

This question already has an answer here:
UICollectionViewCell not forcing Cell Size
(1 answer)
Closed 2 years ago.
My collectionview images are not getting resized. I'm using the following in the viewcontroller that contains the collectionview, and it sizes correctly when the cells are empty; however with an imageview inside it doesn't behave properly.
Thanks!
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let noOfCellsInRow = 2
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let totalSpace = flowLayout.sectionInset.left
+ flowLayout.sectionInset.right
+ (flowLayout.minimumInteritemSpacing * CGFloat(noOfCellsInRow - 1))
let size = Int((collectionView.bounds.width - totalSpace) / CGFloat(noOfCellsInRow))
return CGSize(width: size, height: size)
}
Add this to your ViewController
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.collectionViewLayout.invalidateLayout()
}
And in Storyboard check if the collection view - Estimate Size is set to None in Size Inspector

Swift animate underline bar when selecting cell in collection view?

I need to add animate underline bar in collection view when selected.
Here is my code below:
class TestViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource {
#IBOutlet var segmentCollectionView: UICollectionView!
var segmentTitle = ["Transport","Hotels","Food","Beverages","Boardings"]
var selectedIndex = 0
override func viewDidLoad() {
super.viewDidLoad()
self.collectionViewFitScreen()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return segmentTitle.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SegmentCollectionViewCell", for: indexPath) as! SegmentCollectionViewCell
let segmentValue = segmentTitle[indexPath.item]
cell.nameLbl.text = segmentValue
if selectedIndex == indexPath.item{
cell.underlineBarView.backgroundColor = #colorLiteral(red: 0.1921568627, green: 0.2, blue: 0.3333333333, alpha: 1)
}else{
cell.underlineBarView.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.selectedIndex = indexPath.item
self.segmentCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredVertically)
self.segmentCollectionView.scrollToItem(at: indexPath, at: [.centeredHorizontally], animated: true)
self.segmentCollectionView.reloadData()
}
by above method I've achieve this Segment-Selection.
But what I need is to animate like this Segment-Scroll-Animate.How to do like this?. Any help is appreciated.
As per your code, you are changing the color of the UnlineView bar that will show animation like hiding/showing view.
So to achieve your required animation on the underline bar you need to move ur Underline Bar from CollectionView Cell to outer view or move it on its super view.
And then change the position of the view based on cell selection.
Something like the below code:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.selectedIndex = indexPath.item
UIView.animate(withDuration: 1.0) {
//Change position of your UnderlineBar
self.underineBar.frame = #Set Appropriate Frame Here#
self.view.layoutIfNeeded()
}
}
this will animate ur view from the current position to the selected cell position.
Hope this will helps to get ur animation on the underline bar.
The more clean approach is to draw the indicator as part of UICollectionView UICollectionReusableView. There is a nice example of how to work with it in emilwojtaszek/collection-view-layout-examples.
Note: If you want indicator to change its' width relative to menu cell width, this task might be considerably more complicated. Simplest way is to use the Parchment library. It uses scroll events to compute relative portion of currently scrolled page, to get menu cells which are part of transition and only then change width attribute of UICollectionReusableView.

Last UICollectionViewCell appearing different to the others

I'm creating a UICollectionView on my main menu and all the cells look fine bar the last one, where the image is not centered relative to the cell- it appears to be anchored to the top left corner of the cell (not sure about that though).
here is the image that contains the problem.
I didn't really know where to start with this, as all the cells use the same code and constraints.
I checked that it wasn't an image issue by repeating a previously used image (see above screenshot)
My only idea is that the final cell is in a row on its own whereas the other rows have two cells per row.
extension MainMenuViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return mainMenuOptions.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainMenuCell", for: indexPath) as! MainMenuCollectionViewCell
let imageView = cell.mainMenuImage!
let label = cell.mainMenuLabel!
imageView.image = mainMenuImages[indexPath.item]
imageView.frame.size.height = cell.frame.size.width - 5
imageView.frame.size.width = cell.frame.size.width - 10
cell.mainMenuLabel.text = mainMenuOptions[indexPath.item]
let labelText = cell.mainMenuLabel!
label.frame.size.height = Utils.heightForView(text: labelText.text!, font: labelText.font!, width: cell.frame.width)
label.frame.size.width = cell.frame.size.width
label.center.x = cell.frame.size.width / 2
label.center.y = cell.mainMenuImage.frame.size.height + (cell.frame.size.height - cell.mainMenuImage.frame.size.height) / 2
cell.layer.borderColor = UIColor.darkGray.cgColor
cell.layer.borderWidth = CGFloat(0.5)
cell.layer.cornerRadius = CGFloat(10)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainMenuCell", for: indexPath) as! MainMenuCollectionViewCell
let padding: CGFloat = 40
let cellWidth = (collectionView.frame.size.width - padding) / 2
let labelText = mainMenuOptions[indexPath.item]
let cellHeight = cellWidth + Utils.heightForView(text: labelText, font: cell.mainMenuLabel.font!, width: cell.frame.width) + 70
return CGSize(width: cellWidth, height: cellHeight)
}
}
Utils.heightForView() is just a function that calculates the size required for a label to fit all the text. If you need to see it I'll happily add it.
Thanks very much in advance! I hope this is the right amount of code needed but if not let me know and I'll add more.
EDIT: Cell class
class MainMenuCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var mainMenuLabel: UILabel!
#IBOutlet weak var mainMenuImage: UIImageView!
}
When you dequeue a cell in cellForItem it doesn't necessarily have its final size at that point, yet you're depending on that being correct for your code to work.
You should be using autolayout constraints or a stack view inside the cell to give you the correct layout without needing to do any work at dequeue time.
You seem to be trying to give variable heights for your cells as well, which is going to look pretty messy in a flow layout, although it doesn't seem to be making any difference to the cells in the screenshot which I'd expect to have different heights given their titles. Dequeuing a cell in sizeForItem could have some unexpected side effects too, since that's going to mess with the reuse pool.

UITableViewCell style goes away after scrolling down

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)

Image does not fit properly in collectionCell

In Swift 3. My app has a table view and a detail view with is a view controller. Here I added a collection view. An array of images must be presented. The images adapt themselves beautifully if in portrait I check the content mode in scaler to fill. In ladscape it works in aspectFill. Vice-versa, the layout does not fit. I did the following
in cellForItem At:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = myCollection.dequeueReusableCell(withReuseIdentifier: "cellCollection", for: indexPath) as! CollectionViewCell
cell.cellImage.image = UIImage(named: array[indexPath.item])
if UIDevice.current.orientation.isLandscape{
cell.cellImage.contentMode = .scaleAspectFill
}
else if UIDevice.current.orientation.isPortrait{
cell.cellImage.contentMode = .scaleToFill
}
return cell
}
It does not work. May be I have some inconsistencies from portrait to landscape.
I would appreciate your help. If you want to take a look at the project in git:
[https://github.com/ricardovaldes/tareaFinalHoteles.git1. Thanks in advance.
Eureka. Finally I did solve this problem. With sizeForItem at, the app could function without problems. I was lost or mislead looking for a way to change the image content mode, but this is not the right way. The correct way is resize once you rotate: for this you need the func willTransition toNewCollection: UITraitCollection. Inside you create a variable layout that is of type UICollectionViewFlowLayout. With the help of a conditional, is possible to define how you want the with and heigt after rotation.This post is clear and concise for those curious: UICollectionView Cell Resizing on Device Rotation.
Here the implementation I did in my project: `
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
if UIDevice.current.orientation.isLandscape,
let layout = myCollection.collectionViewLayout as? UICollectionViewFlowLayout{
let with = myCollection.frame.size.width
layout.itemSize = CGSize(width: with, height: 280)
layout.invalidateLayout()
}
else if UIDevice.current.orientation.isLandscape,
let layout = myCollection.collectionViewLayout as? UICollectionViewFlowLayout{
let with = myCollection.frame.size.width
layout.itemSize = CGSize(width: with/2, height: 280)