1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ListでのNavigationLinkとButtonを使った画面遷移

Posted at

List 内で NavigationLink で isActive を使用し、 Button で isActive を管理した時に isActiveが機能しなくなることがあったので対処法を記しておきます。

Listを使用しないときの NavigationLink と Button の組み合わせ

List を使用しない場合、 NavigationLink と Button を併用し isActive の Bool値を falase で固定すると、当然ですが画面遷移は起きません。

ContentView
 struct ContentView: View {
    @State var openDetailView = false
    
    var body: some View {
        ZStack {
            NavigationLink(
                destination: DetailView,
                isActive: $openDetailView,
                label: { EmptyView() }
            )
            Button(action: {
                //self.openDetailView = true
            }, label: {
                Text("画面遷移")
            })
        }
    }
    
    var DetailView: some View {
        Text("DetailView")
    }
}

上記のコードのListを追加する

では、上記のコードにListを追加してみます。

ContentView
struct ContentView: View {
    @State var openDetailView = false
    @State var selectedIndex = 0
    
    var body: some View {
        List(1..<11) { index in
            ZStack {
                NavigationLink(
                    destination: DetailView,
                    isActive: $openDetailView,
                    label: { EmptyView() }
                )
                Button(action: {
                    //self.openDetailView = true
                    selectedIndex = index
                }, label: {
                    Text("\(index)の画面遷移")
                })
            }
        }
    }
    
    var DetailView: some View {
        Text("\(selectedIndex)のDetailView")
    }
}

ここに List を追加すると isActive の値が false であるにも関わらず画面遷移が発生してしまします。

Listを使用した NavigationLink と Button のベストプラクティス

NavigationLink と ZStack を List の外に出すことで isActive を挙動通りに動かすことができます。

ContentView
struct ContentView: View {
    @State var openDetailView = false
    @State var selectedIndex = 0
    
    var body: some View {
        ZStack {
            NavigationLink(
                destination: DetailView,
                isActive: $openDetailView,
                label: { EmptyView() }
            )
            
            List(1..<11) { index in
                Button(action: {
                    //self.openDetailView = true
                    selectedIndex = index
                }, label: {
                    HStack {
                        Text("\(index)の画面遷移")
                        Spacer()
                        Image(systemName: "chevron.right")
                    }
                })
            }
        }
    }
    
    var DetailView: some View {
        Text("\(selectedIndex)のDetailView")
    }
}

コメントアウトを外せば挙動通り、画面遷移が行われます。

NavigatoinView の定義

NavigationView がないと NavigationLink は機能しないので、定義する必要があります。
ContentViewで使用しても良いですし、

ContentViewで使用する場合
var body: some View {
        ZStack {
            NavigationLink(
                destination: DetailView,
                isActive: $openDetailView,
                label: { EmptyView() }
            )
            Button(action: {
                //self.openDetailView = true
            }, label: {
                Text("画面遷移")
            })
        }
    }

{アプリ名}App.swift ファイルに指定してもOKです。

{アプリ名}Appの場合
@main
struct App: App {
  var body: some Scene {
    WindowGroup {
      NavigationView {
        ContentView()
      }
    }
  }
}
1
2
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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?