我是 SwiftUI 新手。 我有一个项目,其中名为“tile”的元素需要在右上角有一个下拉菜单按钮。我已经完成了该部分并添加了下拉菜单。 但是...每当我点击按钮时,它就会摆动到一侧,位于下拉菜单内容的中心 -> 此处进行屏幕录制
此外,当显示的文本较短时,点按按钮会消失,如果我理解正确的话,它会移出框架,对吧?我怎样才能防止这种情况发生?
我缺少什么,非常感谢帮助。
下面该图块和菜单的代码:
import SwiftUI
// just for testing purpose
let iconName = "ellipsis.rectangle"
protocol TileProtocol {
init (
icon: String,
text: String,
action: TileAction?,
hasMenuButton: Bool,
scaler: CGFloat
)
}
struct TileAction {
let title: String
let alignment: Alignment
let callback:(() -> Void)
}
struct TileWithMenu: TileProtocol, View {
let icon: String
let text: String
let action: TileAction?
let hasMenuButton: Bool
let scaler: CGFloat
var body: some View{
HStack(alignment: .top, spacing: 0) {
Image(icon)
.resizable()
.scaledToFit()
.frame(width: scaler, alignment: .leading)
.frame(maxWidth: 30, maxHeight: 30)
.padding(.top, 4)
.padding(.trailing, 10)
HStack(alignment: .center,spacing: 0) {
VStack(alignment: .leading,spacing: 16) {
Text(text)
.font(.headline)
if let action, action.alignment == .bottom {
VStack {
Button(action.title) {
action.callback()
}
}
}
}
}
}
.overlay(alignment: Alignment(horizontal: .trailing, vertical: .top)) {
HStack(alignment: .lastTextBaseline, spacing: 10){
if hasMenuButton {
TileMenuButton(
options: [
TileAction(title: "Postpone for 24h", alignment: .trailing, callback: {
print("24h")
}),
TileAction(title: "Postpone for 24h", alignment: .trailing, callback: {
print("1 week")
}),
TileAction(title: "Cancel", alignment: .trailing, callback: {
print("cancel")
})
],
iconScaling: scaler
)
}
}
}
}
}
struct TileMenuButton: View {
@State private var isVisible: Bool = false
let options: [TileAction]
let iconScaling: CGFloat
var body: some View {
VStack {
Button(action: {
withAnimation {
isVisible.toggle()
}
}) {
Image(iconName)
.resizable()
.scaledToFit()
.frame(width: iconScaling)
}
.padding(2)
.background(.white)
if isVisible {
VStack {
ForEach(0..<options.count, id: \.self) { n in
Button(action: options[n].callback) {
Text(options[n].title)
.font(.caption)
.padding(.top, 1)
.background(.white)
}
}
}
.transition(.asymmetric(insertion: .scale, removal: .opacity))
}
}
}
}
// MARK: PREVIEW
struct TileWithMenu_Previews: PreviewProvider {
static var previews: some View {
TileWithMenu(
icon: iconName,
text: "Some example of a very long text. Some example of a very long text. Some example of a very long text",
action: TileAction(title: "A Button", alignment: .bottom, callback: {
print("A Button tap")
}),
hasMenuButton: true,
scaler: 20
)
}
}
这是我的使用方法
struct ContentView: View {
var body: some View {
VStack {
TileWithMenu(
icon: iconName,
text: "Some example of a very long text. Some example of a very long text. Some example of a very long text",
action: TileAction(title: "A Button", alignment: .bottom, callback: {
print("A Button tap")
}),
hasMenuButton: true,
scaler: 20
)
}
.padding()
}
}
#Preview {
ContentView()
}
我正在网上寻找解决方案。目前还没找到。
要解决横向移动问题,请尝试将
(alignment: .trailing)
添加到 VStack
的顶级 TileMenuButton
:
// TileMenuButton
VStack(alignment: .trailing) { // 👈 HERE
Button //...
if isVisible {
// ...
}
}
要解决文本较短时菜单图标消失的问题,请尝试将
.fixedSize(horizontal: false, vertical: true)
添加到 HStack
叠加层内的 TileWithMenu
中:
// TileWithMenu
HStack(alignment: .top, spacing: 0) {
// ...
}
.overlay(alignment: Alignment(horizontal: .trailing, vertical: .top)) {
HStack(alignment: .lastTextBaseline, spacing: 10) {
// ...
}
.fixedSize(horizontal: false, vertical: true) // 👈 HERE
}