How to show a collectionView like facebook upload image using swift 4?
Your answer is in your question bro some short of conditions
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
switch indexPath.item {
case 0,1:
return CGSize(width: (UIScreen.main.bounds.width - 16) / 2, height: (UIScreen.main.bounds.width - 16) / 2)
default:
return CGSize(width: (UIScreen.main.bounds.width - 32) / 3, height: (UIScreen.main.bounds.width) / 3)
}
}
Swift - Facebook style image grid using UICollectionViewFlowLayout
Change this line:
let itemWidth:CGFloat = (width - 2 * padding) / 3.0
to this:
let itemWidth:CGFloat = floor((width - 2 * padding) / 3.0)
You may want to do that with a 2 item row as well.
Edit
The initial problem is that floating-point numbers are approximations.
So, on an iPhone 8, for example, the view width is 375
points. The cell width calculation of:
let padding: CGFloat = 5
let itemWidth:CGFloat = (width - 2 * padding) / 3.0
itemWidth
ends up being 121.666... (repeating)
, which UIKit interprets as 121.66666666666667
.
So, 121.66666666666667 * 3.0 + 10
equals (roughly) 375.00000000000011
and... that is greater than 375.0
.
So, the collection view says "can't fit that on one row."
Using floor()
fixes the problem, except... it hits a really weird bug!
If you change numberOfItemsInSection
from 5
to 8
, you'll get two rows of 3, and there will be no gap on the right.
We can get around this by making the side cells slightly narrower than the center cell like this:
// we want all three to be the same heights
// 1/3 of (width - 2 * padding)
let itemHeight: CGFloat = (width - 2 * padding) / 3.0
// left and right cells will be 1/3 of (width - 2 * padding)
// rounded down to a whole number
let sideW: CGFloat = floor(itemHeight)
// center cell needs to be
// full-width minus 2 * padding
// minus
// side-width * 2
let centerW: CGFloat = (width - 2 * padding) - sideW * 2
// is it left (0), center (1) or right (2)
let n = (item - 2) % 3
// use the proper width value
let itemWidth: CGFloat = n == 1 ? centerW : sideW
return CGSize(width: itemWidth, height: itemHeight)
Or, what seems to be working is making the width just slightly smaller than the floating-point 1/3rd. You used -0.1
, but it also works with:
let itemWidth:CGFloat = ((width - 2 * padding) / 3.0) - 0.0000001
In any case, that hopefully explains the reason for the "2 cells instead of 3" issue, and two options for avoiding it.
How to upload image from photolibrary to specific collectionview cell when that cell is selected?
You need to remember which cell you tapped before picking image. You can save the index in collectionView(_:, didSelectItemAt:)
// instance property
private var selectedCellIndexPath: IndexPath?
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCellIndexPath = indexPath
let cell: UICollectionViewCell = collectionView.cellForItem(at: indexPath)!
cell.layer.borderWidth = 4.0
cell.layer.borderColor = UIColor.blue.cgColor
cellTapped()
}
Then you need to update you data source when the image is picked and reload collection.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let selectedImage = info[.originalImage] as? UIImage else {
fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
}
dismiss(animated: true, completion: nil)
// let us assume that your collection relies on some array called 'images'
guard let selectedCellIndexPath = selectedCellIndexPath,
selectedCellIndexPath.item < images.count else {
return
}
images[selectedCellIndexPath.item] = images
collectionView?.reloadData()
}
How would I upload new photo into collectionView cell using Firebase?
To upload images to Firebase storage and show them in a collection view, you can use the following steps;
Set up collection view with an array of
URL
s (orString
s) as its
data source. You can use your custom models if required.Keep a reference to your
Firebase storage
and upload the image. After successful upload, get the URL for the uploaded image using theimage reference
.Save the url in
Firebase Database
(orCloud Firestore
). This is required only if you want to sync the collection view with the database and update it when new images are uploaded.Add a listener to your
Firebase database
reference where you have
saved the image URLs. Update the local URLs array inside the listener and reload the collection view.
If you don't want to use Firebase database
, omit steps 3 and 4, save the image URL to the array and reload the collection view right away.
I'm not adding the code for collection view setup here as it's not the objective of this answer.
let storageRef = Storage.storage().reference(withPath: "images")
let databaseRef = Database.database().reference(withPath:"images")
var images: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
addDatabaseListener()
}
private func addDatabaseListener() {
databaseRef.observe(.childAdded) { (snapshot) in
guard let value = snapshot.value as? [String: Any], let url = value["url"] as? String else { return }
self.images.append(url)
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true)
guard let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage, let data = image.jpegData(compressionQuality: 0.1) else { return }
let fileName = "\(Date.timeIntervalSinceReferenceDate).jpeg"
let newImageRef = storageRef.child(fileName)
newImageRef.putData(data, metadata: nil) { (_, error) in
if let error = error {
print("upload failed: ", error.localizedDescription)
return
}
newImageRef.downloadURL { (url, error) in
if let error = error {
print("error: ", error.localizedDescription)
return
}
self.databaseRef.childByAutoId().setValue(["url": url?.absoluteString])
}
}
}
Use ImagePicker to upload images into CollectionView
After appending the new image to your data source call YOUR_COLLECTION_VIEW.reloadData()
just to display the new items which added recently to it's data source.
Show 3 images on 1st row and 3 images on second row on collectionview
Your code looks perfect but you may forgot to confirm the FlowLayout Protocol.
so,
you just need to confirm the below protocol in your code,
UICollectionViewDelegateFlowLayout
Hope this way may help you.
Related Topics
How to Use a Custom Font with Dynamic Text Sizes in iOS7
How to Create a Big, Red Uibutton with iOS
What's the Uiscrollview Contentinset Property For
Pull to Refresh Uitableview Without Uitableviewcontroller
How to Use Presentmodalviewcontroller to Create a Transparent View
Getting Time Elapsed in Objective-C
Reasons for Rejecting iPhone Application by Apple Store
Uiview - How to Get Notified When the View Is Loaded
How to Create a New Swift Project Without Using Storyboards
How to Add Image in Uitableviewrowaction
Segue in Skscene to Uiviewcontroller
Instantiate View Controller from Storyboard VS. Creating New Instance
Decode Base64Url to Base64 -- Swift
Pixel Array to Uiimage in Swift
Xcode - Mpnowplayinginfocenter Info Is Not Displayed on iOS 8