SwiftUI - 带列表的可拖动幻灯片
SwiftUI - Draggable Slides with List
我有点难以构建包含列表的可拖动幻灯片。受到 的启发,下面是我所拥有的 MRE。
import SwiftUI
struct ContentView: View {
static let kMinHeight: CGFloat = 100.0
@State var currentHeight: CGFloat = kMinHeight // << any initial
var body: some View {
GeometryReader { g in // << for top container height limit
ZStack(alignment: .bottom) {
Rectangle().fill(Color.yellow) // << just for demo
self.card()
.gesture(DragGesture()
.onChanged { value in
// as card is at bottom the offset is reversed
let newHeight = self.currentHeight - (value.location.y - value.startLocation.y)
if newHeight > Self.kMinHeight && newHeight < g.size.height {
self.currentHeight = newHeight
}
})
}
}
}
func card() -> some View {
ZStack(alignment: .top){
RoundedRectangle(cornerRadius: 16.0)
.frame(height:currentHeight)
VStack{
RoundedRectangle(cornerRadius: Constants.radius)
.fill(Color.white)
.frame(
width: Constants.indicatorWidth,
height: Constants.indicatorHeight
)
Text("Card")
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
.multilineTextAlignment(.center)
.padding(.top)
Text("LINE 2")
.foregroundColor(Color.white)
// Uncomment the following lines, and the slides becomes unusable
// List {
// Text("The Fellowship of the Ring")
// Text("The Two Towers")
// Text("The Return of the King")
//}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
使用此示例制作的幻灯片有效,但请注意,我注释掉了几行包含列表的内容。取消注释这些行后,滑块将无法使用。
两个明显的问题:(1) 为什么会这样,以及 (2) 关于如何解决它的任何建议? :)
您遇到的问题是 List
是一个贪婪的观点。它占据了它可能占据的所有 space,这让你的身高变得不正常。简单的解决方案是将它放在一个框架中,当卡片一直向下时该框架为零。既然我们有了这些值,我们需要做的就是:
List {
Text("The Fellowship of the Ring")
Text("The Two Towers")
Text("The Return of the King")
}
.frame(height: currentHeight - DraggableSlides.kMinHeight)
在您的代码中,您仅指定卡片内矩形的高度。如果只有矩形存在,这不是问题。但是:
这里的问题是 List
包装了自己的滚动行为,因此它会扩展以占用所有它可以占用的 space 。不要只限制卡内的矩形,而是将卡的高度限制为 currentHeight
:
func card() -> some View {
ZStack(alignment: .top){
RoundedRectangle(cornerRadius: 16.0)
VStack{
RoundedRectangle(cornerRadius: 10)
.fill(Color.white)
.frame(
width: 20,
height: 20
)
Text("Card")
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
.multilineTextAlignment(.center)
.padding(.top)
Text("LINE 2")
.foregroundColor(Color.white)
// Uncomment the following lines, and the slides becomes unusable
List {
Text("The Fellowship of the Ring")
Text("The Two Towers")
Text("The Return of the King")
}
}
}
.frame(maxHeight: currentHeight) // This line
}
我有点难以构建包含列表的可拖动幻灯片。受到
import SwiftUI
struct ContentView: View {
static let kMinHeight: CGFloat = 100.0
@State var currentHeight: CGFloat = kMinHeight // << any initial
var body: some View {
GeometryReader { g in // << for top container height limit
ZStack(alignment: .bottom) {
Rectangle().fill(Color.yellow) // << just for demo
self.card()
.gesture(DragGesture()
.onChanged { value in
// as card is at bottom the offset is reversed
let newHeight = self.currentHeight - (value.location.y - value.startLocation.y)
if newHeight > Self.kMinHeight && newHeight < g.size.height {
self.currentHeight = newHeight
}
})
}
}
}
func card() -> some View {
ZStack(alignment: .top){
RoundedRectangle(cornerRadius: 16.0)
.frame(height:currentHeight)
VStack{
RoundedRectangle(cornerRadius: Constants.radius)
.fill(Color.white)
.frame(
width: Constants.indicatorWidth,
height: Constants.indicatorHeight
)
Text("Card")
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
.multilineTextAlignment(.center)
.padding(.top)
Text("LINE 2")
.foregroundColor(Color.white)
// Uncomment the following lines, and the slides becomes unusable
// List {
// Text("The Fellowship of the Ring")
// Text("The Two Towers")
// Text("The Return of the King")
//}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
使用此示例制作的幻灯片有效,但请注意,我注释掉了几行包含列表的内容。取消注释这些行后,滑块将无法使用。
两个明显的问题:(1) 为什么会这样,以及 (2) 关于如何解决它的任何建议? :)
您遇到的问题是 List
是一个贪婪的观点。它占据了它可能占据的所有 space,这让你的身高变得不正常。简单的解决方案是将它放在一个框架中,当卡片一直向下时该框架为零。既然我们有了这些值,我们需要做的就是:
List {
Text("The Fellowship of the Ring")
Text("The Two Towers")
Text("The Return of the King")
}
.frame(height: currentHeight - DraggableSlides.kMinHeight)
在您的代码中,您仅指定卡片内矩形的高度。如果只有矩形存在,这不是问题。但是:
这里的问题是 List
包装了自己的滚动行为,因此它会扩展以占用所有它可以占用的 space 。不要只限制卡内的矩形,而是将卡的高度限制为 currentHeight
:
func card() -> some View {
ZStack(alignment: .top){
RoundedRectangle(cornerRadius: 16.0)
VStack{
RoundedRectangle(cornerRadius: 10)
.fill(Color.white)
.frame(
width: 20,
height: 20
)
Text("Card")
.font(.title)
.fontWeight(.bold)
.foregroundColor(Color.white)
.multilineTextAlignment(.center)
.padding(.top)
Text("LINE 2")
.foregroundColor(Color.white)
// Uncomment the following lines, and the slides becomes unusable
List {
Text("The Fellowship of the Ring")
Text("The Two Towers")
Text("The Return of the King")
}
}
}
.frame(maxHeight: currentHeight) // This line
}