Swift UI 完全开发(8)List列表

Swift UI 完全开发(8)List列表

强烈安利有条件的朋友,去京东搜索购买《Swift UI 完全开发》原书,原作者由浅入深,字字珠玑,从真实开发角度介绍了SwiftUI的使用,完整阅读带来的裨益与收获远胜于草草的读完浓缩版博客,个人安利。

本章节将介绍List列表控件的基础用法,其次为了优化性能使用结构化编程的方式,实现数据抽离,样式结构抽离,通过定义数据模型Model和创建视图组件的方式大大减少代码量。学习List列表自带的编辑功能,实现拖动排序、滑动删除操作。最后学习List`列表中常用的修饰符

从(6)开始,将不再按照原书顺序介绍,只提供本人阅读后浓缩后代码,并对代码进行逐行解释。

对应《Swift UI 完全开发》原书第8章

  • 第一章 第一个SwiftUI项目
  • 第二章 Text文字使用
  • 第三章 Image图片使用
  • 第四章 Stack布局容器使用
  • 第五章 Swift语法入门
  • 第六章 Button按钮使用
  • 第七章 文本输入框使用
  • 第八章 List列表

P.S. 文章内容为个人阅读后认为的重点,顺序与原书存在不一致。有任何疑问欢迎评论。

8.1 简单列表创建

  1. 创建一个新的SwiftUI View,命名为“SwiftUIList”
  2. 将数据内容定义为数组sentences,使用List列表遍历sentences数组中的内容。
  3. 下方代码中,使用List列表和ForEach循环的方式遍历sentences数组中的内容。ForEach使用索引遍历sentences数组,对于每个索引用作每个文本视图的唯一标志符。
    • ForEach循环的用法类似于for...in...的逻辑,从sentences数组取出一个个数后,通过Text文字根据索引位置item展示sentences数组的句子。
struct SwiftUIList: View {
    
    var sentences:[String] = ["item1", "item2", "item3", "item4"]
    
    var body: some View {
        List{
            ForEach(sentences.indices, id: \.self){
                item in
                Text(sentences[item])
            }
        }
    }
}

image-20240503180142582

###7.2 数据模型展示列表数据

如果List列表中需要创建既包含图片有包含文字的数组呢?

可以通过创建结构体参数类型的方式来实现。

  1. 新增一个文件夹,命名为“Model”,在创建一个Swift文件,命名为“SentencesModel”。

  2. 创建所需结构体,struct SentencesModel: 定义了一个名为SentencesModel的结构体。: Identifiable: 表示SentencesModel结构体遵循了Identifiable协议。var id: UUID = UUID(): 在SentencesModel结构体内部定义了一个id属性,其类型为UUID(通用唯一标识符)。这个属性在初始化时会被自动赋予一个新的、随机的UUID值。var image: String: 定义了一个String类型的image属性,用于存储图片的URL、文件名或其他与图片相关的标识符。var text: String: 定义了一个String类型的text属性,用于存储一段文本或句子。使用这个结构体时,你可以创建多个SentencesModel的实例,并为它们的imagetext属性分配不同的值。由于id属性在初始化时会自动分配一个唯一的UUID,因此每个实例都会有一个唯一的标识符。这在处理列表数据(如SwiftUI中的列表)时特别有用,因为你可以使用这些标识符来追踪和识别列表中的每个数据项。

    struct SentencesModel: Identifiable{
        var id: UUID = UUID()
        var image: String
        var text: String
    }
    

    image-20240504112850054

  3. 在Assets资源库中,创建一个名为“IconImage”的文件夹,然后导入一批社交账号的图片作为演示素材。

    image-20240504113351016

  4. 回到“SentenceModel”文件中声明一个符合“SentencesModel”结构体的数组定义数据集。

    var Sentences:[SentencesModel] = [
        SentencesModel(image:"icon_qq", text:"qq"),
        SentencesModel(image:"icon_wx", text:"微信"),
        SentencesModel(image:"icon_wb", text:"微博"),
    ]
    

    image-20240504113624635

  5. 使用数据模型展示数据。回到SwiftUIList文件中,将之前声明的数组替换成数据模型中声明好的数组。下方代码中,我们替换了ForEach循环中的sentences,然后在内容部分使用HStack横向布局容器对Image图片和Text文字进行布局。并给整个HStack横向布局容器增加了边距。

    struct SwiftUIList: View {
        
        var sentences:[SentencesModel] = Sentences
        
        var body: some View {
            List{
                ForEach(sentences){
                    item in
                    HStack(spacing: 20){
                        Image(item.image)
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 32)
                            .clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)
                            .overlay(
                                Circle()
                                    .stroke(Color(.systemGray5), lineWidth:1))
                        Text(item.text)
                    }
                    .padding(.all,5)
                }
            }
        }
    }
    

    image-20240504113829234

  6. 抽离出单独的视图构件。对展示内容进行抽离,搭建一个新的结构体ListItem。通过声明参数并设计样式,形成一个ImageText的组合组件。然后到SwiftUILitst视图中进行调用,并通过传入赋值的方式,与List列表和ForEach遍历Sentences数据中的数据,最后得到我们想要的视图效果。

    struct SwiftUIList: View {
        
        var sentences:[SentencesModel] = Sentences
        
        var body: some View {
            List{
                ForEach(sentences){item in
                    ListItem(image: item.image, text: item.text)
                }
            }
        }
    }
    
    //列表组件
    struct ListItem:View{
        var image: String
        var text: String
        
        var body: some View{
            HStack(spacing: 20){
                Image(image)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 32)
                    .clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)
                    .overlay(
                        Circle()
                            .stroke(Color(.systemGray5), lineWidth:1))
                Text(text)
            }
            .padding(.all,5)
        }
    }
    

    image-20240504114842231

8.2 List列表拖动排序和滑动删除

  1. 添加顶部导航栏。使用Navigation View顶部导航栏。下方代码使用“.navigationBarTile()“导航栏标题修饰符给List列表视图增加了一个标题,标题名为“账号中心”,展示方式为居中对齐。值得注意的是,“.navigationBarTitle()“导航栏标题修饰符需要修饰在视图内容上,而不是修饰Navigation View导航视图。

     NavigationView{
                List{
                    ForEach(sentences){item in
                        ListItem(image: item.image, text: item.text)
                    }
                }
                .navigationBarTitle("账号中心", displayMode: .inline)
            }
    

    image-20240504121022417

  2. 添加编辑按钮。SwfitUI 在 List 列表控件控件上封装了一个名为EditButton的按钮,用来快速对列表进行编辑操作,我们将 EditButton 添加到导航视图上。如下方代码:

       NavigationView{
                List{
                    ForEach(sentences){item in
                        ListItem(image: item.image, text: item.text)
                    }
                }
                .navigationBarTitle("账号中心", displayMode: .inline)
                .navigationBarItems(trailing: EditButton())
            }
    

    image-20240504123018988

  3. 实现拖动排序方法和滑动删除方法。SwiftUI 提供了排序和滑动删除两种常用操作。下方代码中,我们创建了一个拖动排序的方法 moveItem 。方法中接收单一的 IndexSet 类型的参数,用来定位当前要排序的列的位置,也就拖动时,系统知道了你正在操作的是那条数据。在拖动完成后系统通过Int类型的排序数值来去定存放的位置。

    • 这里需要注意的是,操作排序的是List列表中的数据项,而不是List列表本身,因此,使用.onMove(perform: ... )修饰符需要作用在ForEach循环结构上。
    struct SwiftUIList: View {
        
        @State var sentences:[SentencesModel] = Sentences
        
        var body: some View {
            NavigationView{
                List{
                    ForEach(sentences){item in
                        ListItem(image: item.image, text: item.text)
                    }
                    .onMove(perform:moveItem)
                }
                .navigationBarTitle("账号中心", displayMode: .inline)
                .navigationBarItems(trailing: EditButton())
            }
        }
        
        func moveItem(from source:IndexSet, to destination:Int){
            sentences.move(fromOffsets: source, toOffset: destination)
        }
    }
    

    image-20240504124745128

    同理,使用SwiftUI 为 List 列表提供的删除操作,下方代码,deleteRow 删除行的方法中,我们接收单一的IndexSet 类型的参数,用来定位要删除的列的位置;然后调用remove(atOffsets:...)方法来删除Messages数组中被定位的特定项。使用方法也和排序类似,使用“.onDelete(perform: …)“修饰符调用删除方法。

    import SwiftUI
    struct SwiftUIList: View {
        
        @State var sentences:[SentencesModel] = Sentences
        
        var body: some View {
            NavigationView{
                List{
                    ForEach(sentences){item in
                        ListItem(image: item.image, text: item.text)
                    }
                    .onMove(perform:moveItem)
                    .onDelete(perform: deleteRow)
                }
                .navigationBarTitle("账号中心", displayMode: .inline)
                .navigationBarItems(trailing: EditButton())
            }
        }
        
        func moveItem(from source:IndexSet, to destination:Int){
            sentences.move(fromOffsets: source, toOffset: destination)
        }
        
        func deleteRow(at offsets: IndexSet){
            sentences.remove(atOffsets: offsets)
        }
    }
    

    image-20240504125550739

    image-20240504125559650

8.3 修饰符格式化List列表样式

  • .listStyle()列表样式修饰符修饰列表。列表!,对列表本身进行修改

image-20240504130117036

  • .listRowSeparator()列表项分割线修饰符。列表项!

    image-20240504130249137

  • .listRowBackground()列表项背景修饰符。列表项!

    • 添加背景颜色

    image-20240504130437595

    • 去掉列表背景颜色

    image-20240504130541820

  • 13
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值