كيفية استخدام Long press مع Menu

من المتعارف عليه بأن الـ Menu في SwiftUI عباره عن Button ويعامل كـ Button

بما يعني عن الضغط عليه سوف تظهر الخيارات بشكل تلقائي مثال

struct ContentView: View {
    var body: some View {
        VStack {
            
            Menu {
                Button(action: { print("Menu button 1")
                }) {
                    Text("Menu button 1")
                }
                
                Button(action: { print("Menu button 2")
                }) {
                    Text("Menu button 2")
                }

            } label: {
                Text("Menu")
            }

        }
    }
}

فيديو يوضح المثال السابق

كما هو واضح في المثال السابق بمجرد الضغط على الزر يتم عرض عناصر الـ Menu بشكل مباشر

لكن في بعض الاوقات تحتاج ان تعرض الخيارات بعد ضغطه مطوله Long press وليس بمجرد الضغط على الـ Menu

لكن قبل شرح هذه النقطه اريد أن اوضح بأن الـ Menu عباره عن Button بتغيير ستايله

            Menu {
                Button(action: { print("Menu button 1")
                }) {
                    Text("Menu button 1")
                }
                
                Button(action: { print("Menu button 2")
                }) {
                    Text("Menu button 2")
                }

            } label: {
                Text("Menu")
            }
            .buttonStyle(.borderedProminent)

في الكود السابق اضفت buttonStyle الى الـ Menu

النتيجة

كما تلاحظ تم تغيير شكل الزر كما يتم تغييره عند استخدام Button
هذه المعلومة سوف تفدينا لاحقاً

كيف جعل الـ Menu يظهر فقط عند الضغطه المطوله ؟

الطريقة بسيطه وهيا بإستخدام primaryAction
عند اضافة primaryAction الى الـ Menu سوف تستطيع عمل امرين

١- جعل عناصر الـ Menu تظهر بعد ضغطه مطوله
٢- امكانية اضافة action عند الضغط مره وحده مثل الـ Button

            Menu {
                Button(action: { print("Menu button 1")
                }) {
                    Text("Menu button 1")
                }
                
                Button(action: { print("Menu button 2")
                }) {
                    Text("Menu button 2")
                }

            } label: {
                Text("Menu")
            } primaryAction: {}
            .buttonStyle(.borderedProminent)

لاحظ في الكود السابق لم اضيف اي شي داخل الـ primaryAction

النتيجة

كما تلاحظ عند الضغط على الزر مره وحده لا يحدث اي شي ، وفقط عند الضغط ضغطه مطوله تظهر عناصر الـ Menu

عمل Action عند الضغط على Menu مره وحده

في المثال التالي سوف اغير لون الزر عند الضغط مره وحده

struct ContentView: View {
    @State private var changeColor = false
    
    var body: some View {
        VStack {
 
            Menu {
                Button(action: { print("Menu button 1")
                }) {
                    Text("Menu button 1")
                }
                
                Button(action: { print("Menu button 2")
                }) {
                    Text("Menu button 2")
                }

            } label: {
                Text("Menu")
            } primaryAction: {
                changeColor.toggle()
            }
            .buttonStyle(.borderedProminent)
            .tint(changeColor ? .red : .blue)

        }
    }
}


النتيجة

كيفية ازالة الـ Highlight من الـ Menu

من الامور الاساسيه عندما تريد اضافة Long press الى الـ Menu بانك لا تريد أن يظهر Highlight الـ Buuton

كما وضحت سابقا عند اضافة primaryAction فانه سوف يعامل معاملة الـ Button عند اول ضغطه وبالتالي سوف يظهر Highlight عند اول ضغطه، لذا يفضل ازالتها

وطريقتها سهله راح نعمل buttonStyle مخصص لازالتها

اضيف الكود التالي الى المشروع

struct NoHighlightButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
    }
}

تم استخدمه بهذا الشكل

struct ContentView: View {

    var body: some View {
        VStack {
 
            Menu {
                Button(action: { print("Menu button 1")
                }) {
                    Text("Menu button 1")
                }
                
                Button(action: { print("Menu button 2")
                }) {
                    Text("Menu button 2")
                }

            } label: {
                Text("Menu")
            } primaryAction: {}
            .buttonStyle(NoHighlightButtonStyle())
            .foregroundColor(.white)
            .padding(.horizontal, 15)
            .padding(.vertical, 10)
            .background(Color.blue)
            .cornerRadius(8)
        }
    }
}


النتيجة

كما لاحظت في الفيديو السابق تم ازالة في Highlight
واصبح لا يظهر عند الضغط مره واحده على الـ Menu

كيفية تثبت عناصر الـ Menu

هذه الجزئية اضافية بما انه المقال عن الـ Menu
من iOS 16 ، تم اضاف امكانية تثبيت عناصر الـ Menu

عشان تتضح النقطه ، اذا اضفت Menu ضمن الـ List مثلا
في بداية الـ List سوف تظهر الـ Menu بترتيب معين
وعند نهاية الـ List سوف تظهر بترتيب مختلف

مثال للمشكلة اضفت Spacer مره اعلى الـ VStack ومره اسفله ، لاحظت تغيير ترتيب العناصر

الان سوف اقوم بإضافة meunOrder
خارج اقواس الـ Menu

.menuOrder(.fixed)


النتيجة

كما تلاحظ ترتيب العناصر اصبح كما هو في الصورتين