見出し画像

[SwiftUI] インスタっぽいレイアウトを作ってみた

SwiftUIでインスタっぽいレイアウトを組んでみました😄
ホーム画面だけですが・・

画像1

viewの構成はこんな感じです!

アセット 1

StoryRow

ストーリーズの部分のViewです😄
横スクロールでアイコンとアカウント名を表示します!

アセット 2

struct StoryRow: View {
   var stories: [Story]
   var body: some View {
       ScrollView(.horizontal, showsIndicators: false) {
           HStack(alignment: .top, spacing: 0) {
               ForEach(self.stories) { story in
                   VStack(alignment: .center) {
                       AccountIcon(image: story.image, size: 90)
                       
                       Text(story.name)
                           .frame(width: 100)
                           .font(.caption)
                   }
                   .padding(.leading, 10)
                   .padding(.top, 15)
               }
           }
       }
   }
}

アカウントのアイコンはいろんなところで使うので、レイアウトをAccountIconというクラスにして、共通で使えるようにしています。

AccountIcon.swift

struct AccountIcon: View {
   let image: Image
   let size: CGFloat
   var body: some View {
       image
           .resizable()
           .aspectRatio(contentMode: .fill)
           .frame(width: size, height: size, alignment: .center)
           .clipShape(Circle())
   }
}

PostRow

タイムラインの部分のビューです😄
投稿の情報を縦スクロールで表示します。

アセット 3

struct PostRow: View {
   var posts: [Post]
   var body: some View {
       ScrollView(.vertical, showsIndicators: false) {
           
           ForEach(self.posts) { post in
               VStack(alignment: .leading) {
                   // アカウント情報
                   HStack {
                       AccountIcon(image: post.image, size: 30)
                       Text(post.name)
                           .font(.caption)
                           .fontWeight(.bold)
                           .frame(width: 100, alignment: .leading)
                       Spacer()
                       Image(systemName: "ellipsis")
                   }
                   .padding(.horizontal, 12.0)
                   .padding(.vertical, 5.0)
                   // 投稿画像
                   post.image.resizable()
                       .scaledToFill()
                       .frame(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.width)
                       .clipped()
                   
                   // いいねとかのアイコン
                   HStack {
                       Group {
                           Image(systemName: "heart")
                           Image(systemName: "message")
                           Image(systemName: "paperplane")
                       }
                       .padding(.trailing, 5.0)
                       Spacer()
                       Group {
                           Image(systemName: "bookmark")
                       }
                   }
                   .padding(.horizontal, 12.0)
                   .padding(.vertical, 5.0)
                   
                   // いいね!のところ
                   HStack(spacing: 0) {
                       Text("いいね!:").font(.caption)
                       ForEach(0 ..<  post.likes.count) {
                           Text(post.likes[$0]).font(.caption).fontWeight(.bold)
                           
                           if post.likes[$0] != post.likes.last {
                               Text("、").font(.caption)
                           }
                       }
                       
                   }
                   .padding(.horizontal, 12.0)
                   .padding(.vertical, 1.0)
                   
                   // 投稿テキスト
                   HStack(spacing: 0) {
                       Text(post.name)
                           .font(.caption)
                           .fontWeight(.bold)
                           .padding(.trailing, 5.0)
                       
                       Text(post.contentText).font(.caption)
                   }
                   .padding(.horizontal, 12.0)
                   .padding(.bottom, 5.0)
                   
                   Group {
                       Text("3分前").font(.caption).foregroundColor(Color.gray)
                   }
                   .padding(.horizontal, 12.0)
                   .padding(.bottom, 10.0)
               }
           }
       }
   }
}

HomeView

ホーム画面のビューです😄

struct HomeView: View {
   var body: some View {
       VStack {
           StoryRow(stories: dataStore.stories)
           Divider()
           PostRow(posts: dataStore.posts)
       }
   }
}

上記で作ったStoryRowとPostRowを追加しています。
間にあるDividerは線を表示するビューです。

ContentView

ContentViewが今回一番親になるViewです😊

struct ContentView: View {
   var body: some View {
       NavigationView {
           
           TabView {
               HomeView().tabItem { Image(systemName: "house") }
               
               Text("検索画面").tabItem { Image(systemName: "magnifyingglass") }
               Text("投稿する").tabItem { Image(systemName: "plus.app") }
               Text("いいねの情報").tabItem { Image(systemName: "heart") }
               Text("アカウント情報").tabItem { Image(systemName: "person.crop.circle.fill") }
           }
           .accentColor(.black)
           .navigationBarTitle("Otastagram", displayMode: .inline)
           .navigationBarItems(leading: Image(systemName: "camera"), trailing: Image(systemName: "paperplane"))
       }
   }
}

NavigationViewとTabViewを追加します。
今回はホーム画面だけ作ったので、TabItemにHomeViewを指定し、それ以外はとりあえずアイコンだけ表示しました。

完成

ストーリーズとタイムラインの部分をスクロールできます🎉

画像3

おまけ

アイコンは全てSF Symbolを使っています。

インストールして起動すると、こんな画面が表示されます。

スクリーンショット 2020-10-23 23.34.58

あとは使いたいアイコンを検索して、アイコン名をコピーしてImageViewのsystemNameに指定します🙂

Image(systemName: "heart")

とても簡単にバリエーション豊かなアイコンたちを使うことができます🎉

この記事が気に入ったらサポートをしてみませんか?