Tunko Development Diary

[SwiftUI] iOS14 SwiftUI 2.0 List 구분선(separator line) 없애기 본문

Development/iOS 개발

[SwiftUI] iOS14 SwiftUI 2.0 List 구분선(separator line) 없애기

Tunko 2021. 2. 24. 20:55

사실 간단해보이는 이슈라 적용전엔 블로그에 올릴생각이 없었습니다.
하지만……
많은 삽질을 통해 저와 같은 경험을 하게 되는 분들을 위해 이글을 남깁니다.

기존 iOS13에선 view init에서 요렇게 한줄 넣어주면 깔끔하게 separator line가 사라진것을 확인할 수 있었습니다.

// 사용하지 마세요 ㅠㅠ
UITableView().appearance().separatorStyle = .none

하지만, iOS14, SwiftUI 2.0에 들어와서는 해당 코드가 재대로 동작하지 않습니다.

테스트에 사용되는 cell View의 코드입니다.

struct ToDoItem: Identifiable
{
    var id = UUID()
    var task: String
    var imageName: String
}

...
// 데이터 초기화
var listData: [ToDoItem] = []

init()
{
    for index in 1...15 {listData.append(ToDoItem(task: "task\(index)", imageName: "command"))
    }
}
import SwiftUI

struct TestListCell: View {
    var item: ToDoItem?

    init(_ item: ToDoItem) {
        self.item = item
    }

    var body: some View {
        HStack {
            Image(systemName: item!.imageName)
            Spacer()
            Text("\(item!.task)")
        } 
    }
}

방법 1 (스타일이용)

iOS 14.4 부터 해당 코드가 적용되어 손쉽게 없앨 수 있습니다.
하지만 부작용이 있습니다.
배경색이 불투명 상태가 되며
콘텐츠의 크기가 기본 목록행과 동일해집니다.

.listStyle(SidebarListStyle())

예제 코드

struct TestListContent: View {

    var listData: [ToDoItem] = []

    init()
    {
        for index in 1...15 {
            listData.append(ToDoItem(task: "task\(index)", imageName: "command"))
        } 
    }

    var body: some View {
        VStack { 
            List(listData) { item in
                TestListCell(item)
            }
            .listStyle(SidebarListStyle())
        }
    }
}

위와 같은 결과는 납득하기 어렵습니다.

방법 2

아래 코드를 추가

struct HideRowSeparatorModifier: ViewModifier {

    static let defaultListRowHeight: CGFloat = 44

    var insets: EdgeInsets
    var background: Color

    init(insets: EdgeInsets, background: Color) {
        self.insets = insets

        var alpha: CGFloat = 0
        UIColor(background).getWhite(nil, alpha: &alpha)
        assert(alpha == 1, "Setting background to a non-opaque color will result in separators remaining visible.")
        self.background = background
    }

    func body(content: Content) -> some View {
        content
            .padding(insets)
            .frame(
            minWidth: 0, maxWidth: .infinity,
            minHeight: Self.defaultListRowHeight,
            alignment: .leading
        )
            .listRowInsets(EdgeInsets())
            .background(background)
    }
}

extension EdgeInsets {

    static let defaultListRowInsets = Self(top: 0, leading: 16, bottom: 0, trailing: 16)
}

extension View {

    func hideRowSeparator(
        insets: EdgeInsets = .defaultListRowInsets,
        background: Color = .white
    ) -> some View {
        modifier(HideRowSeparatorModifier(
            insets: insets,
            background: background
            ))
    }
}

예제 코드를 수정

struct TestListContent: View {

    var listData: [ToDoItem] = []

    init()
    {
        for index in 1...15 {
            listData.append(ToDoItem(task: "task\(index)", imageName: "command"))
        }  
    }

    var body: some View {
        VStack {
            List(listData) { item in
                TestListCell(item)
            }
            .listStyle(SidebarListStyle())
            Spacer()
            List {
                ForEach(0..<listData.count) { index in
                    TestListCell(listData[index])
                        .hideRowSeparator()
                }
            }
        }
    }
}

위코드를 보면 List 가 두개 있습니다.
List 생성자에 데이터 배열을 넘기지 않고
ForEach 를 사용해서 데이터를 출력했습니다.
List 생성자를 사용하면 ViewModifier가 정상 적용되지 않았습니다.

 

참고 : [stackoverflow.com/a/62652729/12913140]

반응형
Comments