CatHand Blog

アプリ開発やMac弄り

SwiftUIのListのseparatorを消す

SwiftUIの List はデフォルトでセパレータ(区切り線)が表示されていて、非表示にすることができません。

iOS13

iOS13では、以下のどちらかの方法で消すことができます。

UITableView のappearanceを変更する

        List {
            ListItem(title: "タイトル1")
            ListItem(title: "タイトル2")
            ListItem(title: "タイトル3")
            ListItem(title: "タイトル4")
        }
        .onAppear {
            UITableView.appearance().separatorStyle = .none
        }
        .onDisappear {
            UITableView.appearance().separatorStyle = .singleLine
        }

こんなかんじで onAppearonDisappearseparatorStyle を切り替えることで消すことができます。

注意点としては、アプリ全体の設定が変わるので、全ての ListUITableView が影響を受けます。

Introspect を使う

        List {
            ListItem(title: "タイトル1")
            ListItem(title: "タイトル2")
            ListItem(title: "タイトル3")
            ListItem(title: "タイトル4")
        }
        .introspectTableView { tableView in
            tableView.separatorStyle = .none
            tableView.tableFooterView = .init()
        }

Introspectで UITableView にアクセスできるので、 separatorStyle を設定できます。

iOS14

iOS14ではiOS13の方法どちらを使っても消すことはできません。

listRowInsetsbackground を使う

ListItem に対し、

        ListItem(title: "タイトル1")
            .listRowInsets(.init(top: -1, leading: 0, bottom: -1, trailing: 0))
            .background(bgColor)

とすると一応消せます。ViewModifierで書くとこんなかんじ。

struct RemoveSeparatorModifier: ViewModifier {
    
    let bgColor: Color
    
    func body(content: Content) -> some View {
        content
            .listRowInsets(.init(top: -1, leading: 0, bottom: -1, trailing: 0))
            .background(bgColor)
    }
}

extension View {
    
    func removeSeparator(bgColor: Color = .white) -> some View {
        modifier(RemoveSeparatorModifier(bgColor: bgColor))
    }
}
        ListItem(title: "タイトル1")
            . removeSeparator()

この実装には以下のような問題があります。

  • デフォルトのinsetsを上書きするので、別途レイアウトが必要。
  • bgColorで覆うので、タップ時にセルハイライトされない。ハイライトが必要な場合は別途実装が必要。
  • Sectionとか使う場合にはさらに調整が必要。

LazyVStackを使う

LazyVStack が使える場合は LazyVStack を使った方が幸せになれます。