How to add a background image to a UICollectionViewCell in Swift? - ios

I had assumed that it would be easy to add a background image to a UICollectionViewCell, but I am having trouble figuring it out. I have a border image like this that I want to add to every cell in my UICollectionView.
border.png
I couldn't see an option to add it in the Interface Builder and I'm not sure which method to use on UICollectionViewCell programmatically.
I have seen these similar questions:
UICollectionView Cell with Image, change Background with click (image is already added)
How to add a background image to UICollectionView that will scroll and zoom will cells (UICollectionView, not UICollectionViewCell)

I know this is a old question, with an accepted answer. But why not just set the border of the cell like so:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath)
cell.layer.borderWidth = 1.5
cell.layer.borderColor = UIColor.blueColor().CGColor
cell.layer.cornerRadius = 4
return cell
}
That way you don't need to use a image. Just adjust the borderWidth and cornerRadius until you get the desired effect.

let View=UIView()
View.backgroundColor=UIColor(patternImage:UIImage(named:"border.png")!)
cell.backgroundView=View
in uicollectionview cellForItemAtIndexPath method

Add a UIImageView to your CollectionViewCell and set this image as the image.

Related

UICollectionView Cell subview resizes after collectionView: cellForItemAtIndexPath is complete

I am using a collection view to display a collection of profile images and the person's name. So my cell has a UIImageView and a UILabel as subviews. I am using the UICollectionViewDelegateFlowLayout method:
collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
to calculate the cell's size depending on the available space.
All of this is working fine. I have added constraints to my subviews in the cell so that they also resize accordingly.
The issue I am running into is that I want my UIImageViews to be circles. It seems like auto layout is not recalculating the cell's subview size until after I have applied that effect. Instead, when I calculate the cornerRadius for the imageView it is still saying the imageViews width is 114.0 (which is what is in the storyboard) regardless of how big the cell is. This results in circles on the iPhone 5s but only rounded corners on any bigger device. Here is my code for that:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("PersonCell", forIndexPath: indexPath)
configureCell(cell, atIndexPath: indexPath)
return cell
}
func configureCell(cell: UICollectionViewCell, atIndexPath indexPath: NSIndexPath) {
if let person = personAtIndexPath(indexPath) {
let imageView = cell.viewWithTag(100) as! UIImageView
let nameLabel = cell.viewWithTag(200) as! UILabel
cell.contentView.frame = cell.bounds
cell.contentView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
circularizeImageView(imageView)
imageView.image = person.profileImage
nameLabel.text = person.name
}
}
func circularizeImageView(imageView: UIImageView) {
imageView.layer.cornerRadius = (CGRectGetWidth(imageView.bounds) / 2)
imageView.clipsToBounds = true
imageView.layer.borderWidth = 2.0
imageView.layer.borderColor = UIColor.whiteColor().CGColor
}
I saw in a couple places that previously the subviews would not resize at all like here: UICollectionView cell subviews do not resize
I don't think this is an issue any more, however I did add the fixes into my code as you can see in configureCell() but it still isn't helping.
So it seems like those subviews are not resized until after the cellForItemAtIndexPath call is completed. Any thoughts on how I might address this? See screenshot of :rounded corners on UIImageViews instead of complete circles
Don't use viewWithTag(), it's bad practice. Instead make the UILabel and UIImageView public or leave off the scope modifier.
Is the UIImageView a fixed size? If so, you don't need to call circularizeImageView() each time a cell is reused. Instead, call it in layoutSubviews() in your UITableViewCell subclass. This will also give you the correct size for imageView.bounds.height

Is it possible to create a header for each individual cell in a UICollectionView?

I'm working on a UICollectionView that needs to display two pieces of information. First it needs to display an image, which I've done by setting it to the background view.
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:UICollectionViewCell=collectionView.dequeueReusableCellWithReuseIdentifier("CellIdentifier", forIndexPath: indexPath) as UICollectionViewCell;
cell.backgroundView = UIImageView(image: introViewCollectionArray[indexPath.row].image)
return cell;
}
I have a string I also need to display above the image. The string is different for each image, but can be accessed using
introViewCollectionArray[indexPath.row].note
It looks like setting up a header for the entire UICollectionView is possible, but I don't see a way to have a header for each cell with the text content. Have I missed something, or do I need to approach this differently?
You need to add a supplementaryView or a decorationView to each cell, you do this by subclassing a collectionView layout or, more probably, a UICollectionViewFlowLayout
You may have a look at Apple Flow Layout documention and this decorationView tutorial

How do I remove the selection border on a table view cell?

As you can see, there's a border when selecting. I want to remove this border.
I've tried:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = roomsTableView.dequeueReusableCellWithIdentifier("roomsCell", forIndexPath: indexPath) as! RoomTableViewCell
cell.room = rooms[indexPath.row]
cell.layer.borderWidth = 0.0
cell.contentView.layer.borderWidth = 0.0
cell.layoutMargins = UIEdgeInsetsZero
return cell
}
That doesn't work.
self.roomsTableView.separatorStyle = UITableViewCellSeparatorStyle.None is already set.
Clarification: Look at the middle row. It's selected. You see the border above and below the couple? That's what I want to remove.
I'm going to assume you want to remove the separator from your TableView. You can do this with:
tableView.seperatorStyle = UITableViewSeparatorStyle.None
What is the height of the imageView compared to the cell? If the imageView is smaller by 2 points, the cells background will show through on the top and bottom of the imageView.
Another thing to look at is subclassing UITableViewCell and handling the selection state accordingly.
just for anyone having the same issue setting the
SelectionStyle = UITableViewCellSelectionStyle.None
of your UITableViewCell should do the trick. That will remove the selection border (not the separator) on the item.
Select the tableView and go to the attribute selector in the storyboard file, Then do the followings according to image attached
make Selection to no selection and uncheck the show selection on touch
You can prevent this behaviour by setting
selectionStyle = .none
On your cell awakeFromNib() method.

Change Color of UICollectionViewCell on touch

I have an array of cells in a collection view that I want to get to act like buttons.
When I tap on one, I want that cell to highlight, and then change colors.
I'm able to initially set the color of the view.backgroundColor inside of the collectionViewCell us the cellForItemAtIndexPath method. However, contrary to what I thought would work if I do this:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let cell: ButtonCollectionCell = collectionView.dequeueReusableCellWithReuseIdentifier("ButtonCell", forIndexPath: indexPath) as! ButtonCollectionCell
cell.cellBackgroundView.backgroundColor = UIColor.darkGrayColor()
}
the color still isn't changing...
Essentially I want these cells to behave exactly like a button. I want them to highlight to a lighter gray color upon touch (they are initially white) after I release my finger I want them to become a dark gray color.
If I touch again I want them to again highlight to a lighter gray color, and then become white again.
If didSelectItemAtIndexPath isn't the way to do it, what is?
I would recommend some changes in your code that will help you to resolve your error.
First I would call the cellForItemAtIndexPath method to get your cell instead of using the dequeue method:
let cell = collectionView.cellForItemAtIndexPath(indexPath) as! ButtonCollectionCell
Then you should call the reloadItemsAtIndexPaths inside the didSelectItemAtIndexPath method to reload the cell:
collectionView.reloadItemsAtIndexPaths([indexPath])
Also you shouldn't change the background in the didSelectItemAtIndexPath method, but in the cellForItemAtIndexPath method where you check if the cell is selected:
if(cell?.selected){
//set your background-color
}else{
//change color
}
You can implement your own touch down gesture recognizer for the UICollectionView. See https://stackoverflow.com/a/15629234/1557276
When it's done, call -indexPathForItemAtPoint: method of the UICollectionView instance and then make changes in the cell returned by -cellForItemAtIndexPath:
When you dequeueReusableCellWithReuseIdentifier it can return a new cell to you.
Instead use cellForItemAtIndexPath to get the current cell at that index path.
Put this line of code I your method:
collectionView.cellForItem(at: indexPath)?.backgroundColor = UIColor.cyan

SelectedBackgroundView of UICollectionViewCell visible when it should not be

I've got a UICollectionView. With some cells inside with a white background color. I've set the selectedBackgroundView to a basic purple view.
My CollectionView has a constraint with a height of 0 and when I hit a button I update the constraint to 80. When I'm doing that, during the animation i can see the purple background on the screen until the end on the animation and i cannot understand why or how prevent this ?
Everything else working fine, it's just a "visual" bug.
Any suggestion about how to fix this ?
Gif of the bug where you can see the purple appearing during the animation
Here is my cell construction if it can be of any help :
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("WidgetMenuCellIdentifier", forIndexPath: indexPath) as UICollectionViewCell
cell.removeSubviews()
// some code setup
cell.selectedBackgroundView = UIView()
cell.selectedBackgroundView.backgroundColor = UIColor.purpleColor()
return cell
}
Subclass your UICollectionViewCell
Do
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// your code
cell.selectedBackgroundView.hidden = true
return cell
}
Then in your subclass :
override var selected:Bool {
willSet {
self.selectedBackgroundView.hidden = false
}
}
It should work.
It seems like this code is being executed within an animation, causing unexpected behavior at times based on how various properties animate. Another complicating factor is that, because cells are reused, it won't reproduce if a reused cell is already configured correctly (i.e. there is nothing to animate). Adding the following after styling the selectedBackgroundView was the least hacky solution I could think of.
[cell.selectedBackgroundView.layer removeAllAnimations];
Depending on what your cells are like you may also want to consider removing animations on other layers as well. For example:
[cell.backgroundView.layer removeAllAnimations];

Resources