Can't get a view to change it's size - ios

I have a UIImageView inside a ForecastCell Class (for a UICollectionView), anyhow, I can't get the UIImageView inside the cell to change it's size. This is what I tried:
private func setupWeatherIcon(){
self.addSubview(mWeatherIcon)
//mWeatherIcon.frame.size.width = CGFloat(self.frame.width) / 2
//mWeatherIcon.frame.size.height = CGFloat(self.frame.height) / 2
mWeatherIcon.frame.size.width = 20
mWeatherIcon.frame.size.height = 20
mWeatherIcon.centerXAnchor.constraint(equalTo: self.safeAreaLayoutGuide.centerXAnchor).isActive = true
mWeatherIcon.centerYAnchor.constraint(equalTo: self.safeAreaLayoutGuide.centerYAnchor).isActive = true
}
This is mWeatherIcon:
var mWeatherIcon: UIImageView = {
let image = UIImageView(image: UIImage(named: "partly-cloudy"))
image.translatesAutoresizingMaskIntoConstraints = false
return image
}()
No matter what width and height I set, It always stays the same width and height.

You need width and height constraints
self.contentView.addSubview(mWeatherIcon)
NSLayoutConstraint.activate([
mWeatherIcon.centerXAnchor.constraint(equalTo:contentView.centerXAnchor),
mWeatherIcon.centerYAnchor.constraint(equalTo:contentView.centerYAnchor),
mWeatherIcon.widthAnchor.constraint(equalTo:contentView.widthAnchor,multiplier:0.5),
mWeatherIcon.heightAnchor.constraint(equalTo:contentView.heightAnchor,multiplier:0.5)
])
Don't forget to implement this method
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize

Related

Table view cell scrolling issue

I have a table view and collection view to display image. Table view for vertical scroll and collection view for horizontal scroll. The image is displayed as full screen for the device. But when I scroll vertically half of previous cell is displayed and half of next cell is displayed. I used Table view constant is 0 to superview on all 4 constraints.
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return myTableView.frame.size.height;
}
To return the height of the cell but even this is causing same issue.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.myTableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
return cell
}
This table view cell contains collection view
class TableViewCell: UITableViewCell,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{
func setUpCollectionView(){
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
collectionView = UICollectionView(frame: .zero,collectionViewLayout: layout)
collectionView?.register(VideoCollectionViewCell.self, forCellWithReuseIdentifier: VideoCollectionViewCell.identifier)
collectionView?.isPagingEnabled = true
collectionView?.dataSource = self
collectionView?.delegate = self
self.contentView.addSubview(collectionView!)
collectionView?.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
collectionView!.topAnchor.constraint(equalTo: contentView.topAnchor),
collectionView!.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
collectionView!.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
collectionView!.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
])
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.frame.width, height: self.frame.height)
}
}
This is my implementation, I don't want images to be displayed on half/half portion. I am trying to show it on full screen. Can anyone tell me why this is happening?
you need only UICollectionView display list images and set property scroll horizontal in UICollectionViewFlowLayout
myCollectionView.dataSource = self
myCollectionView.delegate = self
myCollectionView.contentMode = .scaleAspectFill
// scroll the images page by page, set property isPagingEnabled is true
myCollectionView.isPagingEnabled = true
let layout = UICollectionViewFlowLayout()
// set sroll horizontal here
layout.scrollDirection = .horizontal
myCollectionView.collectionViewLayout = layout

Programmatically fill UIImageView with UIImage and place in UICollectionViewCell

I have been trying to fill in a UIImageView with a UIImage (car system image). I have tried numerous solutions online but can not seem to have it fill the UICollectionViewCell, awkward spacing seen here:
I figured since the UIView is the size of the UICollectionViewCell as seen here:
It must be the image is not scaling to the view. So I modified the content mode to scale to fill of the image view when creating the cells for the collection view, then adding this image view into the collection view cell:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CarCell", for: indexPath)
let carImageView = UIImageView(image: UIImage(systemName: "car"))
carImageView.contentMode = .scaleToFill
cell.addSubview(carImageView)
return cell
}
This doesn't seem to have any effect (even when using .bottom for the content mode the image does not move), but looking in the view hierarchy it seems this is what should be fixing it.
Does anyone know what I may be doing wrong?
Here is the storyboard:
Update:
I have added constraints to the image view with this code:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CarCell", for: indexPath)
let carImage = UIImage(systemName: "car")
let carImageView = UIImageView(image: carImage)
carImageView.contentMode = .scaleToFill
cell.addSubview(carImageView)
carImageView.topAnchor.constraint(equalTo: cell.topAnchor).isActive = true
carImageView.bottomAnchor.constraint(equalTo: cell.bottomAnchor).isActive = true
carImageView.leftAnchor.constraint(equalTo: cell.leftAnchor).isActive = true
carImageView.rightAnchor.constraint(equalTo: cell.rightAnchor).isActive = true
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let columns: CGFloat = 2
let collectionViewWidth = collectionView.bounds.width
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
let spaceBetweenCells = flowLayout.minimumInteritemSpacing * (columns - 1)
let adjustedWidth = collectionViewWidth - spaceBetweenCells
let width: CGFloat = floor(adjustedWidth / columns)
let height: CGFloat = width
return CGSize(width: width, height: height)
}
But it ends up shrinking the image view rather than growing it to the size of the cell:
Give constraint to your imageView is zero from all side of collectionView cell and set image content mode to .scaleToFill and than show the result.
Thanks
I got you there. As I previously commented to show how you are giving constraints to image view, thus the error was there. There is a property called "translatesautoresizingmaskintoconstraints" which you need set while giving constraints to your views. You can read about it here.
Now, in your cellForItemAt you need to change:-
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CarCell", for: indexPath)
let carImage = UIImage(systemName: "car")
let carImageView = UIImageView(image: carImage)
carImageView.contentMode = .scaleToFill
carImageView.translatesautoresizingmaskintoconstraints = false
cell.addSubview(carImageView)
carImageView.centerXAnchor.constraint(equalTo: cell.contentView.centerXAnchor).isActive = true
carImageView.centerYAnchor.constraint(equalTo: cell.contentView.centerYAnchor).isActive = true
carImageView.heightAnchor.constraint(equalTo: cell.contentView.heightAnchor).isActive = true
carImageView.widthAnchor.constraint(equalTo: cell.contentView.widthAnchor).isActive = true
return cell
}
As you can notice I've also changed the constraint to give an idea about how you should give the constraints if you want to set the image size as exact as your cell. You should always access cell's content view when you're giving constraint not the cell.

One way paging in scrollview

Is there a way to allow paging in a UIScrollView but restrict the paging to one direction.
For example: Allowing the user to page background (to the left) but not forward. Use case being for some type of onboarding. I know I can add buttons that move forward, have them enabled or disabled, and remove swiping but I rather not.
I don't know if I have well understand what you want but what about using a UICollectionView:
lazy var onBoardingCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
let cv = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
cv.showsHorizontalScrollIndicator = false
cv.showsVerticalScrollIndicator = false
cv.isPagingEnabled = true
return cv
}()
You add you custom cell with the size of the screen as well by the method in UICollectionViewDelegateFlowLayout:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: SCREENW, height: SCREENH)
}
if you don't want to go in a specific direction you can try get the current cell displaying and removing the previous one of the dataSource and collection with this method.
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let currentPage = Int(scrollView.contentOffset.x / scrollView.frame.width)
print("current cell: ", currentPage)
}

Set the size of UICollectionViewCell dynamically

I have a UICollectionViewCell which contains an image view and a label.
I am able to dynamically size the cell only when I have an image view.
I have added a label below the imageView with auto layout.
On viewDidLoad the image gets truncated or the text gets truncated. How can I dynamically size both the image view and label in the UICollectionViewCell.
Following is my code that works only with imageView
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
let imageSize = model.images[indexPath.row].size
return imageSize
}
I have an array of text and images from where I am displaying the content.
Any help will be appreciated. Thank you.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
let imageSize = model.images[indexPath.row].size
//find the height of label on setting text.
//create a temp label
let tempLabel = UILabel()
tempLabel.numberOfLines = 0
tempLabel.text = "abcd" //set ur cells text here
let labelSize = tempLabel.intrinsicContentSize
return CGSize(width: imageSize.width + labelSize.width, height: imageSize.height + labelSize.height)
}
width of label = width of image view.
it is ok.
for height, you can use Intrinsic Content Size function to get size of label.
Here collectioncell is outlet of Collection view
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
let cellsize = CGSize(width: (collectioncell.bounds.size.width/2) - 12, height:(collectioncell.bounds.size.height/3) - 20)
return cellsize
}

Resize images automatically in CollectionViewCell in CollectionView with Auto Layout

I have a collectionView with horizontal UICollectionViewFlowLayout.
I am trying to achieve:
If a device orientation is portrait, UIImageView width will be qual to view.width and let the height be calculated automatically (like it usually happens with Auto Layout). And the same for the landscape mode. Example - standard photo app on the Iphone.
Unfortunately i don't see how to achieve it with autoLayout. I set constraints on UIImageView for it to be equal in size to the cell. But looks like the sell itself cannot be pinned to the Parent View.
After reading similar questions looks like cells must be resized programmatically using
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSize(width: width, height: height)
}
And here i am stuck because i know the width of the screen but don't know how to calculate the height dynamically.
About image height:
I have my image declared like this:
var pageImages = [UIImage]()
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: ImageDetailViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! ImageDetailViewCell
let curr = indexPath.row
let imgName = data[albumNumber][curr]["image"]
cell.DetailImageView.image = UIImage(named: imgName!)
return cell
}
If you use the proper UIImageView resize setting (say, aspect fit/fill), then you just need to set the cell's height to your collectionView's (you get a pointer to it as one of the ...sizeForItemAtIndexPath... method parameters) height. You also should call the - layoutIfNeeded method on your cell afterwards.
You can use sizeForItemAtIndexPath: to change the size of collection view cell.
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
var numberOfCellInRow : Int = 3
var padding : Int = 5
var collectionCellWidth : CGFloat = (self.view.frame.size.width/CGFloat(numberOfCellInRow)) - CGFloat(padding)
return CGSize(width: collectionCellWidth , height: collectionCellWidth)
}
You can get the size of cell via :
((UICollectionViewFlowLayout) self.collectionViewName).itemSize.height)
You can get the image size via :
let sizeOfImage = image.size
let height = image.height
If you want to change the height then change it manually by return CGSize(width: collectionCellWidth , height: cellheight)

Resources