IOS Widget(3):SwiftUI开发小组件布局入门
引言
经过上一篇文章,我们已经可以在桌面上展示出一个小组件出来了,你肯定想小试牛刀,动手改一改,那我们就从改小组件的布局做起吧。本文不会讲解Swift语法,如果是熟悉Flutter,Kotlin这种语言的,问题也不大。本文只讲解小组件中常用的SwiftUI组件。
本文大纲
小组件布局怎么区分组件型号:大中小
常用基础组件 Text Image
常用容器组件 ZStack VStack HStack
常用属性:充满父布局 文字内部居中 等分剩余空间(Spacer)
小组件布局怎么区分组件型号:大中小
struct Widget1EntryView : View { // 这句代码能从上下文环境中取到小组件的型号 @Environment(\.widgetFamily) var family // 组件数据 var entry: Provider.Entry // 这个 body 中就是自己需要实现的组件布局 var body: some View { switch family { case .systemSmall: // 小号 Text(entry.date, style: .time) case .systemMedium: // 中号 Text(entry.date, style: .time) case .systemLarge: // 大号 Text(entry.date, style: .time) @unknown default: Text(entry.date, style: .time) } } }
常用基础组件Text使用
Text("普通文本") .font(.system(size: 15)) // 字体 .foregroundColor(Color(hexString: "#FF0000"))// Text以日期作为参数时可以有以下多种使用方式,参考官网定义// 重要:其中的.timer比较有用,可以用来做时钟的刷新/// A predefined style used to display a `Date`.public struct DateStyle { /// A style displaying only the time component for a date. /// /// Text(event.startDate, style: .time) /// /// Example output: /// 11:23PM public static let time: Text.DateStyle /// A style displaying a date. /// /// Text(event.startDate, style: .date) /// /// Example output: /// June 3, 2019 public static let date: Text.DateStyle /// A style displaying a date as relative to now. /// /// Text(event.startDate, style: .relative) /// /// Example output: /// 2 hours, 23 minutes /// 1 year, 1 month public static let relative: Text.DateStyle /// A style displaying a date as offset from now. /// /// Text(event.startDate, style: .offset) /// /// Example output: /// +2 hours /// -3 months public static let offset: Text.DateStyle /// A style displaying a date as timer counting from now. /// /// Text(event.startDate, style: .timer) /// /// Example output: /// 2:32 /// 36:59:01 public static let timer: Text.DateStyle}
IOS中的颜色RGB不是安卓的0-255,而是0-1,这里写了一个拓展函数支持十六进制颜色字符串
#if (arch(arm64) || arch(x86_64))import Foundationimport SwiftUI@available(iOS 13.0, *)extension Color { //#ARGB init?(hexString: String) { var hex = hexString; guard hexString.starts(with: "#") else { return nil } hex.remove(at: hexString.startIndex) var value: UInt64 = 0 Scanner(string: hex).scanHexInt64(&value) var a = 0xFF / 255.0 if hex.count > 7 { a = Double(value >> 24) / 255.0 } let r = Double((value & 0xFF0000) >> 16) / 255.0; let g = Double((value & 0xFF00) >> 8) / 255.0; let b = Double(value & 0xFF) / 255.0 self.init(red: Double(r), green: Double(g), blue: Double(b)) _ = self.opacity(Double(a)) } }
常用基础组件Image使用
// 访问bundle中的资源Image("imageName")// 通过UIImage加载文件夹中的图片资源Image(uiImage: UIImage(contentsOfFile: "picPath") ?? UIImage()) .resizable() .scaledToFill() .clipped() .colorMultiply(Color(hexString: config.textColor) ?? Color.white) // 重要:这个类似安卓中的colorFilter可以修改图片颜色 .frame(width: 36, height: 36, alignment: .center)
常用容器组件ZStack使用,类似安卓里面的FrameLayout,可以重叠布局
ZStack { Text("普通文本") .font(.system(size: 15)) // 字体 .foregroundColor(Color(hexString: "#FF0000")) Text(entry.date, style: .time) }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top).background(Color(hexString: "#00FFFF"))
常用容器组件HStack使用,水平方向布局
HStack { Text("普通文本") .font(.system(size: 15)) // 字体 .foregroundColor(Color(hexString: "#FF0000")) Text(entry.date, style: .time) }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center).background(Color(hexString: "#00FFFF"))
常用容器组件VStack使用,垂直方向布局
VStack { Text("普通文本") .font(.system(size: 15)) // 字体 .foregroundColor(Color(hexString: "#FF0000")) Text(entry.date, style: .time) }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center).background(Color(hexString: "#00FFFF"))
充满父布局怎么实现
.frame(maxWidth: .infinity, maxHeight: .infinity)VStack { Text("普通文本") .font(.system(size: 15)) // 字体 .foregroundColor(Color(hexString: "#FF0000")) Text(entry.date, style: .time) }.frame(maxWidth: .infinity, maxHeight: .infinity) // 充满父布局.background(Color(hexString: "#00FFFF"))
文字内部居中(multilineTextAlignment)
.multilineTextAlignment(.center)VStack { Text("普通文本") .font(.system(size: 15)) // 字体 .foregroundColor(Color(hexString: "#FF0000")) Text(entry.date, style: .timer) .multilineTextAlignment(.center) // 让文字在Text内部居中 .background(Color(hexString: "#FFFF00")) }.frame(maxWidth: .infinity, maxHeight: .infinity).background(Color(hexString: "#00FFFF"))
等分剩余空间(Spacer)
VStack { Spacer() Text("普通文本") .font(.system(size: 15)) // 字体 .foregroundColor(Color(hexString: "#FF0000")) Spacer() Text(entry.date, style: .timer) .multilineTextAlignment(.center) .background(Color(hexString: "#FFFF00")) Spacer() }.frame(maxWidth: .infinity, maxHeight: .infinity).background(Color(hexString: "#00FFFF"))
控制间距(spacing)
VStack(spacing: 10) { Text("普通文本") .font(.system(size: 15)) // 字体 .foregroundColor(Color(hexString: "#FF0000")) Text(entry.date, style: .timer) .multilineTextAlignment(.center) .background(Color(hexString: "#FFFF00")) }.frame(maxWidth: .infinity, maxHeight: .infinity).background(Color(hexString: "#00FFFF"))
结语
关于小组件SwiftUI布局就讲这么多,入个门差不多了,另外,小组件并不能使用全部的SwiftUI控件,只能使用一些基本的控件
来源:https://www.cnblogs.com/popfisher/p/14736526.html