UICollectionView Data not displaying correctly - ios

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: MaterialCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! MaterialCollectionViewCell
let item = items()[indexPath.item]
//print(cell.contentView.subviews)
for view in cell.contentView.subviews{
view.removeFromSuperview()
}
//print(cell.contentView.subviews)
let colors = [UIColor.grayColor(), UIColor.darkGrayColor()]
cell.backgroundColor = colors[indexPath.item % 2]
let showTitle: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: cell.frame.width, height: cell.frame.height))
showTitle.text = item.title
showTitle.textAlignment = .Center
showTitle.font = UIFont(name: "HelveticaNeue", size: 25.0)
showTitle.textColor = MaterialColor.white
showTitle.center = cell.center
showTitle.hidden = true
//print(showTitle.text)
cell.contentView.addSubview(showTitle)
let imageView: UIImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: cell.frame.width, height: cell.frame.height))
imageView.kf_setImageWithURL(NSURL(string: item.banner)!,
placeholderImage: nil,
optionsInfo: nil,
progressBlock: { (receivedSize, totalSize) -> () in
//print("Download Progress: \(receivedSize)/\(totalSize)")
},
completionHandler: { (image, error, cacheType, imageURL) -> () in
//print("Downloaded and set!")
if (image != nil) {
showTitle.removeFromSuperview()
}
else {
showTitle.hidden = false
}
}
)
cell.contentView.addSubview(imageView)
//print(cell.contentView.subviews)
return cell
}
this is the code I am using to display data into show title label. For the moment imageView doesn't ever show
issue with mine is the complete data is not displayed instead a part of it
current output
Should have shown these in the same order
Game of Thrones
Orange Is the New Black
Marco Polo (2014)
Person of Interest
Dark Matter

I think the problem is that the UILabel view and the UIImageView are overlapped 。 You should shrink the size of UILabel, and put the UIImageView behind the UILabel.

Related

Custom image and switch not showing in collection view controller at right place

My requirement is, I need to populate 10 cell's in collection view controller and I need to display in 6Th cell battery status and in 7th need to switch. The remaining cell is not required to show the battery status and switch. I am adding these two (battery status & switch) through programmatically.
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if indexPath.row == 6 {
let percentage: CGFloat = 0.4
let imageview:UIImageView=UIImageView(frame: CGRect(x: 10, y: 50, width: 30, height: 18))
let img : UIImage = UIImage(named:"batteryIcon")!
imageview.image = img
let batteryView = UIView.init(frame: CGRect(x: 10, y: 50, width: 30, height: 18))
cell.addSubview(batteryView)
let colorRect = CGRect(x: batteryView.bounds.origin.x, y: batteryView.bounds.origin.y, width: batteryView.bounds.width * percentage, height: batteryView.bounds.height)
let coloredView = UIView(frame: colorRect)
coloredView.backgroundColor = UIColor.green
batteryView.addSubview(coloredView)
cell.contentView.addSubview(imageview)
} else if indexPath.row == 7 {
let switchDemo = UISwitch(frame: CGRect(x: 10, y: 40, width: 37, height: 18))
switchDemo.isOn = true
switchDemo.setOn(true, animated: false)
switchDemo.transform = CGAffineTransform(scaleX: 0.70, y: 0.70)
switchDemo.addTarget(self, action: #selector(switchValueDidChange), for: .valueChanged)
cell.contentView.addSubview(switchDemo)
}
return cell
}
Here it is Working fine. But the problem is when I call "collectionView.reloadData()" Instead of showing battery status and switch 6Th and 7Th cells, Those two appearing in other cells also.
I am not getting, What mistake I am done.
For a better understanding of my requirement, I am sharing an image.

ios swift 3 delete contents of each cell when reloading tableView

I am creating a quizApp using DLRadioButton with a label in each cell of tableView, the label is set from the storyBoard(with a tag) but I have set radioButtons programmatically for better design when I click next button to pass to next question new Radiobutton overlaps with the old Radiobutton
here is the first question
here is the second image
Below is my code
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell")!
var reponse = rep[(indexPath as NSIndexPath).row]
let content:UILabel=cell.viewWithTag(111) as! UILabel
//var ra:UIButton=cell.viewWithTag(112) as! UIButton
content.text=reponse["rep"] as? String
content.sizeToFit()
let repiii = reponse["rep"] as? String
// var radio = DLRadioButton()
if (self.type=="case à cocher"){
// cell.contentView.delete(radioButtons)
let frame = CGRect(x: 50, y: 20, width: 200, height: 40)
let squareButton = self.createRadioButton(frame: frame, title:repiii!, color: UIColor.red,compt: squareButtons.count,sqaure:1);
squareButtons.append(squareButton)
cell.contentView.addSubview(squareButton)
}
else{
let frame = CGRect(x: 50, y: 20, width: 200, height: 40)
let radioButton = self.createRadioButton(frame: frame, title:repiii!, color: UIColor.blue,compt: radioButtons.count,sqaure:0);
//radioButton.isMultipleSelectionEnabled = true
print(radioButtons.count)
radioButtons.append(radioButton)
cell.contentView.addSubview(radioButton)
}
return cell
}
any suggestion is appreciated
in your code, just after the line
let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell")!
add this:
for subview in cell.contentView.subviews {
subview.removeFromSuperView()
}

Using buttons/images in tableView:editActionsForRowAt:

I am trying to use tableView:editActionsForRowAt:, having buttons with images instead of the usual texts.
But there are some challenges. Can some one help me?
First here is what I have already working, -- with some precious help from SOF --
and here is what I would like to get ideally:
The relevant code is below. The first case above is obtained when having xShift and xShiftInc both set to 0.0.
The second case is obtained by initializing xShift to 30.0 and xShiftInc to 20.0.
Graphically I get the result I want, but the problem is that the touch areas for the buttons have not moved as the image. In other words in the second case, if I touch the trash it prints "upBtn touched!".
To get "rmvBtn touched!" printed I need touch at the left of the trash.
Beside, I am not very happy with using 46.0 for the height of the cell, I would like a more generic parameter (rowHeigh equals -1 so can't be used). But this is a different issue.
func tableView(_ tableView: UITableView,
editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
var patternImg:UIImage?, xShift = CGFloat(30.0)//CGFloat(0.0)//
let xShiftInc = CGFloat(20.0)//CGFloat(0.0)//
let downBtn = UITableViewRowAction(style: .normal, title: "") {
action, index in
print("downBtn touched!")
}
patternImg = swipeCellImage(named: "DownIcn", side: 46.0, horizOffSet: xShift)
downBtn.backgroundColor = UIColor(patternImage: patternImg!)
let upBtn = UITableViewRowAction(style: .normal, title: "") {
action, index in
print("upBtn touched!")
}
xShift += xShiftInc
patternImg = self.swipeCellImage(named: "UpIcn", side: 46.0, horizOffSet: xShift)
upBtn.backgroundColor = UIColor(patternImage: patternImg!)
let rmvBtn = UITableViewRowAction(style: .destructive, title: "") {
action, index in
print("rmvBtn touched!")
}
xShift += xShiftInc
patternImg = swipeCellImage(named: "TrashIcn", side: 46.0, horizOffSet: xShift)
rmvBtn.backgroundColor = UIColor(patternImage: patternImg!)
return [downBtn,upBtn,rmvBtn]
}
func swipeCellImage(named name: String, side: CGFloat, horizOffSet: CGFloat) -> UIImage? {
let theImage = UIImage(named: name)
UIGraphicsBeginImageContextWithOptions(CGSize(width: UIScreen.main.bounds.width,
height: side), false, UIScreen.main.scale)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(UIColor.clear.cgColor)
theImage?.draw(in: CGRect(x: horizOffSet, y: 0, width: side, height: side))
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}
Simple logic..!! Manually we dont give xshift and xshiftinc.
Case 1:
let downBtn = UITableViewRowAction(style: .normal, title: "") {
action, index in
print("downBtn touched!")
}
Here title's text is "" [empty string with no spaces]
So, tableview automatically takes width 30px for each one. If we add text, it will increase it width sizes automatically.
Case 2:
let downBtn = UITableViewRowAction(style: .normal, title: " ") {
action, index in
print("downBtn touched!")
}
Here title's text is "" [empty string with 1 space]
So, tableview automatically takes width 35px for this.
Hope you understand above thing.
Now, I modified your code.
func tableView(_ tableView: UITableView,
editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let cell = tableView.cellForRow(at: indexPath) as! myTableViewCell
print("cell_height ", cell.frame.size.height) // U MAY GET ROW HEIGHT HERE
var patternImg:UIImage?
let downBtn = UITableViewRowAction(style: .normal, title: " ") {
action, index in
print("downBtn touched!")
}
patternImg = swipeCellImage(named: "down", rowHeight: cell.frame.size.height)
downBtn.backgroundColor = UIColor(patternImage: patternImg!)
let upBtn = UITableViewRowAction(style: .normal, title: " ") {
action, index in
print("upBtn touched!")
}
patternImg = self.swipeCellImage(named: "up", rowHeight: cell.frame.size.height)
upBtn.backgroundColor = UIColor(patternImage: patternImg!)
let rmvBtn = UITableViewRowAction(style: .destructive, title: " ") {
action, index in
print("rmvBtn touched!")
}
let patternIm = swipeCellImage(named: "trash", rowHeight: cell.frame.size.height)
rmvBtn.backgroundColor = UIColor(patternImage: patternIm!)
return [downBtn,upBtn,rmvBtn]
}
func swipeCellImage(name: String, rowHeight: CGFloat) -> UIImage? {
let imgYposition : CGFloat = (rowHeight - 30) / 2
// NOTE: This 30px is image height. Image height is always should be less than Rowheight.
let theImage = UIImage(named: name)
UIGraphicsBeginImageContextWithOptions(CGSize(width: UIScreen.main.bounds.width,
height: rowHeight), false, UIScreen.main.scale)
let context = UIGraphicsGetCurrentContext()
context!.setFillColor(UIColor.yellow.cgColor)
context!.fill(CGRect(x: 0, y: 0, width: (self.view.frame.width) / 3, height: side))
theImage?.draw(in: CGRect(x: 5, y: imgYposition, width: 30, height: 30))
// In this sample, am taking rowHeight as 44px.
// Images should be 30 * 30 sizes.
// I gave two spaces in title. So total width is 40px.
// So,x = 5px and y = 7px.
let resultImage : UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return resultImage
}
Output
If you want to give more gap between three buttons, just increase title's empty text and calculate width and keep your image center.

Dynamically changing CollectionView Cell Size Based on Downloaded Images Using Swift

I'm trying to build a collection view layout like Pinterest uses. Most of what is out there is in Objective C, so I've used this RW tutorial: http://www.raywenderlich.com/107439/uicollectionview-custom-layout-tutorial-pinterest
The problem is that the app in the RW tutorial uses local images, whereas I'm trying to base the cell size on images that are downloaded via PinRemoteImage but I cannot get the collectionView to properly lay itself out again once the images are downloaded.
Below is my attempt to modify the extension:
extension PinCollectionViewController : PinterestLayoutDelegate {
// 1
func collectionView(collectionView:UICollectionView, heightForPhotoAtIndexPath indexPath: NSIndexPath,
withWidth width: CGFloat) -> CGFloat {
var pinterestLargestImage = UIImage()
if imageDownloads == 0 {
pinterestLargestImage = imageArray[indexPath.row]
} else {
pinterestLargestImage = UIImage(named: "testPic")!
}
let boundingRect = CGRect(x: 0, y: 0, width: width, height: CGFloat(MAXFLOAT))
let rect = AVMakeRectWithAspectRatioInsideRect(pinterestLargestImage.size, boundingRect)
return rect.size.height
}
// 2
func collectionView(collectionView: UICollectionView,
heightForAnnotationAtIndexPath indexPath: NSIndexPath, withWidth width: CGFloat) -> CGFloat {
var pinterestLargestImage = UIImage()
if pins.count == imageArray.count {
pinterestLargestImage = imageArray[indexPath.row]
} else { pinterestLargestImage = UIImage(named: "testPic")!}
let annotationPadding = CGFloat(4)
let annotationHeaderHeight = CGFloat(17)
let font = UIFont(name: "AvenirNext-Regular", size: 10)!
let commentHeight = CGFloat(10.0)
let height = annotationPadding + annotationHeaderHeight + commentHeight + annotationPadding
return height
}
}
Then I've tried to call self.collectionView(self.collectionView!, layout: (self.collectionView?.collectionViewLayout)!, sizeForItemAtIndexPath: indexPath) and self.collectionView!.reloadItemsAtIndexPaths([indexPath]) inside cellForRowAtIndexPath once the cell's image is downloaded, but neither properly call these methods to adjust the layout. Can anyone point me in the right direction here?

Image and scrollView rendering making my tableview choppy

There may be no good solution for my problem, but I want to ask just in case.
I have a tableview in which each cell contains a horizontal scrollview of variable width. The width of each cell's scrollview depends on the number and sizes of the images for that cell. Everything works pretty well, but the tableview scrolls less smoothly than it could. I'm using Parse to retrieve the images (and pfquertableviewcontroller), but this question should apply to tableviews in general.
Here is my tableview code:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {
if var cell:MainFeedTableViewCell? = tableView.dequeueReusableCellWithIdentifier(self.cellIdentifier) as? MainFeedTableViewCell{
if(cell == nil) {
cell = NSBundle.mainBundle().loadNibNamed("MainFeedTableViewCell", owner: self, options: nil)[0] as? MainFeedTableViewCell
}
cell?.parseObject = object
return cell
}
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if let c = (cell as? MainFeedTableViewCell){
c.setUpObject()//this is where images are set
}
}
override func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if let c = (cell as? MainFeedTableViewCell){
c.resetObject() //this sets most of the properties to nil
}
}
And here is the function in my cell where images are set
func setUpObject(){
//I left out several lines of code where label text is set from the parseObject that is set when the cell is created
//setting images **problems here**
if let numImages = self.parseObject?["numImages"] as? Int{
self.newWidth1 = self.parseObject?["width1"] as? CGFloat
self.newWidth2 = self.parseObject?["width2"] as? CGFloat
self.newWidth3 = self.parseObject?["width3"] as? CGFloat
self.newWidth4 = self.parseObject?["width4"] as? CGFloat
self.newWidth5 = self.parseObject?["width5"] as? CGFloat
if numImages == 1{
self.containerView = UIView(frame: CGRect(x: self.scrollView.frame.minX, y: self.scrollView.bounds.minY - 90, width: self.scrollView.frame.width, height: self.scrollView.frame.height))
self.image1 = PFImageView(frame: CGRect(x: self.scrollView.frame.minX , y: self.scrollView.frame.minY, width: self.scrollView.frame.width, height: self.scrollView.frame.height))
self.image1?.contentMode = UIViewContentMode.ScaleAspectFit
self.image1!.file = self.parseObject?["image"] as? PFFile
self.image1!.loadInBackground()
self.containerView!.addSubview(self.image1!)
self.scrollView.contentSize = self.containerView!.bounds.size
self.scrollView.addSubview(self.containerView!)
}
else if numImages == 2{
if self.newWidth1 + self.newWidth2 < self.scrollView.frame.width{
self.containerView = UIView(frame: CGRect(x: self.scrollView.frame.midX - (self.newWidth1 + self.newWidth2)/2, y: self.scrollView.bounds.minY - 90, width: (self.newWidth1 + self.newWidth2), height: self.scrollView.frame.height))
}
else{
self.containerView = UIView(frame: CGRect(x: self.scrollView.frame.minX, y: self.scrollView.bounds.minY - 90, width: (self.newWidth1 + self.newWidth2), height: self.scrollView.frame.height))
}
self.image1 = PFImageView(frame: CGRect(x: self.scrollView.frame.minX , y: self.scrollView.frame.minY, width: self.newWidth1, height: self.scrollView.frame.height))
self.image1!.file = self.parseObject?["image"] as? PFFile
self.image1!.loadInBackground()
self.containerView!.addSubview(self.image1!)
self.image2 = PFImageView(frame: CGRect(x: (self.scrollView.frame.minX + self.newWidth1), y: self.scrollView.frame.minY, width: self.newWidth2, height: self.scrollView.frame.height))
self.image2!.file = self.parseObject?["image2"] as? PFFile
self.image2!.loadInBackground()
self.containerView!.addSubview(self.image2!)
self.subLayer = CALayer()
self.subLayer.backgroundColor = UIColor.whiteColor().CGColor
self.subLayer.frame = CGRect(x: self.newWidth1, y: self.scrollView.frame.minY, width: 1, height: self.scrollView.frame.height)
self.containerView!.layer.addSublayer(self.subLayer)
self.scrollView.contentSize = self.containerView!.bounds.size
self.scrollView.addSubview(self.containerView!)
}
//repeat similar code for cases where there are 3, 4, or 5 images
There might be a fundamental issue with dynamically adjusting the size of the scrollview and adding it to superview just in time, but I'm trying to follow the design mockup that my designer gave me.
Here is what the scrollview on the cell looks like (with each image in the scrollview separated by a thin white line)
Remove your willDisplayCell and didEndDisplayingCell. That will fire as you scroll and your setUpObject code, while not huge, will block the main thread slightly. Instead move setUpObject() to right before returning the cell in cellForRowAtIndexPath.
Depending on how many rows you have and performance requirements you could also adjust the viewController to download all of the images ahead of time and pass them to the cell instead of loading them inside the cell.

Resources