SwiftUI--List View全攻略


SwiftUI的List View和UIKit中的UITableView很相似,它可以根据你的需求加载静态或者动态数据。不同的是,List使用起来更加的简单:我们不需要在storyboard或者Xib中创建cell,也不需要使用代码注册cell,不需要告诉它要有多少行内容,当然也不需要dequeue cell以及手动设置cell等等。

一、创建一个静态数据列表

想要创建一个静态数据列表,你首先需要确定每一个cell的样式。我们可以自定义一个简单的cell,代码如下:

struct StreetRow: View {
    
    var name: String
    
    var body: some View {
        Text("The street name is \(name)")
    }
}

这样我们就定义了一个简单的cell,cell上只有一行文字,现在可以创建一个List View,并添加你需要的数量的cell,像这样:

struct ListViewDemo: View {
    var body: some View {
        List{
            //当然可以有多种不同的Row哦
            StreetRow(name: "The Lodon Street")
            StreetRow(name: "The Joe's Street")
            StreetRow(name: "The House Street")
        }
    }
}
静态列表

这样就创建了一个最简单的列表,这里不得不说swiftUI确实是强大,短短几行代码就可以创建出UITableView需要书写大量代码才能看到的效果。

二、创建一个动态数据列表

如果想动态的生成items,比如根据接口返回的数据生成列表,就需要用到动态列表。按照UIKit中的习惯,首先我们需要一个model存储这些数据,SwiftUI也类似,我们需要创建一个Street的结构体,并遵循Identifiable协议,此协议中只有一个必须的属性:id,它用来让SwiftUI区分不同的item。

struct Street: Identifiable {
    var id = UUID()
    var name: String
}

这里我们给id初始化为UUID():

struct StreetRow: View {
    var street: Street
  
    var body: some View {
        Text("The street name is \(street.name)")
    }
}

最后在准备我们需要的数据,并让其动态加载到页面上,实际开发中往往是从接口返回的数据,这里准备了几条假数据来说明使用:

struct ListViewDemo: View {
    var body: some View {
        let street1 = Street(name: "The Lodon Street")
        let street2 = Street(name: "The Joe's Street")
        let street3 = Street(name: "The House Street")
        //数据数组
        let streets = [street1, street2, street3]
        
        return List(streets){ street in
            StreetRow(street: street)
        }
    }
}

SwiftUI会根据streets数组中的数据每次执行闭包创建cell,最终显示页面。其实针对这种情况下还有更简单的创建List的方式:

return List(streets, rowContent: StreetRow.init)

实际上List有很多的创建的方式,剩下的大家可以慢慢探索哦。

三、设置左滑删除cell

struct ListViewDemo: View {
    
    //数据数组
    @State private var streets = [Street(name: "The Lodon Street"), Street(name: "The Joe's Street"), Street(name: "The House Street")]
    
    var body: some View {
        
        func deleteRow(at offsets:IndexSet) {
            streets.remove(atOffsets:offsets)
        }
        
        return List{
            ForEach(streets, id: \.self) { street in
                StreetRow(street: street)
            }.onDelete(perform: deleteRow)
        }
    }
}

实现起来是不是很简单,但是需要注意的是:使用ForEach结构体,需要保证street遵守Hashable协议:

struct Street: Identifiable,Hashable {
    var id = UUID()
    var name: String
}
左滑删除cell

这里你可能会好奇,删除掉cell后数据是怎么同步并实时更新页面的,我们注意到数据源streets使用了@State修饰,这就是数据绑定,后面的章节会有专门的讲解哦。

四、List添加section分组以及设置grouped类型

struct ListViewDemo: View {
    var body: some View {
        return List{
            Section(header:Text("some streets one"), footer: Text("Fotter1")){
                TaskRow()
                TaskRow()
                TaskRow()
            }
            Section(header:Text("some streets two"), footer: Text("Fotter2")){
                TaskRow()
                TaskRow()
                TaskRow()
            }
        }
    }
}

struct TaskRow: View {
    var body: some View {
        Text("Task data goes here")
    }
}

和UITableView一样,你可以让数据分组显示,并为每一个section添加header和fotter,效果如下:


添加section

在UITableView中我们可以设置plain和grouped两种样式,而默认是plain样式,SwiftUI也一样。在swiftUI中设置grouped样式很简单,只需要为list添加相应的listStyle modifier:

struct ListViewDemo: View {
    var body: some View {
        return List{
            Section(header:Text("some streets one"), footer: Text("Fotter1")){
                TaskRow()
                TaskRow()
                TaskRow()
            }
            Section(header:Text("some streets two"), footer: Text("Fotter2")){
                TaskRow()
                TaskRow()
                TaskRow()
            }
        }.listStyle(GroupedListStyle())
    }
}

效果如下:


设置grouped样式

五、点击cell跳转的实现

首先需要新建一个详情页ListViewDetial,因为只是演示跳转,所以里面使用默认的代码。

struct ListViewDemo: View {
    var body: some View {
        let streets = [
        Street(name: "The Lodon Street"), 
        Street(name: "The Joe's Street"), 
        Street(name: "The House Street")
        ]
        
        return NavigationView{
            List(streets){ street in
                NavigationLink(destination:ListViewDetial()){
                    StreetRow(street: street)
                }
            }.navigationBarTitle("Streets")
        }
    }
}

实现跳转的重点是:List包裹在NavigationView中,并且cell也需要包裹进NavigationLink中,并设置destination属性,其他的和上面介绍的没有区别。

好了,本篇文章介绍了swiftUI中List的创建,使用,设置以及点击跳转,基本包含了List的日常使用。每天进步一点点,成为更好的自己!有问题欢迎留言交流,欢迎关注!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,487评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,621评论 2 374
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,611评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,659评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,509评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,380评论 1 274
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,799评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,443评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,739评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,781评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,554评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,400评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,811评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,043评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,330评论 1 253
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,775评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,978评论 2 337