Digital ACT-191 ONEAPP-7013 story: flexible width support, Carousel can be set to any pixel or percentage

This commit is contained in:
Vasavi Kanamarlapudi 2024-07-01 10:32:06 +05:30
parent c51093cfaf
commit fa5051d258

View File

@ -79,7 +79,7 @@ open class Carousel: View {
// MARK: - Public Properties
//--------------------------------------------------
/// Aspect-ratio options for tilelet in the carousel. If 'none' is passed, the tilelet will take the height of the tallest item in the carousel.
open var aspectRatio: Tilelet.AspectRatio = .ratio1x1 { didSet { setNeedsUpdate() } }
open var aspectRatio: Tilelet.AspectRatio = .none { didSet { setNeedsUpdate() } }
/// Data used to render tilelets in the carousel.
open var data: [Any] = [] { didSet { setNeedsUpdate() } }
@ -92,10 +92,13 @@ open class Carousel: View {
switch newValue {
case .percentage(let percentage):
if percentage >= 10 && percentage <= 100.0 {
_width = newValue
let expectedWidth = safeAreaLayoutGuide.layoutFrame.size.width * (percentage/100)
if expectedWidth > carouselScrollbarMinWidth {
_width = newValue
}
}
case .value(let value):
if value > minimumSlotWidth { /*(size.minimumSlotWidth)*/
if value > carouselScrollbarMinWidth {
_width = newValue
}
}
@ -256,6 +259,7 @@ open class Carousel: View {
private var containerViewHeightConstraint: NSLayoutConstraint?
private var prevButtonLeadingConstraint: NSLayoutConstraint?
private var nextButtonTrailingConstraint: NSLayoutConstraint?
private var containerLeadingConstraint: NSLayoutConstraint?
// The scrollbar has top 5X space. So the expected top space is adjusted for tablet and mobile.
let scrollbarTopSpace = UIDevice.isIPad ? VDSLayout.space3X : VDSLayout.space1X
@ -263,6 +267,7 @@ open class Carousel: View {
var slotHeight = 100.0
var peekMinimum = 24.0
var minimumSlotWidth = 0.0
var carouselScrollbarMinWidth = 96.0
//--------------------------------------------------
// MARK: - Lifecycle
//--------------------------------------------------
@ -279,11 +284,12 @@ open class Carousel: View {
containerView
.pinTop()
.pinBottom()
.pinLeading()
.pinLeadingGreaterThanOrEqualTo()
.pinTrailing()
.heightGreaterThanEqualTo(containerSize.height)
containerView.centerXAnchor.constraint(equalTo: centerXAnchor).activate()
containerView.centerYAnchor.constraint(equalTo: centerYAnchor).activate()
containerLeadingConstraint = containerView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: 0)
// add content stackview
containerView.addSubview(contentStackView)
@ -312,13 +318,30 @@ open class Carousel: View {
.pinLeading()
.pinTrailing()
.heightGreaterThanEqualTo(containerSize.height)
contentStackView.centerXAnchor.constraint(equalTo: centerXAnchor).activate()
addlisteners()
}
open override func updateView() {
super.updateView()
if containerView.frame.size.width > 0 {
if let width {
containerLeadingConstraint?.deactivate()
switch width {
case .value(let value):
var expectedWidth = value
let fullWidth = safeAreaLayoutGuide.layoutFrame.size.width
expectedWidth = expectedWidth > fullWidth ? fullWidth : expectedWidth
containerLeadingConstraint?.constant = safeAreaLayoutGuide.layoutFrame.size.width - expectedWidth
case .percentage(let percentage):
let expectedWidth = safeAreaLayoutGuide.layoutFrame.size.width * (percentage/100)
containerLeadingConstraint?.constant = safeAreaLayoutGuide.layoutFrame.size.width - expectedWidth
}
containerLeadingConstraint?.activate()
}
}
carouselScrollBar.numberOfSlides = data.count
carouselScrollBar.layout = _layout
carouselScrollBar.position = (carouselScrollBar.position == 0 || carouselScrollBar.position > carouselScrollBar.numberOfSlides) ? 1 : carouselScrollBar.position
@ -335,58 +358,59 @@ open class Carousel: View {
peek = .standard
}
containerViewHeightConstraint?.isActive = false
containerStackHeightConstraint?.isActive = false
updatePaginationControls()
getSlotWidth()
// perform a loop to iterate each subView
scrollView.subviews.forEach { subView in
// removing subView from its parent view
subView.removeFromSuperview()
}
// add carousel items
if data.count > 0 {
var xPos = 0.0
for x in 0...data.count - 1 {
let carouselSlot = View().with {
$0.clipsToBounds = true
$0.backgroundColor = UIColor(red: CGFloat(216) / 255.0, green: CGFloat(218) / 255.0, blue: CGFloat(218) / 255.0, alpha: 1)
}
scrollView.addSubview(carouselSlot)
let size = ratioSize(for: minimumSlotWidth)
slotHeight = size.height
carouselSlot
.pinTop()
.pinBottom()
.pinLeading(xPos)
.width(minimumSlotWidth)
.height(slotHeight)
carouselSlot.layer.cornerRadius = 12.0
xPos = xPos + minimumSlotWidth + gutter.value
if containerView.frame.size.width > 0 {
containerViewHeightConstraint?.isActive = false
containerStackHeightConstraint?.isActive = false
// perform a loop to iterate each subView
scrollView.subviews.forEach { subView in
// removing subView from its parent view
subView.removeFromSuperview()
}
scrollView.contentSize = CGSize(width: xPos - gutter.value, height: slotHeight)
// add carousel items
if data.count > 0 {
var xPos = 0.0
for x in 0...data.count - 1 {
let carouselSlot = View().with {
$0.clipsToBounds = true
$0.backgroundColor = UIColor(red: CGFloat(216) / 255.0, green: CGFloat(218) / 255.0, blue: CGFloat(218) / 255.0, alpha: 1)
}
scrollView.addSubview(carouselSlot)
let size = ratioSize(for: minimumSlotWidth)
slotHeight = size.height
carouselSlot
.pinTop()
.pinBottom()
.pinLeading(xPos)
.width(minimumSlotWidth)
.height(slotHeight)
carouselSlot.layer.cornerRadius = 12.0
xPos = xPos + minimumSlotWidth + gutter.value
}
scrollView.contentSize = CGSize(width: xPos - gutter.value, height: slotHeight)
}
let containerHeight = slotHeight + scrollbarTopSpace + containerSize.height
if carouselScrollBar.isHidden {
containerStackHeightConstraint = contentStackView.heightAnchor.constraint(equalToConstant: slotHeight)
containerViewHeightConstraint = containerView.heightAnchor.constraint(equalToConstant: slotHeight)
} else {
containerStackHeightConstraint = contentStackView.heightAnchor.constraint(equalToConstant: containerHeight)
containerViewHeightConstraint = containerView.heightAnchor.constraint(equalToConstant: containerHeight)
}
containerViewHeightConstraint?.isActive = true
containerStackHeightConstraint?.isActive = true
}
let containerHeight = slotHeight + scrollbarTopSpace + containerSize.height
if carouselScrollBar.isHidden {
containerStackHeightConstraint = contentStackView.heightAnchor.constraint(equalToConstant: slotHeight)
containerViewHeightConstraint = containerView.heightAnchor.constraint(equalToConstant: slotHeight)
} else {
containerStackHeightConstraint = contentStackView.heightAnchor.constraint(equalToConstant: containerHeight)
containerViewHeightConstraint = containerView.heightAnchor.constraint(equalToConstant: containerHeight)
}
containerViewHeightConstraint?.isActive = true
containerStackHeightConstraint?.isActive = true
layoutIfNeeded()
}
open override func reset() {
super.reset()
shouldUpdateView = false
aspectRatio = .ratio1x1
aspectRatio = .none
layout = UIDevice.isIPad ? .threeUP : .oneUP
pagination = .init(kind: .lowContrast, floating: true)
paginationDisplay = .none