1、如何在List列表视图去掉分割线LineSeparator?
SwiftUI
中的List
可以说是UIKit中TableView
的进化版本,在UIKit
中我们使用separatorColor
修饰符将分割线的样式改为无。示例:
tableView.separatorColor = .clear 复制代码
在SwiftUI
中使用的方法类似,SwiftUI
中的List
的底层使用的是UITableView
,我们可以调用AppearanceAPI
来实现去掉分割线样式。示例:
UITableView.appearance().separatorColor = .clear 复制代码
但是,使用这种方式会导致App
中所有的List
,包含其他页面的的List
也会自动去掉分割线,这是因为UITableView
是List
的底层,我们的修饰符是作用在UITableView上的。
往后我们要在其他页面,比如设置页面,要恢复分割线,我们就需要赋予分割线的样式。示例:
UITableView.appearance().separatorColor = .systemGray4 复制代码
2、如何在List列表视图隐藏箭头?
在UIKit
中,我们使用accessoryType
修饰符来禁用disclosure
指示器,也就是右侧的箭头。示例:
cell.accessoryType = .none 复制代码
在SwiftUI
中,非常遗憾的是,Apple
没有提供专门的API
来设置隐藏disclosure
指示器,这会有点麻烦。
我们建立一个List
列表来看看,当我们使用NavigationLink
跳转到DetailView
详情页时,系统就会自动展示右侧的箭头,示例:
那么我们试试自己来实现隐藏disclosure
指示器。
struct ContentView: View { var body: some View { NavigationView { List { ForEach(1 ... 4, id: \.self) { index in ZStack(alignment: .leading) { NavigationLink( destination: DetailView()) { } .opacity(0) Text("第 \(index)页") } } }.navigationTitle("列表") } } } 复制代码
上述代码中,我们使用ZStack
层叠视图将整个NavigationLink
的视图包裹起来,然后使用opacity
修饰符把disclosure
指示器隐藏。
看起来不错!
3、如何修改整个视图的背景颜色?
在List
列表中,由于我们使用SwiftUI
自带的列表组件,它会默认给整个视图填充一个背景颜色以凸显列表,这时我们追求页面整体性时,需要给List
视图加一个背景颜色。
在UIKit
中,我们可以直接给视图加背景颜色,示例:
view.backgroundColor = UIColor.colorF6F7FB() 复制代码
首先,我们要去掉原有的List
列表颜色,示例:
init() { UITableView.appearance().backgroundColor = .clear } 复制代码
然后在业务代码中,我们可以使用ZStack
层叠视图和Color
的方式设置List
的背景颜色,示例:
Color(red: 132.0 / 255.0, green: 161.0 / 255.0, blue: 255.0 / 255.0).edgesIgnoringSafeArea(.all) 复制代码
不错不错!
4、如何通过网络请求显示一张网络图片?
在常用的设置页面或者我的页面,会使用到用户头像等作为用户登录示例,除了使用第三方网络请求框架外,我们也可以使用SwiftUI
自带的网络图片组件,示例:
AsyncImage(url: URL(string: imageURL)) .aspectRatio(contentMode: .fit) .frame(minWidth: 120, maxWidth: 120, minHeight: 120, maxHeight: 120) .cornerRadius(8) 复制代码
上述代码中,我们只需要定义一个图片的网络地址,就可以使用AsyncImage
组件呈现一张图片出来,并且AsyncImage
和Image
一样,可以使用修饰符修改大小的参数。
5、如何绘制带有边角的图形?
在SwiftUI
开发过程中,我们常常会看到一些带有部分圆角的形状,这又是如何实现的呢?
我们可以通过图片的方式展示,也可以自己根据形状绘制,下面我们尝试使用Shape
形状来实现这个效果。示例:
struct CShape: Shape { func path(in rect: CGRect) -> Path { let path = UIBezierPath( roundedRect: rect, byRoundingCorners: [.topRight, .bottomLeft], cornerRadii: CGSize(width: 55, height: 55) ) return Path(path.cgPath) } } 复制代码
上述代码中,我们绘制了一个形状CShape
结构体,在结构体中我们的定义了一个方法path
,它返回一个Path
路径。
我们使用贝塞尔曲线UIBezierPath
进行绘制,在右上topRight
和左下bottomLeft
绘制曲率。
接下来我们在视图中使用,示例:
struct CShapeView: View { var body: some View { Rectangle() .fill(LinearGradient(gradient: Gradient(colors: [Color.blue, Color.green]), startPoint: .leading, endPoint: .trailing)) .frame(width: 100, height: 100) .clipShape(CShape()) } } 复制代码
上述代码中,我们绘制了一个矩形Rectangle
,给它填充了一个蓝色过渡到绿色的渐变色,然后设置了大小为100*100
。
最后我们使用clipShape
修饰符切割曲线,切割方式为上面设置好的CShape
。
这样,我们就完成了一个类似叶子效果的带边角的形状。
6、如何绘制虚线边框?
在新版的Xcode
中,我们已经不能直接使用border
修饰符给按钮加边框了,那我们该如何给按钮加边框线呢?
其实很简单,我们可以使用overlay
修饰符在按钮上覆盖一层边框,示例:
Text("文如秋雨") .font(.title) .foregroundColor(.blue) .padding() .overlay( RoundedRectangle(cornerRadius: 30) .stroke(Color(.systemGray5), lineWidth: 2) ) 复制代码
上述代码中,我们使用overlay
覆盖了一层圆角矩形RoundedRectangle
,圆角度数为30
,并且使用stroke
修饰符给圆角赋予了一个灰色systemGray5
,和2
的线宽。
这是边框的实现方式,那么虚线边框我们使用的是Capsule
容器。示例:
Text("文如秋雨") .font(.title) .foregroundColor(.blue) .padding() .overlay( Capsule(style: .continuous) .stroke(Color.blue, style: StrokeStyle(lineWidth: 2, dash: [10])) ) 复制代码
上述代码中,我们覆盖的是Capsule
容器,然后将Capsule
容器的样式指定为StrokeStyle
,StrokeStyle
样式中线宽为2
,线段间距为10
。
如此,我们便实现了绘制一个虚线边框。
7、如何分享文本和图片?
在实际的开发应用中,我们常常会在App
中使用分享操作,将某一段文字或者图片分享出去,这是如何实现的呢?
首先我们先实现分享的方法,示例:
struct ShareSheet: UIViewControllerRepresentable { var items: [Any] func makeUIViewController(context: Context) -> UIActivityViewController { let controller = UIActivityViewController(activityItems: items, applicationActivities: nil) return controller } func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) { } } 复制代码
上述代码中,我们创建了一个ShareSheet
结构体,它遵循UIViewControllerRepresentable
协议。
我们声明了一个items
变量是随机类型,便于后续我们存储不同类型的内容。然后定义了一个方法makeUIViewController
,调用系统的UIActivityViewController
视图方法,分享声明好的items
内容。
接下来,我们来完成视图部分,示例:
struct ShareLinkView: View { let items = ["https://juejin.cn/user/3897092103223517"] @State var showingSheet: Bool = false var body: some View { HStack { Image(systemName: "square.and.arrow.up") Text("分享") } .onTapGesture { showingSheet.toggle() } .sheet(isPresented: $showingSheet) { ShareSheet(items: items) } } } 复制代码
上述代码中,我们声明了一个常量,存储我们的网站地址,然后使用Image
和Text
创建了一个分享的样式,调用sheet
弹窗方法打开弹窗,弹窗的内容为我们声明好的ShareSheet
视图,然后将声明好的内容传入进行分享。效果如下:
8、如何在按钮点击时有震动反馈?
iOS
很突出的一点是它的线性马达
所带来的反馈体验,让我们在点击屏幕某些操作时能够接收到App
提供的反馈信息。
如果我们需要给App
的某些操作加入一些震动反馈,该如何实现?
我们可以使用UINotificationFeedbackGenerator
来实现震动反馈的效果,示例:
struct Haptics { static func hapticSuccess() { let generator = UINotificationFeedbackGenerator() generator.notificationOccurred(.success) } static func hapticWarning() { let generator = UINotificationFeedbackGenerator() generator.notificationOccurred(.warning) } } 复制代码
上述代码中,我们创建了一个结构体Haptics
,在Haptics
中定义了2
个震动反馈效果,一个时成功反馈,一个是失败反馈。
然后我们在实际业务视图中使用它,示例:
struct HapticsView: View { var body: some View { VStack(spacing:40) { Text("成功时的反馈") .padding() .foregroundColor(.white) .background(Color.green) .cornerRadius(5) .onTapGesture { Haptics.hapticSuccess() } Text("失败时的反馈") .padding() .foregroundColor(.white) .background(Color.gray) .cornerRadius(5) .onTapGesture { Haptics.hapticWarning() } } } } 复制代码
上述代码中,我们创建了2
个按钮,分别赋予了不同的样式,当我们点击按钮
时,会调用震动反馈的方法,从而实现让用户有点击的效果。
震动反馈常用在长按或者一些警告业务场景中,可以视情况而使用。
小结
好啦!这就是本章的所有内容,是不是有点眼前一亮呢?
你还知道有哪些SwiftUI
小技巧,不妨分享一下。