Skip to content

Instantly share code, notes, and snippets.

@Chronos2500
Created August 14, 2025 13:13
Show Gist options
  • Select an option

  • Save Chronos2500/2bc3b385f5147170eac8698bb35ea3e0 to your computer and use it in GitHub Desktop.

Select an option

Save Chronos2500/2bc3b385f5147170eac8698bb35ea3e0 to your computer and use it in GitHub Desktop.

Revisions

  1. Chronos2500 created this gist Aug 14, 2025.
    95 changes: 95 additions & 0 deletions FullSheet.Swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,95 @@
    import SwiftUI

    struct FullSheet: View {
    @State private var isPresented: Bool = false
    @Namespace private var namespace
    var body: some View {
    TabView {
    Tab("Home", systemImage: "house") {
    NavigationStack {
    list
    .navigationTitle("Home")
    }
    }
    Tab("Search", systemImage: "magnifyingglass") {
    }
    Tab("Profile", systemImage: "person.circle") {
    }
    Tab(role: .search) {
    }
    }
    .tabViewBottomAccessory {
    Button("Show Full Sheet") {
    isPresented.toggle()
    }
    // この効果を使うとZoom効果が適用されますが、現状のAppleMusicでは使われていないので消しました
    // .matchedTransitionSource(id: "sheet", in: namespace)
    // AppleMusicに寄せるには追加でカスタムVCのTransitionを書く必要があります
    }
    .sheet(isPresented: $isPresented) {
    VStack {
    Text("This is a full sheet")
    .font(.title)
    .padding()
    Button("Dismiss") {
    isPresented = false
    }
    .buttonStyle(.borderedProminent)
    }
    .foregroundColor(.white)
    // .navigationTransition(.zoom(sourceID: "sheet", in: namespace))
    .presentationBackground(.pink.gradient)
    .fullDetentSheet()
    }
    }
    var list: some View {
    List {
    ForEach(0..<20) { index in
    Text("Item \(index)")
    }
    }
    }
    }

    extension View {
    public func fullDetentSheet() -> some View {
    modifier( FullDetentSheetModifier() )
    }
    }

    fileprivate struct FullDetentSheetModifier: ViewModifier {
    func body(content: Content) -> some View {
    content.background{ VCWrapper() }
    }
    }

    fileprivate struct VCWrapper: UIViewControllerRepresentable {
    @MainActor final class DummyVC: UIViewController {
    override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .clear
    view.isUserInteractionEnabled = false
    }
    override func didMove(toParent parent: UIViewController?) {
    super.didMove(toParent: parent)
    parent?.sheetPresentationController?.detents = [ .full() ]
    }
    }

    func makeUIViewController(context: Context) -> DummyVC {
    .init()
    }
    func updateUIViewController(_ uiViewController: DummyVC, context: Context) {
    }
    }

    fileprivate extension UISheetPresentationController.Detent {
    static func full() -> UISheetPresentationController.Detent {
    value(forKey: "_\("full")Detent") as! UISheetPresentationController.Detent
    }
    }


    #Preview {
    FullSheet()
    }
    2 changes: 2 additions & 0 deletions ReadMe.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,2 @@
    #### SheetをDismiss後Bottom Accessoryに吸い込まれるようなApple Musicの効果はおそらくAPI化されていないので再現していません🙇
    #### The Apple Music effect where the sheet gets absorbed into the bottom accessory after dismissal probably isn’t API-ized, so I haven’t reproduced it 🙇