admin管理员组文章数量:1355661
I want to use 2 scrollView. One on top of the other. The one below can push over the one above. Here is what i currently have:
Blue rectangle - is an item in scrollView which I can scroll. Bottom(631, Description, Lorem) - is another scrollView, which can be scroll to top. I am using offset to put it bottom, but I cannot seem to get the my bottom ScrollView to slide over the blue rectangle view.
What I want to achieve: Bottom scrollView goes over top scrollView. You can see this behavior in telegram if you open a post with a picture.
Some code to touch:
import SwiftUI
struct ScrollOffsetPreferenceKey: PreferenceKey {
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
struct ScrollmainView: View {
@State private var scrollOffset = CGFloat(0)
@State private var offSetOnStart: CGFloat = 0
// MARK: - UI
@ViewBuilder
var body: some View {
let screenBounds = UIScreen.main.bounds
ZStack(alignment: .top) {
ScrollView(.horizontal) {
LazyHStack {
Rectangle()
.foregroundColor(.cyan)
.frame(width: UIScreen.main.bounds.width - 32, height: 400)
}
.padding(.horizontal, 16)
}
.background(Color.red)
.overlay {
scrollBody.padding(.top, -200)
}
}
.ignoresSafeArea(.all, edges: [.top, .bottom])
}
@ViewBuilder
private var scrollBody: some View {
let size = UIScreen.main.bounds
ScrollView {
LazyVStack {
ZStack(alignment: .top) {
scrollContentBody
GeometryReader { proxy in
let offset = proxy.frame(in: .named("scroll")).minY
Text("\(offset)")
Color.clear.preference(key: ScrollOffsetPreferenceKey.self, value: offset)
}
}
Color.clear
.frame(width: size.width,
height: UIApplication.shared.keyWindow?.safeAreaInsets.bottom)
}
}
.offset(y: 700)
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
scrollOffset = value
print("offset: \(value)")
guard offSetOnStart != 0 && scrollOffset > 0 && scrollOffset < 631
else {
offSetOnStart = 700
return
}
offSetOnStart = scrollOffset
}
}
private var scrollContentBody: some View {
LazyVStack(spacing: 0) {
EntryScrollHeader()
Color.green.opacity(0.5)
.frame(height: 600)
}
}
}
struct EntryScrollHeader: View {
var body: some View {
VStack(spacing: 0) {
HStack {
VStack {
Text("Description")
}
Spacer()
Button {
} label: {
Image(systemName: "bookmark")
.foregroundColor(.black.opacity(0.25))
.font(.system(size: 25, weight: .regular, design: .default))
}
}
.padding(.bottom, 4)
HStack {
VStack {
Text("Lorem")
Text("Ipsum")
}
Spacer()
}
}
.frame(height: 76)
.padding([.leading, .trailing], 15)
.padding(.top, 12)
.background(Color.white)
}
}
I want to use 2 scrollView. One on top of the other. The one below can push over the one above. Here is what i currently have:
Blue rectangle - is an item in scrollView which I can scroll. Bottom(631, Description, Lorem) - is another scrollView, which can be scroll to top. I am using offset to put it bottom, but I cannot seem to get the my bottom ScrollView to slide over the blue rectangle view.
What I want to achieve: Bottom scrollView goes over top scrollView. You can see this behavior in telegram if you open a post with a picture.
Some code to touch:
import SwiftUI
struct ScrollOffsetPreferenceKey: PreferenceKey {
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
struct ScrollmainView: View {
@State private var scrollOffset = CGFloat(0)
@State private var offSetOnStart: CGFloat = 0
// MARK: - UI
@ViewBuilder
var body: some View {
let screenBounds = UIScreen.main.bounds
ZStack(alignment: .top) {
ScrollView(.horizontal) {
LazyHStack {
Rectangle()
.foregroundColor(.cyan)
.frame(width: UIScreen.main.bounds.width - 32, height: 400)
}
.padding(.horizontal, 16)
}
.background(Color.red)
.overlay {
scrollBody.padding(.top, -200)
}
}
.ignoresSafeArea(.all, edges: [.top, .bottom])
}
@ViewBuilder
private var scrollBody: some View {
let size = UIScreen.main.bounds
ScrollView {
LazyVStack {
ZStack(alignment: .top) {
scrollContentBody
GeometryReader { proxy in
let offset = proxy.frame(in: .named("scroll")).minY
Text("\(offset)")
Color.clear.preference(key: ScrollOffsetPreferenceKey.self, value: offset)
}
}
Color.clear
.frame(width: size.width,
height: UIApplication.shared.keyWindow?.safeAreaInsets.bottom)
}
}
.offset(y: 700)
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { value in
scrollOffset = value
print("offset: \(value)")
guard offSetOnStart != 0 && scrollOffset > 0 && scrollOffset < 631
else {
offSetOnStart = 700
return
}
offSetOnStart = scrollOffset
}
}
private var scrollContentBody: some View {
LazyVStack(spacing: 0) {
EntryScrollHeader()
Color.green.opacity(0.5)
.frame(height: 600)
}
}
}
struct EntryScrollHeader: View {
var body: some View {
VStack(spacing: 0) {
HStack {
VStack {
Text("Description")
}
Spacer()
Button {
} label: {
Image(systemName: "bookmark")
.foregroundColor(.black.opacity(0.25))
.font(.system(size: 25, weight: .regular, design: .default))
}
}
.padding(.bottom, 4)
HStack {
VStack {
Text("Lorem")
Text("Ipsum")
}
Spacer()
}
}
.frame(height: 76)
.padding([.leading, .trailing], 15)
.padding(.top, 12)
.background(Color.white)
}
}
Share
Improve this question
edited Mar 28 at 6:57
Dmitriy Greh
asked Mar 28 at 6:05
Dmitriy Greh Dmitriy Greh
6968 silver badges18 bronze badges
1 Answer
Reset to default 1If I understand correctly, what you're trying to achieve is to have one row in the scroll view (outer scroll view), that is itself a scroll view (inner scroll view).
If so, you need to limit height of this inner scroll view.
A solution may look like this:
ScrollView(.vertical) {
LazyVStack {
ScrollView(.horizontal) {
YourHorizontallyScrollableContent()
}
.frame(height: 200)
YourVerticallyScrollableContent()
}
}
UPDATE:
I misunderstood your question, so here's the proper solution
import SwiftUI
struct ContentView: View {
@State
private var contentOffset: CGFloat = .zero
var body: some View {
ObservableScrollView(
contentOffset: $contentOffset
) {
VStack(spacing: 0) {
StaticContent()
.offset(y: -contentOffset)
.zIndex(1)
ScrollableContent()
.zIndex(2)
}
}
}
}
struct StaticContent: View {
var body: some View {
VStack {
Button("Press") {
print("Pressed")
}
.buttonStyle(.borderedProminent)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.aspectRatio(1, contentMode: .fit)
.background(Color.cyan)
}
}
struct ScrollableContent: View {
var body: some View {
VStack(spacing: 32) {
Color.purple.frame(height: 50)
Text("Scrollable content")
Button("Action") {
print("Actioned")
}
.buttonStyle(.borderedProminent)
Spacer()
}
.frame(maxWidth: .infinity)
.frame(height: 2000)
.background(.green)
}
}
The idea is to apply a negative content offset to whatever view you need to be static on the screen. ObservableScrollView
is a custom implementation of a scroll view that reports it's content offset (taken from this article)
本文标签: ios2 ScrollView issue in SwiftUIStack Overflow
版权声明:本文标题:ios - 2 ScrollView issue in SwiftUI - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744053579a2582809.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论