LazyVStack具有每次进入屏幕调用onAppear,离开屏幕调用onDisappear的功能,意味为将LazyVStack放到ScrollView以后,只要用户滚动视图就可以一直触发功能代码。
我们可以利用LazyVStack的这2个特性制作一个无限联动的分类菜单。这也是目前我使用的最成熟的一种方案了,经过暴力测试,完全符合我的预期需求。推荐大家使用。
1、首先我们要定义2个临时的外部状态变量:
@State var ScrollVal = "" //当前的分类默认为空
@State var setTypes = Set()//存放分类的集合
2、将视图分为2栏
var body: some View{
ScrollViewReader { scrollProxy in//锚点跳转雷达
HStack(spacing:0){
//左侧遍历的所“顶级分类”点击scrollTo
ScrollView(.vertical, showsIndicators: false){
VStack(spacing:0){
ForEach(catData.cates){ cat in //遍历左侧显示的主分类
catScrollTo(categorie:cat, scrollProxy: scrollProxy)
.id(cat.type)//用type字段做为锚点,联动跳转的关键
}
}
}.frame(width: 110)//左侧宽度根据自己的情况调整
Divider()//分栏线
ScrollView(.vertical,showsIndicators: false){
LazyVStack{
ForEach(catData.cates){ cat in //遍历右边显示的主分类下的子分类内容
typeView(cat: cat.children, type: cat.type)
.id(cat.typename)//使用名称做为锚点,联动跳转的到指定位置
}
}
}
}
}.animation(.spring(), value: ScrollVal)//统一使用这个动画效果
}
3、左侧主分类展示的子视图
func catScrollTo(categorie:FoodTypeModel,scrollProxy:ScrollViewProxy) -> some View{
VStack(spacing:0){
Text(categorie.typename)
.modifier(CatScrollStyle(isIDEqual: ScrollVal == categorie.type))
.onTapGesture{
scrollProxy.scrollTo(categorie.typename,anchor: .top) //点击后将右边对应锚点的顶部
}
}
}
我们还有一个分类展示的modifier,传入一个布尔值,当被选中或者滚动到对应位置时显示不同的样式。
//分类样式
private struct CatScrollStyle: ViewModifier{
let isIDEqual:Bool
func body(content: Content) -> some View {
ZStack{
if isIDEqual{ Color.gray.opacity(0.1).overlay(Color.red.opacity(0.8).frame(width:3), alignment: .leading) }
content.foregroundColor(isIDEqual ? .red : .black.opacity(0.8)).padding(18)
}
}
}
4、右侧分类里的子分类内容视图
//Type 顶组分类的的内容视图
func typeView(cat:[FoodTypeModel.Child],type:String)-> some View{
ForEach(cat){ subCat in//遍历“顶级分类”下的“所有子分类”
Text(subCat.name).padding(20)
}
.onAppear{
setTypes.insert(type)//显示时将此项加入到集合里
DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) { //防止动画惯性(跑多了,又回来1步)
if let inType = setTypes.first, inType != ScrollVal{
ScrollVal = type //利用LazyVStack的特性设置当前显示的type值
}
}
}
.onDisappear{
setTypes.remove(type)//消失时从集合里删除此项
if let inType = setTypes.first, inType != type{
ScrollVal = inType //将type从集合删除后从集合里取出1个做为默认值
}
}
}
注意理解最后的 onAppear与onDisappear 这是滚动触发左侧样式联动的关键。
点击左侧的时候,右侧内容会滚动到相对应的位置,当右侧滚动到对应位置的时候,左也会联动改变样式。
如果你还需要参考更多的实现可以在这里查看:http://www.55mx.com/ios/169.html
除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:https://www.55mx.com/post/178
《【SwiftUI实战】利用LazyVStack的onAppear与onDisappear特性制作无限联动分类》的网友评论(1)