How to lower the opacity of the the left and right image? I am using a CollectionView to show all the data in the image. I want to lower the opacity of the views to the left and right of the center. I don't know how to do that. I can do all stuff in viewDidLayoutSubviews. Please resolve this issue. This is my code:
var arrHeading = ["Total Visitors in last 30 Days", "Total Departments", "Total Employees"]
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return arrHeading.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VisitorDashboardCell", for: indexPath) as! VisitorDashboardCell
cell.imgBG.layer.cornerRadius = 10
cell.imgBG.layer.masksToBounds = true
//Set Gradient Color to CollectionViewCell
cell.layer.shadowColor = UIColor.black.cgColor
cell.layer.shadowOffset = CGSize(width: 0, height: 0)
cell.layer.shadowRadius = 2.0;
cell.layer.shadowOpacity = 0.9;
cell.layer.cornerRadius = 10
cell.layer.masksToBounds = false
cell.imgBG.layer.shadowPath = UIBezierPath(rect: CGRect(x: -8, y: -18, width: cell.frame.size.width + 8 , height: cell.frame.size.height + 18)).cgPath
cell.layoutIfNeeded()
cell.imgBG.image = UIImage.init(named: arrImage[indexPath.row])
cell.imgIcon.image = UIImage.init(named: arrIcon[indexPath.row])
cell.lblHeading.text = arrHeading[indexPath.row]
cell.lblNum.text = arrNum[indexPath.row]
return cell
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let middleValue = round(Double(arrHeading.count / 2))
print("Middle Value \(middleValue)")
if arrHeading.count < Int(middleValue)
{
var leftArray = [Int]()
for i in 0..<(Int(middleValue) - 1) {
leftArray.append(i)
}
print("Left Array \(leftArray)")
}
else if arrHeading.count > Int(middleValue)
{
var rightArray = [Int]()
for i in Int(middleValue)..<arrHeading.count
{
rightArray.append(i)
}
print("Right Array \(rightArray)")
}
else
{
//Show middle element of the collection view
let selectedIndex = IndexPath(item: Int(middleValue), section: 0)
self.collectionView.scrollToItem(at: selectedIndex, at: .centeredHorizontally, animated: false)
}
}
Try something like this on your delegate:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
UIView.animate(withDuration: 0.5) {
cell.alpha = cell.isSelected ? 1 : 0.5
}
}
Related
I have a collectionView with images from a service request that are showed in lines with 3 elements.
What I need is that when a Have just one or two images from the request, the images shows aligned to the left, but the screen shows the images centered.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if imageFuelArray.count == 1{
let padding: CGFloat = 10
let collectionViewWidth = collectionView.frame.size.width - padding
let collectionViewHeight = collectionView.frame.size.height - padding
return CGSize(width: collectionViewWidth, height: collectionViewHeight)
} else{
let padding: CGFloat = 10
let collectionViewWidth = collectionView.frame.size.width - padding
let collectionViewHeight = collectionView.frame.size.height - padding
return CGSize(width: collectionViewWidth/2, height: collectionViewHeight/2)
}
}
I have this function
func getSizeVews(){
if imageFuelArray.count > 6{
self.collectionView.heightAnchor.constraint(equalToConstant: self.collectionView.contentSize.height+45).isActive = true
self.servicesTableView.heightAnchor.constraint(equalToConstant: self.servicesTableView.contentSize.height+70).isActive = true
view.layoutSubviews()
} else {
self.collectionView.heightAnchor.constraint(equalToConstant: self.collectionView.contentSize.height).isActive = true
self.servicesTableView.heightAnchor.constraint(equalToConstant: self.servicesTableView.contentSize.height+70).isActive = true
view.layoutSubviews()
}
}
And there I have my collectionView datasource and delegate
extension ServicesStationViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
imageFuelArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: flCollectionVieCell, for: indexPath) as! FuelCollectionViewCell
let fuel = imageFuelArray[indexPath.row]
if let cepsaFuel = CepsaFeaturesFuel(key: Int(fuel) ?? 0) {
let imgName = CepsaFeaturesFuel.featureFuelImageName(with: cepsaFuel.featuresFuelType)
cell.fuelImageView?.image = UIImage(named: imgName!)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
if imageFuelArray.count == 1{
let padding: CGFloat = 10
let collectionViewWidth = collectionView.frame.size.width - padding
let collectionViewHeight = collectionView.frame.size.height - padding
return CGSize(width: collectionViewWidth, height: collectionViewHeight)
} else{
let padding: CGFloat = 10
let collectionViewWidth = collectionView.frame.size.width - padding
let collectionViewHeight = collectionView.frame.size.height - padding
return CGSize(width: collectionViewWidth/2, height: collectionViewHeight/2)
}
}
}
I want to create a UICollectionview like the picture. Here I am having 18 Squares. The width of the Collection view is addition of 6 times square width and three border lines width.Similarly the height is also addition of 3 times the height of square and two border lines.
In collectionView how can i add the borderlines in the front as well as in between the cells as in the picture.
Output
You can get above design layout from UICollectionViewLayout.
Three Files:
1. SquareViewController
2. SquareCollectionViewCell
3. SquareLayout
SquareViewController----
class SquareViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
// CONSTRAINTS: top 20, left 0, right 0, height 100.
#IBOutlet weak var squareCollectionVw: UICollectionView!
// SET squareCollectionVw HEIGHT CONSTRAINT OUTLET
#IBOutlet weak var collectionVwHeightConst: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
collectionVwHeightConst.constant = (UIScreen.main.bounds.width / 6) * 3 + 1
squareCollectionVw.backgroundColor = UIColor.darkGray
// Do any additional setup after loading the view.
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 18
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "square", for: indexPath) as! SquareCollectionViewCell
cell.backgroundColor = UIColor.white
cell.layer.borderColor = UIColor.lightGray.cgColor
cell.layer.borderWidth = 1.0
return cell
}
}
SquareCollectionViewCell
class SquareCollectionViewCell: UICollectionViewCell {
}
SquareLayout [UICollectionViewLayout]
class Square: UICollectionViewLayout {
var CELL_HEIGHT = 0.0
var CELL_WIDTH = 0.0
var portrait_Ypos : Double = 0.0
var portrait_Xpos : Double = 0.0
var contentSize = CGSize.zero
var cellAttrsDictionary = Dictionary<IndexPath, UICollectionViewLayoutAttributes>()
override var collectionViewContentSize : CGSize {
return self.contentSize
}
override func prepare() {
CELL_WIDTH = (Double(UIScreen.main.bounds.width) / 6) - 0.5
CELL_HEIGHT = CELL_WIDTH
if let sectionCount = collectionView?.numberOfSections, sectionCount > 0 {
for section in 0...sectionCount-1 {
if let rowCount = collectionView?.numberOfItems(inSection: section), rowCount > 0 {
for item in 0...rowCount-1 {
let cellIndex = IndexPath(item: item, section: section)
if item <= 5
{
portrait_Ypos = 1
if item == 0
{
portrait_Xpos = 1
}
else
{
if item == 3
{
portrait_Xpos = portrait_Xpos + CELL_WIDTH + 1
}
else
{
portrait_Xpos = portrait_Xpos + CELL_WIDTH
}
}
}
else
{
if item == 6
{
portrait_Ypos = 1 + CELL_HEIGHT
portrait_Xpos = 1
}
else
{
if item % 6 == 0
{
portrait_Ypos = portrait_Ypos + CELL_HEIGHT
portrait_Xpos = 1
}
else
{
if item % 6 == 3
{
portrait_Xpos = portrait_Xpos + CELL_WIDTH + 1
}
else
{
portrait_Xpos = portrait_Xpos + CELL_WIDTH
}
}
}
}
let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex)
cellAttributes.frame = CGRect(x: portrait_Xpos, y: portrait_Ypos, width: CELL_WIDTH, height: CELL_HEIGHT)
if section == 0 && item == 0 {
cellAttributes.zIndex = 4
} else if section == 0 {
cellAttributes.zIndex = 3
} else if item == 0 {
cellAttributes.zIndex = 2
} else {
cellAttributes.zIndex = 1
}
cellAttrsDictionary[cellIndex] = cellAttributes
}
}
}
}
let contentWidth = UIScreen.main.bounds.width
let contentHeight = CGFloat(portrait_Ypos) + CGFloat(CELL_HEIGHT)
self.contentSize = CGSize(width: contentWidth, height: contentHeight)
print("sPort.contentSize ", self.contentSize)
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var attributesInRect = [UICollectionViewLayoutAttributes]()
for cellAttributes in cellAttrsDictionary.values {
if rect.intersects(cellAttributes.frame) {
attributesInRect.append(cellAttributes)
}
}
return attributesInRect
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cellAttrsDictionary[indexPath]!
}
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true
}
}
Embedd UICollectionViewLayout in UICollectionView:
Select squareCollectionVw, and Click Attributes Inspector,
Change Layout as Custom from Flow
Class as SquareLayout [ For me, Square ]
You can simply put two UICollectionViewCell, with nine squares inside, in your UICollectionView and in the method cellForItem
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellID", for: indexPath) as! CustomCell
cell.layer.borderWidth = 2
cell.layer.borderColor = .black
return cell
}
From my opinion, you have to create a 2 identical cells and configure it in UICollectionViewFlowLayoutDelegate that each cell width is screen.width / 2 and put border for those 2 cells. In part of border you might have to play with layer (CALayer) to make it equal for 4 sides
For add space between cell
Suppose there are 2 cell in one row of UICollectionView
For example:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = (self.view.frame.size.width - 15) / 2.0 //total view width and 15 space between each cell
let height = CGFloat(70.0) //Height is 70. (you can take same as width also)
return CGSize(width: width, height: height)
}
This will help you to add space between cell.
For add border between cell
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionCell
cell.layer.borderWidth = 1.0
cell.layer.borderColor = UIColor.black
}
How can i animate Horizontal Collectionview as it is scrolled i changed alpha to 0 in the cell and in cellForItemAt i animate the alpha back to 1 but that only happens when the Collectionview is scrolled through the first time here is the code i have tried
UIView.animate(withDuration: 0.8) {
cell.imageView.alpha = 1
cell.onboardLabel.alpha = 1
}
I also tried to do this in scrollViewDidEndDecelerating but still not working
let index = Int(scrollView.contentOffset.x) / Int(scrollView.frame.width)
let indexPath = IndexPath(item: index, section: 0)
let cell = collectionView.cellForItem(at: indexPath) as? OnboardingCell
UIView.animate(withDuration: 0.8) {
cell?.imageView.alpha = 1
cell?.onboardLabel.alpha = 1
}
Swift 4:
Use this function from UICollectionViewDelegate:
override func collectionView(_ collectionView: UICollectionView,
willDisplay cell: UICollectionViewCell,
forItemAt indexPath: IndexPath) {
cell.alpha = 0
UIView.animate(withDuration: 0.8) {
cell.alpha = 1
}
}
Firstly you need to know which cells are visible so set this variable at the top of the file.
var visibleIndexPath: IndexPath? = nil
In scrollViewDidEndDecelerating use this code to set the visibleIndexPath:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
var visibleRect = CGRect()
visibleRect.origin = collectionView.contentOffset
visibleRect.size = collectionView.bounds.size
let visiblePoint = CGPoint(x: visibleRect.midX, y: visibleRect.midY)
if let visibleIndexPath = collectionView.indexPathForItem(at: visiblePoint) {
self.visibleIndexPath = visibleIndexPath
}
}
Now that you have a visibleIndexPath you can animate the cell in the willDisplay cell function.
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if let visibleIndexPath = self.visibleIndexPath {
// This conditional makes sure you only animate cells from the bottom and not the top, your choice to remove.
if indexPath.row > visibleIndexPath.row {
cell.contentView.alpha = 0.3
cell.layer.transform = CATransform3DMakeScale(0.5, 0.5, 0.5)
// Simple Animation
UIView.animate(withDuration: 0.5) {
cell.contentView.alpha = 1
cell.layer.transform = CATransform3DScale(CATransform3DIdentity, 1, 1, 1)
}
}
}
}
I have a horizontal collectionView and i would like to manage that when scrolling it, the centre cell becomes larger. So, each time a cell is the center cell it will be larger than the others. Check the image beneath.
Can anyone help me with the best way to do this? Thanks in advance!
My code so far:
import UIKit
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet var horizontalCollectionView: UICollectionView!
#IBOutlet var verticalCollectionView: UICollectionView!
var horizontal = ["1","2","3","4","5","6","7","8","9","10","1","2","3","4","5","6","7","8","9","10"]
var horizontalCellSize = CGSize(width: 50, height: 50)
var horizontalLargeCellSize = CGSize(width: 80, height: 80)
var centerCell = UICollectionViewCell()
var cellIsInCenter = false
var myIndexPath = IndexPath()
override func viewDidLoad() {
super.viewDidLoad()
}
// When the main view's dimensions change this will re-layout the collection view
override func viewWillLayoutSubviews() {
verticalCollectionView.collectionViewLayout.invalidateLayout()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return horizontal.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == horizontalCollectionView {
let horizontalCell = collectionView.dequeueReusableCell(withReuseIdentifier: "HorizontalCell", for: indexPath) as! HorizontalCell
horizontalCell.backgroundColor = UIColor.blue
horizontalCell.textLabel.text = horizontal[indexPath.row]
return horizontalCell
}
else {
let verticalCell = collectionView.dequeueReusableCell(withReuseIdentifier: "VerticalCell", for: indexPath) as! VerticalCell
verticalCell.backgroundColor = UIColor.red
verticalCell.textLabel.text = horizontal[indexPath.row]
return verticalCell
}
}
// MARK: UIScrollViewDelegate
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView == self.horizontalCollectionView {
let horizontalScrollPosition = scrollView.contentOffset.x * 35
self.verticalCollectionView.delegate = nil
self.verticalCollectionView.contentOffset = CGPoint(x: 0, y: horizontalScrollPosition)
self.verticalCollectionView.delegate = self
}
if scrollView == self.verticalCollectionView {
let verticalScrollPosition = scrollView.contentOffset.y
self.horizontalCollectionView.delegate = nil
self.horizontalCollectionView.contentOffset = CGPoint(x: verticalScrollPosition, y: 0)
self.horizontalCollectionView.delegate = self
}
}
// MARK: CollectionViewLayout
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if collectionView == verticalCollectionView {
let size = CGSize(width: collectionView.bounds.width, height: collectionView.bounds.height)
return size
}
if indexPath.item == 3 {
return CGSize(width: 70, height: 70)
}
return CGSize(width: 50, height: 50)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.verticalCollectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: true)
print("\(indexPath)")
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
var closestCell: UICollectionViewCell = self.horizontalCollectionView.visibleCells[0]
for cell in self.horizontalCollectionView.visibleCells as [UICollectionViewCell] {
let closestCellDelta = abs(closestCell.center.x - self.horizontalCollectionView.bounds.size.width / 2.0 - self.horizontalCollectionView.contentOffset.x)
let cellDelta = abs(cell.center.x - self.horizontalCollectionView.bounds.size.width/2.0 - self.horizontalCollectionView.contentOffset.x)
if (cellDelta < closestCellDelta){
closestCell = cell
self.centerCell = cell
self.cellIsInCenter = true
horizontalCellSize = CGSize(width: 80, height: 50)
}
}
let indexPath = self.horizontalCollectionView.indexPath(for: closestCell)
self.horizontalCollectionView.scrollToItem(at: indexPath!, at: .centeredHorizontally , animated: true)
if closestCell.backgroundColor == UIColor.black {
closestCell.backgroundColor = UIColor.blue
}
horizontalCollectionView.reloadItems(at: [self.horizontalCollectionView.indexPath(for: closestCell)!])
closestCell.backgroundColor = UIColor.black
}
}
Try this out:
func collectionView(_ collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if collectionView == verticalCollectionView {
let size = CGSize(width: collectionView.bounds.width, height: collectionView.bounds.height)
return size
}
let point = CGPoint(x: self.view.frame.size.width/2.0, y:35 )
//or you can try this code also
//let point = CGPoint(x: UIScreen.main.bounds.width/2, y:35 )
print(point)
let centerIndex = self.collectionView.indexPathForItemAtPoint(point)
if indexPath.item == centerIndex {
return CGSize(width: 70, height: 70)
}
return CGSize(width: 50, height: 50)
}
This code gives you the index of the item at the center of the collection View.
Hope this helps
I have collection view with items, each item has dimension (65 * 65) with horizontal flow, and I have button.
So when I click on the button all items must stack over first item, then I need to make collection layout vertically (like table view).
How to make it (with animation)?
func collectionView(collectionView: UICollectionView,layout collectionViewLayout: UICollectionViewLayout,sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if self.isClose {
return CGSizeMake(50, 50)
}else{
if self.isOpen {
return CGSizeMake(320, 50)
}else {
return CGSizeMake(50, 50)
}
}
}
Screenshot
In Swift 3 and 4
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
UIView.animate(withDuration: 0.5) {
if let cell = collectionView.cellForItem(at: indexPath) as? SSProductCell {
cell.imageView.transform = .init(scaleX: 0.95, y: 0.95)
cell.contentView.backgroundColor = UIColor(red: 0.95, green: 0.95, blue: 0.95, alpha: 1)
}
}
}
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
UIView.animate(withDuration: 0.5) {
if let cell = collectionView.cellForItem(at: indexPath) as? SSProductCell {
cell.imageView.transform = .identity
cell.contentView.backgroundColor = .clear
}
}
}