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 // 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. /// 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. /// Data used to render tilelets in the carousel.
open var data: [Any] = [] { didSet { setNeedsUpdate() } } open var data: [Any] = [] { didSet { setNeedsUpdate() } }
@ -92,10 +92,13 @@ open class Carousel: View {
switch newValue { switch newValue {
case .percentage(let percentage): case .percentage(let percentage):
if percentage >= 10 && percentage <= 100.0 { 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): case .value(let value):
if value > minimumSlotWidth { /*(size.minimumSlotWidth)*/ if value > carouselScrollbarMinWidth {
_width = newValue _width = newValue
} }
} }
@ -256,6 +259,7 @@ open class Carousel: View {
private var containerViewHeightConstraint: NSLayoutConstraint? private var containerViewHeightConstraint: NSLayoutConstraint?
private var prevButtonLeadingConstraint: NSLayoutConstraint? private var prevButtonLeadingConstraint: NSLayoutConstraint?
private var nextButtonTrailingConstraint: 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. // 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 let scrollbarTopSpace = UIDevice.isIPad ? VDSLayout.space3X : VDSLayout.space1X
@ -263,6 +267,7 @@ open class Carousel: View {
var slotHeight = 100.0 var slotHeight = 100.0
var peekMinimum = 24.0 var peekMinimum = 24.0
var minimumSlotWidth = 0.0 var minimumSlotWidth = 0.0
var carouselScrollbarMinWidth = 96.0
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Lifecycle // MARK: - Lifecycle
//-------------------------------------------------- //--------------------------------------------------
@ -279,11 +284,12 @@ open class Carousel: View {
containerView containerView
.pinTop() .pinTop()
.pinBottom() .pinBottom()
.pinLeading() .pinLeadingGreaterThanOrEqualTo()
.pinTrailing() .pinTrailing()
.heightGreaterThanEqualTo(containerSize.height) .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 // add content stackview
containerView.addSubview(contentStackView) containerView.addSubview(contentStackView)
@ -312,13 +318,30 @@ open class Carousel: View {
.pinLeading() .pinLeading()
.pinTrailing() .pinTrailing()
.heightGreaterThanEqualTo(containerSize.height) .heightGreaterThanEqualTo(containerSize.height)
contentStackView.centerXAnchor.constraint(equalTo: centerXAnchor).activate()
addlisteners() addlisteners()
} }
open override func updateView() { open override func updateView() {
super.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.numberOfSlides = data.count
carouselScrollBar.layout = _layout carouselScrollBar.layout = _layout
carouselScrollBar.position = (carouselScrollBar.position == 0 || carouselScrollBar.position > carouselScrollBar.numberOfSlides) ? 1 : carouselScrollBar.position carouselScrollBar.position = (carouselScrollBar.position == 0 || carouselScrollBar.position > carouselScrollBar.numberOfSlides) ? 1 : carouselScrollBar.position
@ -335,58 +358,59 @@ open class Carousel: View {
peek = .standard peek = .standard
} }
containerViewHeightConstraint?.isActive = false
containerStackHeightConstraint?.isActive = false
updatePaginationControls() updatePaginationControls()
getSlotWidth() getSlotWidth()
// perform a loop to iterate each subView if containerView.frame.size.width > 0 {
scrollView.subviews.forEach { subView in containerViewHeightConstraint?.isActive = false
// removing subView from its parent view containerStackHeightConstraint?.isActive = false
subView.removeFromSuperview()
} // perform a loop to iterate each subView
scrollView.subviews.forEach { subView in
// add carousel items // removing subView from its parent view
if data.count > 0 { subView.removeFromSuperview()
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)
// 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() { open override func reset() {
super.reset() super.reset()
shouldUpdateView = false shouldUpdateView = false
aspectRatio = .ratio1x1 aspectRatio = .none
layout = UIDevice.isIPad ? .threeUP : .oneUP layout = UIDevice.isIPad ? .threeUP : .oneUP
pagination = .init(kind: .lowContrast, floating: true) pagination = .init(kind: .lowContrast, floating: true)
paginationDisplay = .none paginationDisplay = .none