如何在SwiftUI中配置ContextMenu按钮以进行删除和禁用?

时间:2019-10-19 20:45:25

标签: swift contextmenu swiftui ios13

我尝试在contextMenu中配置按钮,但是它不起作用。

Text("A label that have context menu")
    .contextMenu {
        Button(action: {
            // remove it
        }) {
            Text("Remove")
                .foregroundColor(.red) // Not working
            Image(systemName: "trash")
        }.disabled(true) // Not working
    }

我有什么:

 Not working appearance

我要寻找的内容:(删除通话按钮)

Demo

我会在UIAction中创建一个类似以下内容的UIKit,但是我找不到任何修饰符,或者无论如何都无法将其带到 SwiftUI

let delete = UIAction(title: "Remove", image: UIImage(systemName: "trash"), attributes: .destructive) { action in
    // remove it
}

4 个答案:

答案 0 :(得分:5)

iOS 15

现在支持所有询问的情况

破坏性:(适用于 iOS 15)

#include <iostream> using namespace std; int fight(); int lowblow(); int eyes(); int run(); int underground(); int officebuilding(); int main() { int choice1; int fchoice2, fchoice3; int rchoice2, rchoice3; cout << "As you’re walking down the street you feel somebody grab your shoulder, when you turn around to see. You notice the person is holding a knife towards you and demanding for your valuables." << endl; cout << "Do you fight or run?" << endl; cout << "1 - Fight" << endl; cout << "2 - Run" << endl; cin >> choice1; while (choice1 != 1 && choice1 != 2) { cout << "Do you fight or run? " << endl; cout << "1 - Fight" << endl; cout << "2 - Run" << endl; cin >> choice1; } if (choice1 == 1) { fchoice2 = fight(); while (fchoice2 != 1 && fchoice2 != 2) { fchoice2 = fight(); } if (fchoice2 == 1) { fchoice3 = lowblow(); while (fchoice3 != 1 && fchoice3 != 2) { fchoice3 = lowblow(); } } if (fchoice2 == 2) { fchoice3 = eyes(); while (fchoice3 != 1 && fchoice3 != 2) { fchoice3 = eyes(); } if (choice1 == 2) { rchoice2 = run(); while (rchoice2 != 1 && rchoice2 != 2) { rchoice2 = run(); } if (rchoice2 == 1) { rchoice3 = underground(); while (rchoice3 != 1 && rchoice3 != 2) { rchoice3 = underground(); } if (rchoice3 == 1) { officebuilding(); } } } } } } int fight() { system("clear"); int c2; cout << "You choose to fight off the attacker and suddenly all those self-defense classes come rushing into your mind.As you fight to defend yourself, you find yourself getting outmatched and have to try something drastic to survive." << endl; cout << "1 - Go for the low blow" << endl; cout << "2 - Go for the eyes " << endl; cin >> c2; return c2; } int lowblow() { system("clear"); cout << "You catch your attacker off guard and land the hit, to your surprise the attack proves ineffective.In retaliation you get hit so hard that you start seeing stars and soon blackout leaves you defenseless.Now you are knocked out and getting your valuables taken." < endl; cout << "The End" << endl; return 0; } int eyes() { system("clear"); cout << "Using the element of surprise to try fighting back gave you no advantage, so you resort to another tactic. You’ve seen it in movies and it always worked out there. You decide to go for the eyes and to your surprise it works. You use this opportunity to escape and get to safety, all while keeping your valuables safe. "<< endl; cout << "The End" << endl; return 0; } int run() { system("clear"); int c2; cout << " While running down the street to loose the attacker, you noticed that there was an underground subway a little down the road.Immediately to your left there is an office building you could run into and try to lose your attacker there."<< endl; cout << "1 - Underground ?" << endl; cout << "2- office building?" << endl; cin >> c2; return c2; } int underground() { system("clear"); cout << "As you make your way towards the underground subway station you notice rushing out.In a desperate attempt to reach safety, you run down the stairs while narrowly avoiding others.Upon arriving at the station you look back and notice that you lost your attacker.You are safe now."; cout << "The End" << endl; return 0; } int officebuilding() { system("clear"); cout << "A spontaneous decision leads you into an office building, while it may look safe, upon entering you notice everything is silent as the building seems to be completely empty.None of it matters however, since you have to escape at any cost in order.While trying to find a good way to lose the attacker you hear footsteps behind you.The attacker has cornered you and has taken your valuables." << endl; cout << "The End" << endl; return 0; } 设置为按钮的 .destructive 参数:

role

Delete Demo


已禁用:(适用于 iOS 14.2)

向按钮添加 Button(role: .destructive) { // ? This argument // delete something } label: { Label("Delete", systemImage: "trash") } 修饰符。

.disabled

Disabled Demo


分隔线:(适用于 iOS 14)

直接使用 Button { // call someone } label: { Label("Call", systemImage: "phone") }.disabled(true) // ? This modifier 视图。

Divider Demo


完整演示:

Demo ⚠️记住!不要不要使用Divider()代替image在按钮上显示SFSymbol!

答案 1 :(得分:3)

iOS 15

从 iOS 15 开始,我们可以向按钮添加 role,以便它可以自动调整其外观:

enter image description here

这是一个例子:

Text("A label that have context menu")
    .contextMenu {
        Button(role: .destructive) {
            print("removing...")
        } label: {
            Text("Remove")
            Image(systemName: "trash")
        }
    }

答案 2 :(得分:0)

Apple提倡使用Menu而不是ContextMenu。如果要禁用菜单中的选项,则可以使用以下代码。您可以在修饰符内部使用表达式使其动态化

关于样式-当前无法在菜单中设置单个项目的样式。即使您应用样式也不起作用。

struct ContentView: View {
    var body: some View {
        
        VStack {
            Menu("Actions") {
                Button("Duplicate", action: {})
                Button("Rename", action: {})
                Button(action: {}) {
                    
                    Label("Delete", systemImage: "trash")
                    
                }.disabled(true)
                Button(action: {}) {
                   
                    Label("Call", systemImage: "phone")
                    
                }.disabled(true)
            }      
        }
    }
}

Diasbled Menu Options

答案 3 :(得分:-2)

切换确定视图是否可见的布尔值是可行的:

struct ContentView: View {
    @State var textVisible = true
    var body: some View {
        Group {
            if textVisible {
                Text("Hello World")
                .contextMenu {
                    Button(action: {
                        self.textVisible = false
                    }) {
                        HStack {
                            Text("Remove")
                            Image(systemName: "trash")
                        }
                    }
                }
            }
        }
    }
}

当然,由于上下文菜单是附加到已删除的Text上的,因此除非您有其他可切换布尔值({{1 }})。

编辑:OP想知道如何使上下文菜单中的按钮处于禁用/破坏性(灰色/红色前景色),但我相信截至2019年10月20日,SwiftUI都有一个错误不允许上下文菜单中的任何按钮为红色以外的任何其他颜色。否则,将按钮设置为Button会将其设置为灰色并禁用它,将按钮的前景色设置为红色(textVisible)将使按钮具有破坏性。