SwiftUI:带动画条的步进器
我想创建一个带有动画条的步进器组件。以下是我得到的结果: 其想法是,该条应始终居中,而且我希望在值更改时设置蓝色条的动画,但我无法使其工作 这是我的密码:SwiftUI:带动画条的步进器,swiftui,stepper,uistepper,Swiftui,Stepper,Uistepper,我想创建一个带有动画条的步进器组件。以下是我得到的结果: 其想法是,该条应始终居中,而且我希望在值更改时设置蓝色条的动画,但我无法使其工作 这是我的密码: struct Stepper: View { @Binding var currentIndex: Int var total: Int var body: some View { ZStack(alignment: .center) { ZStack(alignme
struct Stepper: View {
@Binding var currentIndex: Int
var total: Int
var body: some View {
ZStack(alignment: .center) {
ZStack(alignment: .leading) {
Color.gray.opacity(0.4)
Color.blue
.frame(width: 175.5 / CGFloat(total) * CGFloat(currentIndex))
}
.frame(width: 175.5, height: 2)
Text("\(currentIndex)")
.foregroundColor(.black)
.offset(x: -113)
Text("\(total)")
.foregroundColor(.black)
.offset(x: 113)
}
.frame(width: .infinity, height: 18)
}
init(withTotal total: Int,
andCurrentIndex currentIndex: Binding<Int>) {
self._currentIndex = currentIndex
self.total = total
}
func update(to value: Int) {
guard value >= 0, value <= total else {
return
}
withAnimation {
currentIndex = value
}
}
}
你能帮我理解为什么动画不起作用吗?
还有,有没有更好的方法来布局UI
谢谢大家! 最简单的解决方案是在
带动画的块中更改currentIndex
,如下所示:
Button(action: {
withAnimation {
currentIndex += 1
}
}, label: {
Text("INCREMENT")
})
这里是固定的步进器(使用Xcode 12.1/iOS 14.1测试)
struct步进器:视图{
@绑定变量currentIndex:Int
变量总计:Int
var body:一些观点{
ZStack(对齐:。中心){
ZStack(对齐:。引导){
颜色。灰色。不透明度(0.4)
蓝色
.框架(宽度:175.5/CGFloat(总计)*CGFloat(当前指数))
}
.框架(宽度:175.5,高度:2)
.animation(.default,value:currentIndex)/这里是固定的以步进器为中心的动画对齐方式。还添加了增量-减量值的验证。您现在可以在不使用更新函数的情况下以自己的方式使用它。目前,在您的代码中,这一行出现一条警告,这也得到了解决
.frame(width: .infinity, height: 18)
最终代码:
struct Stepper: View {
@Binding var currentIndex: Int
private var total: Int
private var mainIndex: Int {
if currentIndex >= 0 && currentIndex <= total {
return currentIndex
} else if currentIndex < 0 {
DispatchQueue.main.async {
self.currentIndex = 0
}
return 0
} else {
DispatchQueue.main.async {
self.currentIndex = total
}
return total
}
}
var body: some View {
GeometryReader { geometry in
HStack() {
Text("\(mainIndex)")
.foregroundColor(.black)
.frame(width: 30)
ZStack(alignment: .leading) {
Color.gray.opacity(0.4).frame(width: geometry.size.width - 60)
Color.blue.frame(width: (geometry.size.width - 60) / CGFloat(total) * CGFloat(mainIndex))
}
.animation(.default, value: mainIndex)
.frame(width: geometry.size.width - 60, height: 2)
Text("\(total)")
.foregroundColor(.black)
.frame(width: 30)
}
.frame(width: geometry.size.width, height: geometry.size.height)
.background(Color.yellow)
}
}
init(withTotal total: Int,
andCurrentIndex currentIndex: Binding<Int>) {
self._currentIndex = currentIndex
self.total = total
}
func update(to value: Int) {
guard value >= 0, value <= total else {
return
}
withAnimation {
currentIndex = value
}
}
}
struct StepperVC: View {
@State private var currentIndex: Int = 1
var body: some View {
VStack( alignment: .center,spacing: 32) {
Stepper(withTotal: 8, andCurrentIndex: $currentIndex)
.frame(width: UIScreen.main.bounds.size.width - 50, height: 50, alignment: .center)
Button(action: {
currentIndex += 1
}, label: {
Text("INCREMENT")
})
Button(action: {
currentIndex -= 1
}, label: {
Text("DECREMENT")
})
}
}
}
struct步进器:视图{
@绑定变量currentIndex:Int
私人变量总计:Int
私有索引:Int{
如果currentIndex>=0&¤tIndex=0,则为
.frame(width: .infinity, height: 18)
struct Stepper: View {
@Binding var currentIndex: Int
private var total: Int
private var mainIndex: Int {
if currentIndex >= 0 && currentIndex <= total {
return currentIndex
} else if currentIndex < 0 {
DispatchQueue.main.async {
self.currentIndex = 0
}
return 0
} else {
DispatchQueue.main.async {
self.currentIndex = total
}
return total
}
}
var body: some View {
GeometryReader { geometry in
HStack() {
Text("\(mainIndex)")
.foregroundColor(.black)
.frame(width: 30)
ZStack(alignment: .leading) {
Color.gray.opacity(0.4).frame(width: geometry.size.width - 60)
Color.blue.frame(width: (geometry.size.width - 60) / CGFloat(total) * CGFloat(mainIndex))
}
.animation(.default, value: mainIndex)
.frame(width: geometry.size.width - 60, height: 2)
Text("\(total)")
.foregroundColor(.black)
.frame(width: 30)
}
.frame(width: geometry.size.width, height: geometry.size.height)
.background(Color.yellow)
}
}
init(withTotal total: Int,
andCurrentIndex currentIndex: Binding<Int>) {
self._currentIndex = currentIndex
self.total = total
}
func update(to value: Int) {
guard value >= 0, value <= total else {
return
}
withAnimation {
currentIndex = value
}
}
}
struct StepperVC: View {
@State private var currentIndex: Int = 1
var body: some View {
VStack( alignment: .center,spacing: 32) {
Stepper(withTotal: 8, andCurrentIndex: $currentIndex)
.frame(width: UIScreen.main.bounds.size.width - 50, height: 50, alignment: .center)
Button(action: {
currentIndex += 1
}, label: {
Text("INCREMENT")
})
Button(action: {
currentIndex -= 1
}, label: {
Text("DECREMENT")
})
}
}
}