핀수로그
  • [SwiftUI] 인스타그램 UI 클론 코딩
    2023년 02월 03일 23시 13분 30초에 업로드 된 글입니다.
    작성자: 핀수
    728x90
    반응형

    그동안 Swift와 SwiftUI(이하 스유)에 대해 알아보는 시간을 가졌다.

    그러나 백문이불여일코...!!!

    직접 해보는 것만큼 좋은 공부가 어디 있겠는가?

    그래서 일단 스유에 익숙해지기 위해 클론 코딩을 해보기로 했다.

    따라서 이 글은 정보성이기 보다는...그냥 내 삽질노트 같은 거다.

    * 잘못된 정보가 다수 포함되어 있을 수 있음 * 

    원본

    *참고 : 하단의 댓글 달기..부분은 구현하지 않았다.

    인스타그램의 모든 화면을 다 만들면 시간이 없으니까 일단 메인화면만 만들어보겠다.

    완성본

    하단 네비게이션 만들기

    안드로이드에서는 바텀네비게이션뷰라고 불리었다

    스유에서는 TabView로 바텀 네비게이션 뷰를 구현할 수 있다.

    공식 문서에 나온 예제

    각 ChildView 를 먼저 만들고, 각 ChildView를 TabView안에 감싸주면 된다.

    아이콘은 그냥 SF Symbols에서 제공하는 거 갖다 썼다.

    TabView {
        MainView()
            .tabItem {
                Label("", systemImage: "house")
            }
        SearchView()
            .tabItem {
                Label("", systemImage: "magnifyingglass")
            }
        ShotsView()
            .tabItem {
                Label("", systemImage: "film")
            }
        ShopView()
            .tabItem {
                Label("", systemImage: "bag")
            }
        MyPageView()
            .tabItem {
                Label("", systemImage: "person.circle")
            }
    }

    아이콘이 다른 점을 양해바란다

    각 라벨을 클릭하면 각각 화면으로 잘 이동한다.

    아주...쉽죠?

    메인 화면을 얼추 만들고 확인해보니 백그라운드에 색상이 들어가있는 걸 확인했다.

    배경 색깔이...왜이래..?

    그리고 라벨이 묘하게...너무....위로 바짝 붙어있지 않나...?

    TabView 배경색상 바꾸기

    찾아봤는데 나의 구글링 실력 부족탓인지 정석 방법은 찾을 수 없었고,

    약간의 꼼수(?)를 통해 변경하는 것을 알아왔다.

    TabView.onAppear{
        UITabBar.appearance().barTintColor = .white
    }

    TabView가 onAppear 상태일 때 해당 탭 바의 색상을 white로 지정

    TabView 라벨 중앙정렬

    이거...못찾았다....How to align TabView vertically center?

    클릭 시 색상 바꾸기

    위 이미지를 보면 알 수 있듯 기본 색상은 파란색이다.

    인스타그램은 검은색이기 때문에 검은색으로 바꿔보자.

    View.accentColor를 통해 변경이 가능했는데, 사용하려고 하니 deprecated 되었단다.

    View.tint 속성을 사용해 변경하면 된다.

    상단 로고

    이미지 추가 및 정렬하기

    이미지를 추가하는 법은 간단하다.

    Xcode의 Assets 파일에 이미지를 추가하면 된다.

    이미지 파일을 해당 공간에 드래그 하거나, 우클릭 후 import 하면 된다.

    그리고 해당 이미지의 이름을 써주면 된다.

    Image("ImageName")

    ?

    이미지 크기 조절하기

    resizable

    이미지를 현재 View에 딱 맞게 채워준다.

    aspectRatio

    이미지의 비율을 유지시켜주는 View Modifier

    이미지가 찌그러지는 문제를 해결해준다. 인자로 contentMode 를 전달해야한다.

    .fit 속성을 사용하면

    이미지가 너무 커서 자리를 다 차지한다.

    크기를 조절하려면 frame 메소드를 사용하면 된다.

    frame

    인자로 width와 height를 전달할 수 있다.

    또 alignment 속성으로 정렬도 가능하다.

    안드로이드에서는 start, end 또는 left, right 로 지정하지만

    iOS는 leading이 왼쪽, trailing이 오른쪽이라고 한다. (top, bottom, center는 다들 아는거니까 패쓰)

     

    원하는 크기를 지정했는데..계속 가운데 정렬이라서 정렬을 다시 해주고 싶었다.

    그러려면 각 View가 차지하는 공간이 wrap이 아니라 match 거나 크기가 view보다는 커야한다.

    설명을…안드로이드처럼 할 수 밖에 없네….끙

     

    이때 또 frame 메소드의 maxWidth 인자를 통해서 지정할 수 있다.

    .infinity 로 설정하면 자기가 가질 수 있는 최대 공간을 차지한다.

    그러니까 만약 뷰가 다섯개 있는데 모두 해당 속성을 가지면 공간을 공평하게 5등분해서 차지하는 것임

    ConstraintLayout에 weight 설정하는 거랑 비슷한듯

     

    버튼 색상 변경하기

    View.tint 로 색상을 변경할 수 있다.

    재사용할 수 있도록 만들기

    원본을 보면 알겠지만 버튼이 세개다.

    그말인 즉슨 각 버튼마다 속성을 지정해주어야 한다는 것 -> 번거롭다.

    재사용 가능하도록 만들어준다.

    struct MainButton: View {
        var labelName: String
        var buttonAction: () -> Void
        
        var body: some View {
            Button {
                buttonAction()
            } label: {
                Image(systemName: labelName)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 25)
            }
            .tint(.black)
            .padding(10)
        }
    }

    labelName과 버튼을 클릭시 트리거 되는 action 부분을 해당 View 생성시 받아준다.

    MainButton(labelName: "plus.app") {
        // action
    }

    이렇게 사용해주자

    스토리

    가로 스크롤 가능하도록 만들기

    ScrollView를 사용하면 스크롤이 가능한 레이아웃을 만들 수 있다.

    기본 설정은 Vertical 이므로 인자에 horizental을 넘겨주면 가로 스크롤이 가능하다.

    ScrollView(.horizontal){
        HStack {
            ForEach (1..<10) { _ in
                StoryView()
            }
        }// VStack
    } // horizontal ScrollView

    ForEach 를 이용해서 임의로 10개 정도를 만들어줬다.

    재사용할 수 있도록 만들기

    유저 이미지는 추후 피드의 프로필 이미지로도 쓰여야 하니까 재사용할 수 있도록 만들어주자!

    크기만 나중에 정할 수 있게 해주면 되지 않을까?

    아까 만든 StroyView를 보면

    struct StoryView: View {
        var body: some View {
            VStack {
                // 이 부분 컴포넌트로 만들기
                Image("user")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 70.0)
                    .clipShape(Circle())
                Text("user")
            }
            .padding(8)
        }
    }

    여기서 Image만 따로 빼줄 것이다.

    크기만 생성할 때 받으면 되니까 변수로 만들어준다.

    struct UserProfileComponent: View {
        var imageWidth: CGFloat
        var body: some View {
            Image("user") // 이미지를 불러올거면 이부분도 나중에 받기
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: imageWidth)
                .clipShape(Circle())
        }
    }

    Image.clipShape(Circle()) 속성을 사용하면 이미지를 동그랗게 잘라준다.

    스토리 하단 선 만들기

    스토리 영역 하단에 선이 하나 있다.

    선은 어떻게 그을까?

    Divider() 를 사용하면 된다.

    피드

    인디케이터는 생략하겠다

    피드는 앞의 것들을 만들면서 크게 어렵지 않게 만들 수 있게 되었으므로 여기 기술하지 않겠다.

     

    마치며

    제대로...알고나 만든건지는 알 수 없지만...이렇게 계속 만들어보면서 실력도...느는 거라구 생각한다....

    확실히 직접 만드는 게 재밌다. 이제는 서버하고 통신하면서 하나씩 더 깨우쳐나가 볼 생각이다~~_~~


    공부하며 작성된 글이라 잘못된 정보가 있을 수 있습니다.

    말씀해주시면 수정하겠습니다. 감사합니다.

    References

    아래 글을 참고하여 작성 되었습니다.

    https://mila00a.tistory.com/44

    https://huniroom.tistory.com/entry/SwiftUI-alignment-%EC%A0%95%EB%A6%AC

    https://seons-dev.tistory.com/entry/HStack

    https://medium.com/devtechie/tabview-in-swiftui-f582fd5c6e88

    https://seons-dev.tistory.com/entry/SwiftUI-Text

    https://seons-dev.tistory.com/entry/ScrollView

     

     

     

     

     

     

    728x90
    반응형

    'iOS' 카테고리의 다른 글

    [SwiftUI] 인스타그램 UI 클론 코딩2  (0) 2023.02.06
    [iOS] 라이브러리 설치하기  (0) 2023.01.21
    댓글