实战教程·元宇宙来了,准备好你的电子名片了吗?(三)(2)

简介: 实战教程·元宇宙来了,准备好你的电子名片了吗?(三)

界面设计:平台称号输入框

声明好需要的变量后,我们来搭建平台称号输入框内容,我们可以和搭建closeBtn关闭按钮视图一样,单独搭建平台输入框视图,再将该视图内容赋予NewView主要的视图中,如下代码所示:


// 头衔名称输入框
func titleInputView() -> some View {
    TextField("请输入头衔", text: $title)
        .padding()
        .background(Color(.systemGray6))
        .cornerRadius(8)
        .padding(.horizontal)
}

image.png

上述代码中,我们创建了一个平台称号输入框视图titleInputView,主体内容使用TextField输入框控件,输入框提示文字为“请输入头衔”,输入内容绑定声明的变量title。

在样式方面,为了突出输入框视图内容,使用padding修饰符“撑开”输入框外层区域,将外层区域填充背景色为systemGray6,并设置圆角度数为8,最后设置水平位置两边留白,便实现了上图效果。

界面设计:自定义平台选择器

接下来我们来设计“选择平台”的操作逻辑。可以简单设想下,用户在“添加身份卡”页面输入完平台称号后,下一步是选择该称号所在的社区或者平台。

最直观的展现方式是将平台都排列出来让用户进行选择,而由于展示空间有限,我们可以只展示平台的图标。当用户看到平台图标时,通过点击选择以确定平台,而且平台选择单张身份卡只能选择一个平台。

有了基础的想法后,我们来实现这个交互逻辑。

首先需要创建一个平台展示的数据集合,我们声明一个数据用于存放数据,如下代码所示:

private let platforms = [
        ("稀土掘金技术社区", "icon_juejin"),
        ("CSDN博客", "icon_csdn"),
        ("阿里云社区", "icon_aliyun"),
        ("华为云社区", "icon_huaweiyun"),
    ]

上述代码中,我们声明了一个常量数组platforms,在platforms数组内有两个内容,前一个参数是平台名称,后一个参数是平台图标。

声明好数据后,我们来创建平台选择样式部分,这次需要用到的SwiftUI控件是LazyVGrid垂直网格布局容器,LazyVGrid垂直网格布局容器类似VStack垂直布局容器,不同的是VStack垂直布局容器只能将内部的元素垂直排布,而LazyVGrid垂直网格视图容器可以保持垂直布局的情况下,将内部的元素分为几列,如下图所示:

image.png

LazyVGrid垂直网格布局容器使用需要提前声明网格的列数,如下代码所示:

private var gridItemLayout = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]

上述代码中,我们声明了布局容器的GridItem列项为4列自适应调整的列项,将参数赋予变量值gridItemLayout。

紧接着我们来使用LazyVGrid垂直网格布局容器,LazyVGrid垂直网格布局容器的使用方法和List列表的使用方法类似,通过与ForEach循环遍历配合使用,我们依旧使用单独构建视图的方法创建它,如下代码所示:

// 平台选择器
func platformPicker() -> some View {
    LazyVGrid(columns: gridItemLayout, spacing: 10) {
        ForEach(0 ..< platforms.count, id: .self) { item in
            Image(platforms[item].1)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 48, height: 48)
                .clipShape(Circle())
        }
    }
}

image.png

上述代码中,我们创建了“选择平台”视图platformPicker,在platformPicker视图中使用LazyVGrid垂直网格布局容器搭建网格视图,LazyVGrid的columns列项为上面声明的gridItemLayout,网格之间元素的spacing间距为10。

和List列表的方法一样,我们使用ForEach循环遍历platforms数组的数据,并使用了Image图片控件来展示platforms数组中的数据。由于platforms数组使用两个数据,因此我们使用下标法指向数组的第二个数据(计算机数据从0开始计数)。

在这里还需要考虑一个问题,当我们平台图标太多时,可能会占据整个App的页面,我们可以在LazyVGrid垂直网格布局容器最外层增加一个ScrollView滚动视图容器,并设置滚动视图的高度,如此LazyVGrid垂直网格布局容器不管有多少元素,都只会在ScrollView滚动视图容器中展示,如下代码所示:

ScrollView {
            LazyVGrid(columns: gridItemLayout, spacing: 10) {
                ForEach(0 ..< platforms.count, id: .self) { item in
                    Image(platforms[item].1)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 48, height: 48)
                        .clipShape(Circle())
                }
            }
        }
        .padding()
        .background(Color(.systemGray6))
        .cornerRadius(8)
        .padding(.horizontal)
        .frame(maxHeight: 180)

image.png

很好,完成了“平台选择器”的样式之后,我们来实现交互逻辑部分,首先我们要看到用户点击选择的平台是哪一个,并将其凸显出来。

由于ForEach是遍历数据给到了item,因此当用户点击了指定的item时,该item对应的样式与其他未选中的样式分隔开。为了实现这个效果,我们首先要声明一个变量,知道选中的是哪一个item,如下代码所示:

@State var selectedItem = 0

当选中时,即item的值等于selectedItem时,我们设置图片加一层边框,如果不是,则保持原样,如下代码所示:

if item == selectedItem {
    Image(platforms[item].1)
        .resizable()
        .aspectRatio(contentMode: .fit)
        .frame(width: 48, height: 48)
        .clipShape(Circle())
        .overlay(
            Circle()
                .stroke(Color.green, lineWidth: 4)
        )
} else {
    Image(platforms[item].1)
        .resizable()
        .aspectRatio(contentMode: .fit)
        .frame(width: 48, height: 48)
        .clipShape(Circle())
    .onTapGesture {
          selectedItem = item
  }
}

上述代码中,我们通过判断当前的item是否等于selectedItem来构建不同的图片样式,如果一致,则Image图片使用overlay修饰符覆盖一层绿色的圆形边框。如果不一致,则保持原来的样式,在原有的样式上增加onTapGesture点击事件,当点击的时候,让selectedItem选中的item等于点击的item。

可以在模拟器上试试效果,如下图所示:

image.png

另外,当点击平台图标时,我们需要给声明的变量进行赋值,如下代码所示:

platformIcon = platforms[item].1
platformName = platforms[item].0

image.png

如此,便完成了“自定义平台选择器”的所有内容。


相关文章
|
存储 JSON 缓存
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)(1)
实战教程·元宇宙来了,准备好你的电子名片了吗?
79 0
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)(1)
实战教程·元宇宙来了,准备好你的电子名片了吗?(七)(3)
实战教程·元宇宙来了,准备好你的电子名片了吗?(七)
39 0
实战教程·元宇宙来了,准备好你的电子名片了吗?(七)(3)
|
存储 安全 容器
实战教程·元宇宙来了,准备好你的电子名片了吗?(七)(5)
实战教程·元宇宙来了,准备好你的电子名片了吗?(七)
63 0
实战教程·元宇宙来了,准备好你的电子名片了吗?(七)(5)
|
JSON API 数据格式
实战教程·元宇宙来了,准备好你的电子名片了吗?(五)(4)
实战教程·元宇宙来了,准备好你的电子名片了吗?(五)
65 0
|
存储 XML Swift
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)(2)
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)
76 0
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)(2)
|
存储 JSON 测试技术
实战教程·元宇宙来了,准备好你的电子名片了吗?(五)(2)
实战教程·元宇宙来了,准备好你的电子名片了吗?(五)
52 0
实战教程·元宇宙来了,准备好你的电子名片了吗?(五)(2)
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)(5)
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)
50 0
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)(5)
|
数据库
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)(4)
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)
51 0
实战教程·元宇宙来了,准备好你的电子名片了吗?(八)(4)
实战教程·元宇宙来了,准备好你的电子名片了吗?(四)(3)
实战教程·元宇宙来了,准备好你的电子名片了吗?(四)
55 0
实战教程·元宇宙来了,准备好你的电子名片了吗?(四)(3)
实战教程·元宇宙来了,准备好你的电子名片了吗?(七)(4)
实战教程·元宇宙来了,准备好你的电子名片了吗?(七)
56 0
实战教程·元宇宙来了,准备好你的电子名片了吗?(七)(4)