From 1b9e7a43a881858d338115121b9a16a82c81199d Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 19 Oct 2024 22:50:41 +0400 Subject: [PATCH] Improve tab selector in stats tabs --- .../ItemListControllerTabsContentNode.swift | 6 ++- .../Sources/TabSelectorComponent.swift | 46 ++++++++++++++----- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/submodules/ItemListUI/Sources/ItemListControllerTabsContentNode.swift b/submodules/ItemListUI/Sources/ItemListControllerTabsContentNode.swift index c629bd0b4e..cb68336005 100644 --- a/submodules/ItemListUI/Sources/ItemListControllerTabsContentNode.swift +++ b/submodules/ItemListUI/Sources/ItemListControllerTabsContentNode.swift @@ -86,8 +86,10 @@ final class ItemListControllerTabsContentNode: NavigationBarContentNode { ), customLayout: TabSelectorComponent.CustomLayout( font: Font.medium(14.0), - spacing: 24.0, - lineSelection: true + spacing: 48.0, + innerSpacing: 0.0, + lineSelection: true, + allowScroll: false ), items: mappedItems, selectedId: AnyHashable(self.index), diff --git a/submodules/TelegramUI/Components/TabSelectorComponent/Sources/TabSelectorComponent.swift b/submodules/TelegramUI/Components/TabSelectorComponent/Sources/TabSelectorComponent.swift index 486ab7df91..f107fd6366 100644 --- a/submodules/TelegramUI/Components/TabSelectorComponent/Sources/TabSelectorComponent.swift +++ b/submodules/TelegramUI/Components/TabSelectorComponent/Sources/TabSelectorComponent.swift @@ -27,14 +27,18 @@ public final class TabSelectorComponent: Component { public struct CustomLayout: Equatable { public var font: UIFont public var spacing: CGFloat + public var innerSpacing: CGFloat? public var lineSelection: Bool public var verticalInset: CGFloat + public var allowScroll: Bool - public init(font: UIFont, spacing: CGFloat, lineSelection: Bool = false, verticalInset: CGFloat = 0.0) { + public init(font: UIFont, spacing: CGFloat, innerSpacing: CGFloat? = nil, lineSelection: Bool = false, verticalInset: CGFloat = 0.0, allowScroll: Bool = true) { self.font = font self.spacing = spacing + self.innerSpacing = innerSpacing self.lineSelection = lineSelection self.verticalInset = verticalInset + self.allowScroll = allowScroll } } @@ -154,16 +158,19 @@ public final class TabSelectorComponent: Component { verticalInset = customLayout.verticalInset * 2.0 } - let innerInset: CGFloat = 12.0 - let spacing: CGFloat = component.customLayout?.spacing ?? 2.0 + var innerInset: CGFloat = component.customLayout?.innerSpacing ?? 12.0 + var spacing: CGFloat = component.customLayout?.spacing ?? 2.0 let itemFont: UIFont var isLineSelection = false + let allowScroll: Bool if let customLayout = component.customLayout { itemFont = customLayout.font isLineSelection = customLayout.lineSelection + allowScroll = customLayout.allowScroll || component.items.count > 3 } else { itemFont = Font.semibold(14.0) + allowScroll = true } if selectionColorUpdated { @@ -181,15 +188,14 @@ public final class TabSelectorComponent: Component { } } - var contentWidth: CGFloat = spacing - var previousBackgroundRect: CGRect? - var selectedBackgroundRect: CGRect? - var nextBackgroundRect: CGRect? + var innerContentWidth: CGFloat = 0.0 let selectedIndex = component.items.firstIndex(where: { $0.id == component.selectedId }) var validIds: [AnyHashable] = [] var index = 0 + var itemViews: [AnyHashable: (VisibleItem, CGSize, ComponentTransition)] = [:] + for item in component.items { var itemTransition = transition let itemView: VisibleItem @@ -243,8 +249,27 @@ public final class TabSelectorComponent: Component { environment: {}, containerSize: CGSize(width: 200.0, height: 100.0) ) - - if !contentWidth.isZero { + innerContentWidth += itemSize.width + itemViews[item.id] = (itemView, itemSize, itemTransition) + index += 1 + } + + let estimatedContentWidth = 2.0 * spacing + innerContentWidth + (CGFloat(component.items.count - 1) * (spacing + innerInset)) + if estimatedContentWidth > availableSize.width && !allowScroll { + spacing = (availableSize.width - innerContentWidth) / CGFloat(component.items.count + 1) + innerInset = 0.0 + } + + var contentWidth: CGFloat = spacing + var previousBackgroundRect: CGRect? + var selectedBackgroundRect: CGRect? + var nextBackgroundRect: CGRect? + + for item in component.items { + guard let (itemView, itemSize, itemTransition) = itemViews[item.id] else { + continue + } + if contentWidth > spacing { contentWidth += spacing } let itemTitleFrame = CGRect(origin: CGPoint(x: contentWidth + innerInset, y: verticalInset + floor((baseHeight - itemSize.height) * 0.5)), size: itemSize) @@ -269,7 +294,6 @@ public final class TabSelectorComponent: Component { itemTransition.setBounds(view: itemTitleView, bounds: CGRect(origin: CGPoint(), size: itemTitleFrame.size)) itemTransition.setAlpha(view: itemTitleView, alpha: item.id == component.selectedId || isLineSelection || component.colors.simple ? 1.0 : 0.4) } - index += 1 } contentWidth += spacing @@ -301,7 +325,7 @@ public final class TabSelectorComponent: Component { } } - var mappedSelectionFrame = effectiveBackgroundRect.insetBy(dx: 12.0, dy: 0.0) + var mappedSelectionFrame = effectiveBackgroundRect.insetBy(dx: innerInset, dy: 0.0) mappedSelectionFrame.origin.y = mappedSelectionFrame.maxY + 6.0 mappedSelectionFrame.size.height = 3.0 transition.setFrame(view: self.selectionView, frame: mappedSelectionFrame)