Digital ACT-191 ONEAPP-7013 story: flexible width support, Carousel can be set to any pixel or percentage
This commit is contained in:
parent
c51093cfaf
commit
fa5051d258
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user