Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios SwiftUI可滚动选项卡栏通过项目设置动画错误_Ios_Swift_Xcode_Swiftui - Fatal编程技术网

Ios SwiftUI可滚动选项卡栏通过项目设置动画错误

Ios SwiftUI可滚动选项卡栏通过项目设置动画错误,ios,swift,xcode,swiftui,Ios,Swift,Xcode,Swiftui,我通过可滚动的选项卡栏项目构建了pageView。如果用户滚动“不是那么快”,效果非常好,但是如果用户滚动项目的速度非常快,视图浮动并且行为非常奇怪,则会出现问题,动画似乎无法跟随用户交互 我想知道,如果有人有解决方案,仍然有流体动画独立如何用户快速滚动 ContentView struct ContentView: View { @State private var selection = 1 //selected page let dataModel = ["Forums"

我通过可滚动的选项卡栏项目构建了pageView。如果用户滚动“不是那么快”,效果非常好,但是如果用户滚动项目的速度非常快,视图浮动并且行为非常奇怪,则会出现问题,动画似乎无法跟随用户交互

我想知道,如果有人有解决方案,仍然有流体动画独立如何用户快速滚动

ContentView

struct ContentView: View {
@State private var selection = 1 //selected page
let dataModel = ["Forums", "Learn", "Careers", "Store", "About"]
var body: some View {
    NavigationView {
        VStack {
            //ScrollableTabView
            ScrollView(.horizontal, showsIndicators: false, content: {
                ScrollViewReader { scrollReader in
                    ScrollableTabView(activeIdx: $selection,dataSet: dataModel)
                        .padding(.top).onChange(of: selection, perform: { value in
                            withAnimation{
                                scrollReader.scrollTo(value, anchor: .center)
                            }
                        })
                }
            })
            .background(Color(UIColor.secondarySystemFill))
            //Page View
            LazyHStack {
                PageView(selection: $selection, dataModel: dataModel)
            }
        }
        .navigationBarTitle("Demo", displayMode: .inline)
    }.onChange(of: selection, perform: { value in
        //update tab
    })
}
} 
分页

struct PageView: View {
@Binding var selection: Int
let dataModel: [String]
var body: some View {
    TabView(selection:$selection) {
        ForEach(0..<dataModel.count) { i in
            VStack {
                HStack {
                Text(dataModel[i])
                    .foregroundColor(Color.primary)
                    .padding()
                 Spacer()
                }
                Spacer()
            }.tag(i)
        }
    }
    .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - 170)
    //give padding nav height + scrollable Tab
    .tabViewStyle(PageTabViewStyle.init(indexDisplayMode: .never))

}
}
struct页面视图:视图{
@绑定变量选择:Int
let dataModel:[字符串]
var body:一些观点{
选项卡视图(选择:$selection){
ForEach(0..CGFloat{
返回d[前导]
}
}
静态let underlineLeading=水平对齐(underlineLeading.self)
}
结构宽度首选项键:首选项键{
静态var defaultValue=CGFloat(0)
静态函数reduce(值:inout CGFloat,nextValue:()->CGFloat){
value=nextValue()
}
typealias值=CGFloat
}
结构ScrollableTabView:视图{
@绑定变量activeIdx:Int
@国有-私有var w:[CGFloat]
私有let数据集:[字符串]
初始化(activeIdx:绑定,数据集:[字符串]){
self.\u activeIdx=activeIdx
self.dataSet=dataSet
_w=State.init(initialValue:[CGFloat](重复:0,计数:dataSet.count))
}
var body:一些观点{
VStack(对齐:。下划线删除){
HStack{
ForEach(0..some视图{
团体{
如果activeIdx==idx{
content.alignmentGuide(.underlineEleding){d在中
返回d[前导]
}.ontapsigne{
动画片{
self.activeIdx=self.idx
}
}
}否则{
content.ontaps{
动画片{
self.activeIdx=self.idx
}
}
}
}
}
}
结构内容视图\u预览:PreviewProvider{
静态var预览:一些视图{
ContentView()
}
}
    extension HorizontalAlignment {
private enum UnderlineLeading: AlignmentID {
    static func defaultValue(in d: ViewDimensions) -> CGFloat {
        return d[.leading]
    }
}

static let underlineLeading = HorizontalAlignment(UnderlineLeading.self)
}

struct WidthPreferenceKey: PreferenceKey {
static var defaultValue = CGFloat(0)

static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
    value = nextValue()
}

typealias Value = CGFloat
}


struct ScrollableTabView : View {

@Binding var activeIdx: Int
@State private var w: [CGFloat]
private let dataSet: [String]
init(activeIdx: Binding<Int>, dataSet: [String]) {
    self._activeIdx = activeIdx
    self.dataSet = dataSet
    _w = State.init(initialValue: [CGFloat](repeating: 0, count: dataSet.count))
        
}

var body: some View {
    VStack(alignment: .underlineLeading) {
        HStack {
            ForEach(0..<dataSet.count) { i in
                Text(dataSet[i])
                    .font(Font.title2.bold())
                    .modifier(ScrollableTabViewModifier(activeIdx: $activeIdx, idx: i))
                    .background(TextGeometry())
                    .onPreferenceChange(WidthPreferenceKey.self, perform: { self.w[i] = $0 })
                    .id(i)
                Spacer().frame(width: 20)
            }
        }
        .padding(.horizontal, 5)
        Rectangle()
            .alignmentGuide(.underlineLeading) { d in d[.leading]  }
            .frame(width: w[activeIdx],  height: 4)
            .animation(.linear)
    }
}
}

struct TextGeometry: View {
var body: some View {
    GeometryReader { geometry in
        return Rectangle().fill(Color.clear).preference(key: WidthPreferenceKey.self, value: geometry.size.width)
    }
}
}

struct ScrollableTabViewModifier: ViewModifier {
@Binding var activeIdx: Int
let idx: Int

func body(content: Content) -> some View {
    Group {
        if activeIdx == idx {
            content.alignmentGuide(.underlineLeading) { d in
                return d[.leading]
            }.onTapGesture {
                withAnimation{
                    self.activeIdx = self.idx
                }
            }

        } else {
            content.onTapGesture {
                withAnimation{
                    self.activeIdx = self.idx
                }
            }
        }
    }
}
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}