@momo-kits/native-kits 0.121.0-rc.4 → 0.121.0-rc.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -3,7 +3,7 @@ import SwiftUI
|
|
|
3
3
|
|
|
4
4
|
public struct ScrollViewWithScrollBar<Content: View>: View {
|
|
5
5
|
let INDICATOR_HEIGHT: CGFloat = 4
|
|
6
|
-
@State var position = CGPoint(x: 0, y: 2)
|
|
6
|
+
@State var position = CGPoint(x: 0, y: 2) //2 is INDICATOR_HEIGHT/2
|
|
7
7
|
@State var contentSize: CGFloat = 0
|
|
8
8
|
@State var scrollViewWidth: CGFloat = 0
|
|
9
9
|
var indicatorWidth: CGFloat
|
|
@@ -11,69 +11,97 @@ public struct ScrollViewWithScrollBar<Content: View>: View {
|
|
|
11
11
|
var indicatorColor: Color
|
|
12
12
|
var indicatorContainerColor: Color
|
|
13
13
|
@ViewBuilder var content: () -> Content
|
|
14
|
-
|
|
15
|
-
public init(
|
|
14
|
+
|
|
15
|
+
public init(
|
|
16
|
+
indicatorWidth: CGFloat = 12, indicatorContainerWidth: CGFloat = 36,
|
|
17
|
+
indicatorColor: Color = Colors.primary, indicatorContainerColor: Color = Colors.black06,
|
|
18
|
+
@ViewBuilder content: @escaping () -> Content
|
|
19
|
+
) {
|
|
16
20
|
self.indicatorWidth = indicatorWidth
|
|
17
21
|
self.indicatorContainerWidth = indicatorContainerWidth
|
|
18
|
-
self.content = content
|
|
19
22
|
self.indicatorColor = indicatorColor
|
|
20
23
|
self.indicatorContainerColor = indicatorContainerColor
|
|
24
|
+
self.content = content
|
|
21
25
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
|
|
27
|
+
// MARK: Public
|
|
28
|
+
|
|
25
29
|
public var body: some View {
|
|
26
30
|
return VStack {
|
|
27
|
-
|
|
28
|
-
HStack {
|
|
29
|
-
content()
|
|
30
|
-
}.background(GeometryReader {
|
|
31
|
-
proxy in
|
|
32
|
-
Color.clear.onAppear {
|
|
33
|
-
self.contentSize = proxy.size.width
|
|
34
|
-
self.position = CGPoint(x: indicatorWidth / 2, y: INDICATOR_HEIGHT / 2)
|
|
35
|
-
}
|
|
36
|
-
Color.clear.preference(key: ViewOffsetKey.self,
|
|
37
|
-
value: -proxy.frame(in: .named("scroll")).origin.x)
|
|
38
|
-
|
|
39
|
-
})
|
|
40
|
-
.onPreferenceChange(ViewOffsetKey.self) {
|
|
41
|
-
let newPosition = $0 * ((indicatorContainerWidth - indicatorWidth) / (contentSize - scrollViewWidth)) + indicatorWidth / 2
|
|
42
|
-
if (newPosition > indicatorWidth / 2 && newPosition < indicatorContainerWidth - indicatorWidth / 2 + 1)
|
|
43
|
-
{
|
|
44
|
-
self.position = CGPoint(x: newPosition, y: INDICATOR_HEIGHT / 2)
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}.background(GeometryReader {
|
|
48
|
-
proxy in
|
|
49
|
-
Color.clear.onAppear {
|
|
50
|
-
self.scrollViewWidth = proxy.size.width
|
|
51
|
-
}
|
|
52
|
-
}).coordinateSpace(name: "scroll")
|
|
53
|
-
|
|
31
|
+
ScrollView(.horizontal, showsIndicators: false) {
|
|
54
32
|
HStack {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
.
|
|
33
|
+
content()
|
|
34
|
+
}
|
|
35
|
+
.fixedSize(horizontal: true, vertical: false)
|
|
36
|
+
.overlay(
|
|
37
|
+
GeometryReader { proxy in
|
|
38
|
+
Color.clear
|
|
39
|
+
.preference(
|
|
40
|
+
key: ViewOffsetKey.self,
|
|
41
|
+
value: -proxy.frame(in: .named("scroll")).origin.x
|
|
42
|
+
)
|
|
43
|
+
.preference(
|
|
44
|
+
key: ContentSizeKey.self,
|
|
45
|
+
value: proxy.size.width)
|
|
46
|
+
},
|
|
47
|
+
alignment: .topLeading
|
|
48
|
+
)
|
|
49
|
+
.onPreferenceChange(ContentSizeKey.self) { newContentSize in
|
|
50
|
+
if newContentSize > 0 {
|
|
51
|
+
self.contentSize = newContentSize
|
|
52
|
+
if self.position == CGPoint(x: 0, y: 2) {
|
|
53
|
+
self.position = CGPoint(x: indicatorWidth / 2, y: INDICATOR_HEIGHT / 2)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
.onPreferenceChange(ViewOffsetKey.self) { offset in
|
|
58
|
+
let newPosition =
|
|
59
|
+
(offset * ((indicatorContainerWidth - indicatorWidth) / (contentSize - scrollViewWidth)))
|
|
60
|
+
+ indicatorWidth / 2
|
|
61
|
+
|
|
62
|
+
if !newPosition.isNaN {
|
|
63
|
+
self.position = CGPoint(x: newPosition, y: INDICATOR_HEIGHT / 2)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}.background(
|
|
67
|
+
GeometryReader { proxy in
|
|
68
|
+
Color.clear.onAppear {
|
|
69
|
+
self.scrollViewWidth = proxy.size.width
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
).coordinateSpace(name: "scroll")
|
|
73
|
+
|
|
74
|
+
HStack(spacing: 0) {
|
|
75
|
+
HStack(spacing: 0) {}.frame(width: indicatorWidth, height: INDICATOR_HEIGHT)
|
|
76
|
+
.background(indicatorColor)
|
|
77
|
+
.cornerRadius(8)
|
|
78
|
+
.position(self.position)
|
|
79
|
+
}.frame(width: indicatorContainerWidth, height: INDICATOR_HEIGHT, alignment: .leading)
|
|
80
|
+
.background(indicatorContainerColor).cornerRadius(8)
|
|
61
81
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
82
|
}
|
|
66
|
-
|
|
67
83
|
}
|
|
68
84
|
|
|
69
85
|
// MARK: - ViewOffsetKey
|
|
70
86
|
|
|
71
87
|
struct ViewOffsetKey: PreferenceKey {
|
|
72
88
|
typealias Value = CGFloat
|
|
73
|
-
|
|
89
|
+
|
|
74
90
|
static var defaultValue = CGFloat.zero
|
|
75
|
-
|
|
91
|
+
|
|
76
92
|
static func reduce(value: inout Value, nextValue: () -> Value) {
|
|
77
93
|
value += nextValue()
|
|
78
94
|
}
|
|
79
95
|
}
|
|
96
|
+
|
|
97
|
+
// MARK: - ContentSizeKey
|
|
98
|
+
|
|
99
|
+
struct ContentSizeKey: PreferenceKey {
|
|
100
|
+
typealias Value = CGFloat
|
|
101
|
+
|
|
102
|
+
static var defaultValue = CGFloat.zero
|
|
103
|
+
|
|
104
|
+
static func reduce(value: inout Value, nextValue: () -> Value) {
|
|
105
|
+
value = nextValue()
|
|
106
|
+
}
|
|
107
|
+
}
|