0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[SwiftUI]サイドメニューをTab,Navigationの上に表示する

Last updated at Posted at 2025-02-25

fullScreenCoverを使用

サイドメニューがタブ等の下に表示されるので、fullScreenCoverを使って前面に表示する

swift
extension View {
    
    func sideMenu(isPresented: Binding<Bool>) -> some View {
        self.modifier(SideMenuView(isPresented: isPresented))
    }
}
swift
struct SideMenuView: ViewModifier {
    
    @Binding var isPresented: Bool
    @State var showSideMenu: Bool = false
    
    private let width: CGFloat = 270
    
    func body(content: Content) -> some View {
        content
            .fullScreenCover(isPresented: self.$isPresented) {
                let bounds = UIScreen.main.bounds
                let screenWidth = bounds.width
                ZStack {
                    GeometryReader { _ in EmptyView() }
                        .background(Color.gray.opacity(0.3))
                        .opacity(self.showSideMenu ? 1.0 : 0.0)
                        .opacity(1.0)
                        .animation(.easeIn(duration: 0.25), value: showSideMenu)
                        .onTapGesture {
                            self.showSideMenu = false
                        }
                    HStack {
                        VStack {
                            // TODO: リスト部分
                            Spacer()
                        }
                        .frame(width: width)
                        .background(.white)
                        .offset(x: self.showSideMenu ? screenWidth - self.width : screenWidth)
                        .animation(.easeIn(duration: 0.25), value: self.showSideMenu)
                        Spacer()
                    }
                }
                .background(BackgroundTranslucentView())
            }
            .onChange(of: self.isPresented) { _, newValue in
                if newValue {
                    DispatchQueue.main.async {
                        self.showSideMenu = true
                    }
                }
            }
            .onChange(of: self.showSideMenu) { _, newValue in
                if !newValue {
                    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                        var transaction = Transaction()
                        transaction.disablesAnimations = true
                        withTransaction(transaction) {
                            self.isPresented = false
                        }
                    }
                }
            }
    }
}
swift
struct BackgroundTranslucentView: UIViewRepresentable {
    
    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        DispatchQueue.main.async {
            view.superview?.superview?.backgroundColor = .black.withAlphaComponent(0.2)
        }
        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {}
}

注意

isPresentedをtrueにする際はwithTransactionで囲んでfullScreenCoverのアニメーションをしないようにする

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?