Im trying to get rounded UICollection cell but i found out that it's not working somehow and I can't come up why. I have a TableView in regular ViewController, in this tableview i've a custom table cell (in specified section) and in this custom table cell I've a CollectionView also with custom collectionCell and if i do anything rounded there, it's just not rounding anything. I cliped testBtn into bounds, but it wasn't work with this... I also tried testBtn.layer.masksToBounds with no success. However, if I'am doing a rounding in parent (tableView cell itself), it's working just good...
CollectionViewCell code:
import UIKit
class ProfileTileCollectionViewCell: UICollectionViewCell {
#IBOutlet var testBtn: UIButton!
#IBOutlet var contView: UIView!
override func awakeFromNib() {
super.awakeFromNib()
testBtn.layer.cornerRadius = 20
testBtn.clipsToBounds = true
// Initialization code
}
#IBAction func testClicked(_ sender: Any) {
print("clicked")
}
}
Screenshot of the mainView: Screenshot.png
Blue color is a background of collectionView, gray is background of cell and violet is a button. I don't know if it's getting late but it's weird for me, not be able to get working this thing... I'm missing something... Any help I will appreciate !
Try to set testBtn.layer.masksToBounds = true
From the screenshot, I guess you have added corner radius in your collection view and set clipsToBounds true. If you don't need rounded collection view then remove cornerRadius and set clipsToBounds false. Or if you need both of them rounded then maintain padding between collection view and button. You can do this by fine-tuning the section inset property.
I had a great 8 hours of sleep and cuz that and Rob's comment, I tried to dig into debug for a bit, and I noticed a warning message which were saying that behaviour of UICollectionViewFlowLayout is not set... (and so on). So I decided to set up UICollectionViewDelegateFlowLayout like this:
extension ProfileTilesTableViewCell: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top:0, left:10, bottom:0, right: 10)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: (collectionView.frame.width - 40) / 3 , height: collectionView.frame.height - 5)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 10
}
And finally :D somehow it started working properly !
So I deleted everything that I used for testing, deleted testBtn and changed testBtn.roundedCorners to contView.roundedCorners, set back the collectionView properties and it's looking near to what I'm looking for: Screenshot2.png
Thanx for your answers, especially to Rob's one. This is what I was looking for !
Best regards SB !
Related
This has been asked several times and I have tried to include aspects of all answers in my code - which still does not work - so there may be issues with methods/characteristics becoming obsolete in the newest iOS or with me just doing things wrong. But here is where I'm at:
The teal is background color for the CollectionView. Then there is a PostCell with a pink background which is covered with a blue image view on top of it to which I set an image from a url (the video thumbnail on top) as well as a pink textView containing notes.
What I want is to make the PostCell adhere to the top and bottom of the collection View so that you can no longer see the teal section.
Here are the constraints I have set as well as the view hierarchy:
In my TagViewController - the controller for this view, I have:
class TagViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
....
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
//top, left, bottom, right
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
override func viewDidLoad() {
super.viewDidLoad()
self.automaticallyAdjustsScrollViewInsets = false
collectionView.contentInsetAdjustmentBehavior = .never
}
....
}
The insetForSectionAt method and the methods I set in viewDidLoad are from the answers to similar questions I have found on stackOverflow so far such as here: UICollectionView adds top margin
and here:
iOS:Setting UICollectionView cell to view size
Have you tried the 'sizeForItemAt indexPath' method ?
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout:
UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: view.frame.height)
}
I noticed a big issue where in right to left languages, the cells order is not properly reversed, only the alignment is correct. But only for horizontal flow layout, and if the collection view contain different cell sizes! Yes, I know this sound insane. If all the cells are the same size, the ordering and alignment is good!
Here is what I got so far with a sample app (isolated to make sure this is the actual issue, and not something else):
(First bar should always be drawn blue, then size increase with index.)
Is this an internal bug in UICollectionViewFlowLayout (on iOS 11)? Or is there something obvious that I am missing?
Here is my test code (Nothing fancy + XIB with UICollectionView):
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 6
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "test", for: indexPath)
cell.backgroundColor = (indexPath.item == 0) ? UIColor.blue : UIColor.red
return cell
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: (10 * indexPath.item) + 20, height: 170)
}
Automatic right-to-left support on dynamically-sized UICollectionViews is not a supported configuration. For this to work, you need to explicitly sign up for automatic layout mirroring as follows:
Create a subclass of UICollectionViewFlowLayout
Override flipsHorizontallyInOppositeLayoutDirection, and return true in Swift or YES in Objective-C
Set that as the layout of your collection view
This property is defined on UICollectionViewLayout (parent of Flow), so you can technically use this property on any custom layout you already have.
I believe that for this you will have to implement your own custom collectionViewLayout - although I understand that one would expect that it would automatically work just as the right-to-left on the rest of the components.
I want to set custom horizontal scroll for my CollectionView, that it will be scrolling by 1 cell (not by the whole width of my screen).
I could set HORIZONTAL scroll, but not custom. (See screens).
1 screen: my extension of my collectionView for UIScrollViewDelegate.
*I saw, that in console (see too) "x" - my offset = 290 - it's true! But on fact it is not 290. Paging was marked in "true" 2 screen: delegate and dataSource.
Help, please!
First you need to set your collectionView scroll direction horizontal (UICollectionViewScrollDirectionHorizontal) and set pagingEnabled to YES
It means your collection view will be scroll horizontally with one by one cell.
Set horizontal direction (Select collection view from XIB or Storyboard)
And for set pagination enable
myCollectionView.pagingEnabled = true
Updated :
You should use of UICollectionViewDelegateFlowLayout delegate
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
let width = UIScreen.main.bounds.size.width
var height = 101.7 // set height as you want
return CGSize(width: width, height: height)
}
If using storyBoard the go to collection view and select the right handed tab "show the size inspector" and change
minimum spacing for cells = 0
minimum spacing for lines = 0
if you want to change directly from code then implement these UICollectionViewDelegateFlowLayout methods
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
must be remember scrolling direction set horizontal
and pagination enabled
and implement this delegate methods into code
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout
collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath:
IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.size.width, height:
collectionView.frame.size.height)
}
}
You could create a custom UICollectionViewFlowLayout that will center the cells in the screen and then page one at a time. Karmadust have written a good blog post that I have successfully used in the past to do the same thing
http://blog.karmadust.com/centered-paging-with-preview-cells-on-uicollectionview/
In an iOS app I have a UICollectionView which has 100 (or 80, or 40) cells to start with.
At the beginning all is fine, the layout is OK and the size of each cell is also right, smaller if there is 100 and larger if there is only 40 cells.
Inside the app the user has the possibility to change the number of cells to 100 (or 80, or 40).
When the number changes the layout and size of each cell should be changed accordingly. But that part does not work as expected.
When the user changes the number of cells this code is executed:
myCollectionView.reloadData()
myCollectionView.collectionViewLayout.invalidateLayout()
And for some reasons something is not working. Should I do something more or different in the code above?
The number of cells is right, but the size of the news cells is messed up and I am not totally sure about the layout (positionning).
As far as the UICollectionViewDelegate protocol is concerned, I only implement one method:
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath) {
.........
}
For the UICollectionViewDelegateFlowLayout protocol, I implement the following:
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let cellSide = UIScreen.main.bounds.width * 3 / CGFloat(brain.getSide()! * 4)
return CGSize(width: cellSide, height: cellSide)
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 6.0
}
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return UIScreen.main.bounds.width / (CGFloat(brain.getSide()!) * 4.4)
}
It seems like the methods above are working fine at start, giving adequate values. But they do not even seem to be called when the user changes the settings.
Please try this reloading method
Objective-c
[self.collectionView performBatchUpdates:^{
[myCollectionView reloadData];
}
completion:^(BOOL finished) {}
];
Swift-3
myCollectionView?.performBatchUpdates({
myCollectionView.reloadData()
}, completion: { (result: Bool) in
})
I ended up by solving the problem, using cell prototypes with a different cell identifier for each size I need and it works perfectly.
I have a UICollectionView, which uses UICollectionViewFlowLayout to arrange my cells inside the collection view.
Inside my cells, I have an image and a label. Using the above layout I am able to design my collection view with vertical scrolling,
But instead of vertical scrolling, I want a structure like UIPageViewController which will contain my UICollectionView with the above cells.
I have tried with flowLayout.scrollDirection = .horizontal,
But with that approach I could not solve my issue.
I am new to Swift and I am not using storyboards.
Open your storyboard, select the collectionView and change the scroll direction from vertical to horizontal as shown below :)
Now your collectionView will start scrolling horizontally than vertically :)
If you want pagination, like ViewControllers in pageViewController, select the collectionView and select paging enabled check box :)
Now if you want your collection view cell to cover the whole collectionView like view controllers in UIPageViewController, type this in your UICollectionView delegate :)
extension YourViewController : UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return self.pageViewController.frame.size
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
}
Want to leave spacing between cells return value instead of 0.0 in the above method :) Thats all
EDIT
In case you dont have storyboard you can set the scroll direction and other properties programmatically using
(self.collectionView.collectionViewLayout as! UICollectionViewFlowLayout).scrollDirection = .horizontal
I found my answer from the below link:
http://swiftiostutorials.com/ios-tutorial-using-uipageviewcontroller-create-content-slider-objective-cswift/
It really helped me a lot. Thanks.