- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
代码
我有以下代码:
struct CustomTabView: View where Content: View {
let children: [AnyView]
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
let m = Mirror(reflecting: content())
if let value = m.descendant("value") {
let tupleMirror = Mirror(reflecting: value)
let tupleElements = tupleMirror.children.map({ AnyView($0.value) }) // ERROR
self.children = tupleElements
} else {
self.children = [AnyView]()
}
}
var body: some View {
ForEach(self.children) { child in
child...
}
}
}
TupleView
成
AnyView
的数组但我收到错误
Protocol type 'Any' cannot conform to 'View' because only concrete types can conform to protocols
CustomTabView
像这样:
CustomTabView {
AnyView(Text("A"))
AnyView(Text("B"))
AnyView(Rectangle())
}
TabView
一样执行以下操作
CustomTabView {
Text("A")
Text("B")
Rectangle()
}
TupleView
成
AnyView
的数组?
最佳答案
以下是我使用 SwiftUI 创建自定义选项卡 View 的方法:
struct CustomTabView<Content>: View where Content: View {
@State private var currentIndex: Int = 0
@EnvironmentObject private var model: Model
let content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
var body: some View {
GeometryReader { geometry in
return ZStack {
// pages
// onAppear on all pages are called only on initial load
self.pagesInHStack(screenGeometry: geometry)
}
.overlayPreferenceValue(CustomTabItemPreferenceKey.self) { preferences in
// tab bar
return self.createTabBar(screenGeometry: geometry, tabItems: preferences.map {TabItem(tag: $0.tag, tab: $0.item)})
}
}
}
func getTabBarHeight(screenGeometry: GeometryProxy) -> CGFloat {
// https://medium.com/@hacknicity/ipad-navigation-bar-and-toolbar-height-changes-in-ios-12-91c5766809f4
// ipad 50
// iphone && portrait 49
// iphone && portrait && bottom safety 83
// iphone && landscape 32
// iphone && landscape && bottom safety 53
if UIDevice.current.userInterfaceIdiom == .pad {
return 50 + screenGeometry.safeAreaInsets.bottom
} else if UIDevice.current.userInterfaceIdiom == .phone {
if !model.landscape {
return 49 + screenGeometry.safeAreaInsets.bottom
} else {
return 32 + screenGeometry.safeAreaInsets.bottom
}
}
return 50
}
func pagesInHStack(screenGeometry: GeometryProxy) -> some View {
let tabBarHeight = getTabBarHeight(screenGeometry: screenGeometry)
let heightCut = tabBarHeight - screenGeometry.safeAreaInsets.bottom
let spacing: CGFloat = 100 // so pages don't overlap (in case of leading and trailing safetyInset), arbitrary
return HStack(spacing: spacing) {
self.content()
// reduced height, so items don't appear under tha tab bar
.frame(width: screenGeometry.size.width, height: screenGeometry.size.height - heightCut)
// move up to cover the reduced height
// 0.1 for iPhone X's nav bar color to extend to status bar
.offset(y: -heightCut/2 - 0.1)
}
.frame(width: screenGeometry.size.width, height: screenGeometry.size.height, alignment: .leading)
.offset(x: -CGFloat(self.currentIndex) * screenGeometry.size.width + -CGFloat(self.currentIndex) * spacing)
}
func createTabBar(screenGeometry: GeometryProxy, tabItems: [TabItem]) -> some View {
let height = getTabBarHeight(screenGeometry: screenGeometry)
return VStack {
Spacer()
HStack(spacing: screenGeometry.size.width / (CGFloat(tabItems.count + 1) + 0.5)) {
Spacer()
ForEach(0..<tabItems.count, id: \.self) { i in
Group {
Button(action: {
self.currentIndex = i
}) {
tabItems[i].tab
}.foregroundColor(self.currentIndex == i ? .blue : .gray)
}
}
Spacer()
}
// move up from bottom safety inset
.padding(.bottom, screenGeometry.safeAreaInsets.bottom > 0 ? screenGeometry.safeAreaInsets.bottom - 5 : 0 )
.frame(width: screenGeometry.size.width, height: height)
.background(
self.getTabBarBackground(screenGeometry: screenGeometry)
)
}
// move down to cover bottom of new iphones and ipads
.offset(y: screenGeometry.safeAreaInsets.bottom)
}
func getTabBarBackground(screenGeometry: GeometryProxy) -> some View {
return GeometryReader { tabBarGeometry in
self.getBackgrounRectangle(tabBarGeometry: tabBarGeometry)
}
}
func getBackgrounRectangle(tabBarGeometry: GeometryProxy) -> some View {
return VStack {
Rectangle()
.fill(Color.white)
.opacity(0.8)
// border top
// https://www.reddit.com/r/SwiftUI/comments/dehx9t/how_to_add_border_only_to_bottom/
.padding(.top, 0.2)
.background(Color.gray)
.edgesIgnoringSafeArea([.leading, .trailing])
}
}
}
// MARK: - Tab Item Preference
struct CustomTabItemPreferenceData: Equatable {
var tag: Int
let item: AnyView
let stringDescribing: String // to let preference know when the tab item is changed
var badgeNumber: Int // to let preference know when the badgeNumber is changed
static func == (lhs: CustomTabItemPreferenceData, rhs: CustomTabItemPreferenceData) -> Bool {
lhs.tag == rhs.tag && lhs.stringDescribing == rhs.stringDescribing && lhs.badgeNumber == rhs.badgeNumber
}
}
struct CustomTabItemPreferenceKey: PreferenceKey {
typealias Value = [CustomTabItemPreferenceData]
static var defaultValue: [CustomTabItemPreferenceData] = []
static func reduce(value: inout [CustomTabItemPreferenceData], nextValue: () -> [CustomTabItemPreferenceData]) {
value.append(contentsOf: nextValue())
}
}
// TabItem
extension View {
func customTabItem<Content>(@ViewBuilder content: @escaping () -> Content) -> some View where Content: View {
self.preference(key: CustomTabItemPreferenceKey.self, value: [
CustomTabItemPreferenceData(tag: 0, item: AnyView(content()), stringDescribing: String(describing: content()), badgeNumber: 0)
])
}
}
// Tag
extension View {
func customTag(_ tag: Int, badgeNumber: Int = 0) -> some View {
self.transformPreference(CustomTabItemPreferenceKey.self) { (value: inout [CustomTabItemPreferenceData]) in
guard value.count > 0 else { return }
value[0].tag = tag
value[0].badgeNumber = badgeNumber
}
.transformPreference(CustomTabItemPreferenceKey.self) { (value: inout [CustomTabItemPreferenceData]) -> Void in
guard value.count > 0 else { return }
value[0].tag = tag
value[0].badgeNumber = badgeNumber
}
.tag(tag)
}
}
struct MainTabsView: View {
var body: some View {
// TabView
CustomTabView {
A()
.customTabItem { ... }
.customTag(0, badgeNumber: 1)
B()
.customTabItem { ... }
.customTag(2)
C()
.customTabItem { ... }
.customTag(3)
}
}
}
关于SwiftUI 将 TupleView 转换为 AnyView 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59608417/
有没有办法获取/获取 SwiftUI 中 Text 对象中使用的当前字体?前任。 Text("abc").font() 不起作用。 最佳答案 可以从环境访问当前字体: struct ChildView
我想知道为什么 SwiftUI 中的 2 个元素之间会出现这种间距?以及如何控制/修改它?我尝试向 ExtractedView 添加一些填充,但没有任何改变。似乎它是由 .frame(height:
目标 获取要显示在scrollView中的数据 预期结果 实际结果 另类 使用List,但不灵活(无法删除分隔符,不能具有多列) 码 struct Object: Identifiable {
我想使用 onIncrement 和 onDecrement 在手动(非绑定(bind))模式下使用 Stepper View 。当我尝试实现下限和上限时,有一种奇怪的行为,例如。年龄值不低于 1 或
我正在尝试在 SwiftUI 中显示全局警报。无论当前显示/呈现在屏幕上的内容(例如工作表),此警报都应显示在所有内容的顶部。 这是我的代码: @main struct MyApp: App {
我正在尝试为我的模态表实现一个关闭按钮,如下所示: struct TestView: View { @Environment(\.isPresented) var present va
我有一个在 SwiftUI 中处理的主细节应用程序,但是一旦在第一个 DetailView 上,NavBar 中的 NavigationLink 就不再有效。我把它写成一个简单的演示: struct
这是我想做的一个最小的、可重复的例子。 我有一系列的段落。 var notes = [ "One line paragraph", "This is a small paragraph
有什么方法可以使用 SwiftUI 找到父 View 大小,我查看了文档和示例,似乎大多数(如果不是全部)都是硬编码大小,理想情况下我想找到父 View 的大小然后设置基于父级大小百分比的 subvi
我有一个 列表由单元格组成,每个单元格包含一个图像和一列文本,我希望以特定的方式布局。左侧图像,占宽度的四分之一。文本的剩余空间,左对齐。 这是我得到的代码: struct TestCell: Vie
这是 iOS 13 Health 应用程序的屏幕截图 - 用户个人资料。我最近开始使用 swiftui并想知道如何开发如下所示的屏幕。我尝试了简单和分组的列表样式。但我无法看到下面的布局。 这样的UI
更新 : 14 个月后,AppKit 发行说明中有这样一个有趣的说明: A TextField that you are editing inside a selected List row now
我来自 React,在那里我使用 useMemo 来确保某些计算不会过于频繁地执行。我如何在 SwiftUI 中做类似的事情? 考虑这个例子: struct MyView: View { va
我已经查看并尝试了所有不同的组合,但我无法弄清楚如何更改 View 导航栏标题的文本颜色。这是我的代码,我也在尝试使用我已经从我的 Assets 文件夹中添加和使用的自定义颜色。我知道这个问题已被问过
如何更改swiftUI上导航栏“返回”按钮的文本? form from a navigationLink init(){ UINavigationBar.appearance().backgr
具有渐变填充的矩形并尝试为颜色变化设置动画。 ... Rectangle() .fill(LinearGradient( gradient: .init(stops:
我已经将UITextView包装在UIViewRepresentable中,并包括了Coordinator作为UITextViewDelegate,但是未调用事件。我究竟做错了什么? struct T
我需要更改 swiftUI 中 tabItem 徽章的颜色。我创建了这个 Pod https://github.com/jogendra/BadgeHub可以与 swiftUI 一起使用吗? 我有选项
我可以使用以下代码在 UIKIt 中定义常量字体: let appFont = UIFont.systemFont(ofSize: 18, weight: UIFont.Weight.regular)
通常我可以在 SwiftUI 中显示这样的项目列表: enum Fruit { case apple case orange case banana } struct Frui
我是一名优秀的程序员,十分优秀!