问题描述
** 编辑 ** 怀疑这个 SwiftUI 视图嵌入的 UIKit 视图(通过 UIHostingController)是问题所在,因为@excore 的解决方案在预览中对我有用。这是 UIKit 布局代码:
var searchBox: UIHostingController<WKMapDropdownView> = UIHostingController(rootView: WKMapDropdownView(activityTypes: []))
searchBox.view.backgroundColor = UIColor.clear
self.view.addSubview(searchBox.view)
searchBox.view.translatesAutoresizingMaskIntoConstraints = false
let constraints = [
searchBox.view.topAnchor.constraint(equalTo: self.mapView!.topAnchor,constant: 30),searchBox.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor,constant: 20),searchBox.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor,constant: -20),]
NSLayoutConstraint.activate(constraints)
========
我有一个 SwiftUI 视图,其中包含一个 vstack,其中一些子视图在点击第一个子视图时显示/隐藏。
动画看起来有点奇怪,因为动画会导致已经可见的孩子跳到中间然后扩展回顶部。我希望它发生,所以已经可见的孩子留在原地,隐藏的选项滑到下面。
我认为为孩子们制作高度动画可能会更好,或者 vstack 本身就是问题的原因。
有人可以帮忙吗?
视图模型:
import Foundation
enum WKMapDropdownState {
case optionsCollapsed
case optionsExpanded
case dropdownCollapsed
}
enum WKMapSearchType {
case postcode
case name
case activityType
}
class WKMapDropdownviewmodel : ObservableObject {
@Published var optionsExpanded : Bool = false
@Published var titleVisible : Bool = true
@Published var backArrowVisible : Bool = false
private var currentState : WKMapDropdownState = .optionsCollapsed
func toggleDropdown() {
switch (currentState) {
case .optionsCollapsed:
expandOptions()
case .optionsExpanded:
collapSEOptions()
case .dropdownCollapsed:
// self.delegate?.dropdownBackTapped() -> Hide everything
expandDropdown()
}
}
func searchTypeButtonTapped(searchType: WKMapSearchType) {
collapseDropdown()
}
private func showDropdownoptions() {
optionsExpanded = true
}
private func hideDropdownoptions() {
optionsExpanded = false
}
private func showCollapsedOpenviewButton() {
titleVisible = true
backArrowVisible = true
}
private func showExpandedOpenviewButton() {
titleVisible = true
backArrowVisible = false
}
private func expandOptions() {
showDropdownoptions()
currentState = .optionsExpanded
}
private func collapSEOptions() {
hideDropdownoptions()
currentState = .optionsCollapsed
}
private func expandDropdown() {
hideDropdownoptions()
showExpandedOpenviewButton()
currentState = .optionsCollapsed
}
private func collapseDropdown() {
hideDropdownoptions()
showCollapsedOpenviewButton()
currentState = .dropdownCollapsed
}
}
查看:
struct WKMapDropdownView: View {
@Observedobject var viewmodel = WKMapDropdownviewmodel()
var body: some View {
vstack {
HStack {
Button(action: {
withAnimation {
self.viewmodel.toggleDropdown()
}
}) {
HStack {
Text("I want to search...")
.opacity(self.viewmodel.titleVisible ? 1 : 0)
.foregroundColor(.white)
.font(.custom("Roboto-Regular",size: 19))
.frame(maxWidth: .infinity,alignment: .leading)
Image(self.viewmodel.optionsExpanded ? "searchBoxUpArrow" : "searchBoxDownArrow")
.frame(maxWidth: .infinity,alignment: .trailing)
.animation(nil)
}
.frame(maxWidth: .infinity)
.padding(EdgeInsets(top: 19,leading: 22,bottom: 18,trailing: 25))
}
.background(Color.init("tealish"))
}
.frame(maxHeight: .infinity,alignment: .top)
if self.viewmodel.optionsExpanded {
vstack {
Button(action: { self.viewmodel.searchTypeButtonTapped(searchType: .postcode) }) {
Text("By Postcode")
.font(.custom("Roboto-Regular",size: 19))
.foregroundColor(Color.init("tealish"))
.background(Color.clear)
.padding(EdgeInsets(top: 19,trailing: 25))
.frame(maxWidth: .infinity,alignment: .leading)
}
.transition(.identity)
Button(action: { self.viewmodel.searchTypeButtonTapped(searchType: .name) }) {
Text("All Wiki Places")
.font(.custom("Roboto-Regular",alignment: .leading)
}
.transition(.identity)
Button(action: { self.viewmodel.searchTypeButtonTapped(searchType: .activityType) }) {
Text("By Activity Type")
.font(.custom("Roboto-Regular",alignment: .leading)
}
.transition(.identity)
}
.frame(maxHeight: .infinity,alignment: .top)
}
}
.frame(maxHeight: .infinity,alignment: .top)
.background(Color(UIColor.systemBackground))
.clipShape(RoundedRectangle(cornerRadius:10))
}
}
struct WKMapDropdownView_Previews: PreviewProvider {
static var previews: some View {
WKMapDropdownView()
}
}
解决方法
我无法发表评论,所以我假设我正在解决正确的问题。
首先,我不太明白为什么你的 maxHeight: .infinity
中有 VStack
,删除它们可能是答案的一部分,之后我有这个:
接下来,如果您想将此下拉列表固定在顶部,我认为最简单的选择是将 Spacer()
放在下拉视图下,如下所示:
这里是修复的概述:
struct WKMapDropdownView: View {
@ObservedObject var viewModel = WKMapDropdownViewModel()
var body: some View {
VStack { // Wrapped into another VStack
VStack {
HStack {
...
}
.frame(alignment: .top) // Removed maxHeight
if self.viewModel.optionsExpanded {
VStack {
...
}
.frame(alignment: .top) // Removed maxHeight
}
}
.frame(alignment: .top) // Removed maxHeight
.background(Color(UIColor.systemBackground))
.clipShape(RoundedRectangle(cornerRadius:10))
Spacer() // Added Spacer
}
}
}