# iOS 應用程式開發入門 HW1 Select a APP in the APP Store and make a UI that is as same as the APP, the APP I chose is Dcard. - [Github Link](https://github.com/Ateto1204/DcardUI-iOS.git) - [Medium Link](https://medium.com/@tonysu1204/ios-%E6%87%89%E7%94%A8%E7%A8%8B%E5%BC%8F%E9%96%8B%E7%99%BC%E5%85%A5%E9%96%80-hw1-98b1e7516925) ## Comparing the UI in Dcard to what I imitated I took the screenshot on my iPhone, but I developed my APP on iPad. APPs developed on iPad seem to be only suitable to iPad, so the interface what I uploaded is horizontal. ### The interface I made: ![](https://hackmd.io/_uploads/Skr-QXBxp.jpg) ### The screenshot from iPhone on Dcard: ![](https://hackmd.io/_uploads/S1sHfmHl6.png =300x) ### The screenshot from iPad on Dcard: Since my interface is based on iPhone screenshot, this screenshot is only for reference to what the interface looks like on iPad. ![](https://hackmd.io/_uploads/r1kI-ESla.jpg) ## The important points what I do in this UI (摘要) 所有的 components 都是一個一個拼上去的: - SearchBox 裡面的提示文字是用放大鏡 `Image` 加上 `Text` 而不是整片截圖直接貼上去。 - SearchBox 有用 `clipShape()`、`RoundedRectangle()` 和 `cornerRadius` 去切邊角。 - AD 上方熱門選單兩側的火花和 arrow 是分開拼上去的而不是整塊截圖直接貼上去。 - 上排選單,選項 "全部" 底下的藍色橫槓有做出來。 - 文章原po 頭貼、藍勾勾認證 icon、互動 emoji & icon 都是一個一個拼上去的。 - 文章置頂 hashtags 是用 `RoundedRectangle` 疊上 `Text` 而非整塊截圖直接貼圖片上去。 - 第二篇文章的互動 emoji 是把 `love` 和 `laugh` 兩個 emoji 是用 `HStack` 疊起來而不是截整塊圖直接貼上去。 - 下排選單的 icon 是一個一個拼上去的,再用 `UI.main.bounds.width` 去排出來的,而不是整條截圖貼上去,另外 - 下排選單 Notifications 上方的紅點是用 `ZStack` 疊上去的不是整塊截圖直接貼上去。 p.s. 上排選單也是 - 貼文附圖有用 `clipShape()`、`RoundedRectangle()` 和 `cornerRadius` 去切邊角。 - 所有文字和圖片位置都幾乎與 Dcard 的相同,沒有因為用 `alignment` 就直接整個和左右側整個貼齊,如:SearchBox 兩側有留空白,並且不是用 `frame()` 直接定義 `Rectangle()` 的 `width`、右下 po文 buttom 有和右側 edge 及下排選單留出間隔而沒有整個貼齊。 - 第 $3$ 篇貼文也有做,只是被下排選單遮住而看不到,貼文程式碼位於第 $299$ 行,並且該篇貼文的互動 emoji 都和從 iPhone 截圖上的一樣。 $$ log_😄~😅~=💧 $$ ### Code of the UI ```swift= import SwiftUI struct ContentView: View { var body: some View { ZStack { ZStack (alignment: .top) { let backgroundColor = Color(red: 242/255, green: 243/255, blue: 244/255) let dcardBlue = Color(red: 0, green: 106/255, blue: 166/255) let searchBox = Color(red: 0, green: 92/255, blue: 144/255) let searchFont = Color(red: 108/255, green: 161/255, blue: 190/255) backgroundColor .ignoresSafeArea() VStack (spacing: 5) { // Search window ZStack (alignment: .bottom) { Rectangle() .frame(height: 80) .foregroundColor(dcardBlue) VStack (spacing: 0) { HStack (spacing: 0) { Rectangle() .frame(width: 10, height: 20) .foregroundColor(dcardBlue) // Search box ZStack (alignment: .leading) { Rectangle() .frame(height: 25) .foregroundColor(searchBox) .clipShape(RoundedRectangle(cornerRadius: 5)) HStack (spacing: 3) { Image("SearchIcon") .resizable() .frame(width: 20, height: 20) Text("Iphone 保護貼") .font(.system(size: 13)) .foregroundColor(searchFont) } } Rectangle() .frame(width: 10, height: 20) .foregroundColor(dcardBlue) } Rectangle() .frame(height: 5) .foregroundColor(dcardBlue) } } // Top menu ZStack { let widthSize = UIScreen.main.bounds.width Rectangle() .frame(height: 38) .foregroundStyle(.white) HStack (spacing: widthSize/5) { Text("推薦") .foregroundColor(.gray) .font(.system(size: 15)) .bold() VStack { Rectangle() .frame(width: widthSize/5, height: 2) Text("全部") .foregroundColor(.black) .font(.system(size: 15)) .bold() // Bottom line Rectangle() .frame(width: widthSize/5, height:2) .foregroundColor(dcardBlue) } Text("追蹤") .foregroundColor(.gray) .font(.system(size: 15)) .bold() Text("主題") .foregroundColor(.gray) .font(.system(size: 15)) .bold() } } // Sorting bar ZStack (alignment: .leading) { Rectangle() .frame(height: 25) .foregroundColor(backgroundColor) HStack { Rectangle() .frame(width: 3, height: 25) .foregroundColor(backgroundColor) HStack (spacing: 3) { Image("Fire") .resizable() .frame(width: 15, height: 15) Text(" 熱門") .font(.system(size: 12)) .foregroundColor(.gray) .bold() Image("Arrow") .resizable() .frame(width: 15, height: 15) } } } // Advertisement Image("Ad") .resizable() .scaledToFill() // Post_1 ZStack (alignment: .leading) { Rectangle() .frame(height: 105) HStack { Rectangle() .frame(width: 10, height: 100) VStack (alignment: .leading, spacing: 5) { // Poster_1 informations HStack (spacing: 0) { Image("User1") .resizable() .frame(width: 20, height: 20) Text(" 好物・平價小管家") .foregroundColor(.gray) .font(.system(size: 12)) Image("Flag") .resizable() .frame(width: 16, height: 16) Text("・21 小時前 ") .foregroundColor(.gray) .font(.system(size: 12)) ZStack { RoundedRectangle(cornerRadius: 4) .frame(width: 30, height: 16) .foregroundColor(.gray) Text("置頂") .font(.system(size: 11)) } } // Post_1 contents Text("What's in my bag? 外出必備好物大公開") .foregroundColor(.black) .font(.system(size: 14)) .bold() Text("大家好~我是平價小管家~大家是否和小管家...") .foregroundColor(.black) .font(.system(size:12)) HStack (spacing: 15) { HStack (spacing: 3) { Image("Love") .resizable() .frame(width: 18, height: 18) Text("302") .foregroundColor(.gray) .font(.system(size: 12)) .bold() } HStack (spacing: 3) { Image("Message") .resizable() .frame(width: 20, height: 20) Text("5") .foregroundColor(.gray) .font(.system(size: 12)) .bold() } HStack (spacing: 3) { Image("Keep") .resizable() .frame(width: 20, height: 20) Text("收藏") .foregroundColor(.gray) .font(.system(size: 12)) .bold() } } } } // Post_1 menu & Post_1 image ZStack (alignment: .trailing) { HStack { VStack (alignment: .trailing, spacing: 10) { Text("...") .foregroundColor(.gray) .bold() Image("Image1") .resizable() .frame(width: 60, height: 60) } Rectangle() .frame(width: 5, height: 105) } Spacer() .frame(alignment: .trailing) } } // Post_2 ZStack (alignment: .leading) { Rectangle() .frame(height: 105) HStack { Rectangle() .frame(width:10, height: 105) VStack (alignment: .leading, spacing: 5) { // Poster_2 informations HStack (spacing: 3) { Image("FemaleUser") .resizable() .frame(width: 20, height: 20) Text("心情・13 小時前") .foregroundColor(.gray) .font(.system(size: 12)) } // post_2 contents Text("朱李一家 小朱開始團購了?") .foregroundColor(.black) .font(.system(size: 14)) .bold() Text("看到小朱開始被撻伐失去初衷這件事,我想說..,其實吧,...") .foregroundColor(.black) .font(.system(size:12)) HStack (spacing: 15) { HStack (spacing: 5) { HStack (spacing: -3) { Image("Love") .resizable() .frame(width: 18, height: 18) Image("Laugh") .resizable() .frame(width: 15, height: 15) } Text("844") .foregroundColor(.gray) .font(.system(size: 12)) .bold() } HStack (spacing: 3) { Image("Message") .resizable() .frame(width: 20, height: 20) Text("133") .foregroundColor(.gray) .font(.system(size: 12)) .bold() } HStack (spacing: 3) { Image("Keep") .resizable() .frame(width: 20, height: 20) Text("收藏") .foregroundColor(.gray) .font(.system(size: 12)) .bold() } } } } // Post_2 menu ZStack (alignment: .trailing) { HStack (spacing: 0) { VStack (alignment: .trailing) { Text("...") .foregroundColor(.gray) .bold() Rectangle() .frame(width: 20, height: 60) } Rectangle() .frame(width: 12, height: 105) } Spacer() .frame(alignment: .trailing) } } // Post_3 ZStack (alignment: .leading) { Rectangle() .frame(height: 105) HStack { Rectangle() .frame(width: 10, height: 105) HStack (spacing: 35) { VStack (alignment: .leading, spacing: 5) { // Poster_3 information HStack (spacing: 3) { Image("MaleUser") .resizable() .frame(width: 20, height: 20) Text("追星・21 小時前") .foregroundColor(.gray) .font(.system(size: 12)) } // Post_3 contents Text("#新聞 布魯斯威利失智一年了......") .foregroundColor(.black) .font(.system(size: 14)) .bold() Text("去年卻傳出他因罹患「失語症」宣布息影,之...") .foregroundColor(.black) .font(.system(size:12)) HStack (spacing: 15) { HStack (spacing: 3) { HStack (spacing: -3) { Image("Love") .resizable() .frame(width: 18, height: 18) Image("Sad") .resizable() .frame(width: 15, height: 15) Image("Wow") .resizable() .frame(width: 15, height: 15) } Text("1644") .foregroundColor(.gray) .font(.system(size: 12)) .bold() } HStack (spacing: 3) { Image("Message") .resizable() .frame(width: 20, height: 20) Text("49") .foregroundColor(.gray) .font(.system(size: 12)) .bold() } HStack (spacing: 3) { Image("Keep") .resizable() .frame(width: 20, height: 20) Text("收藏") .foregroundColor(.gray) .font(.system(size: 12)) .bold() } } } } } // Post_3 menu & Post_3 image ZStack (alignment: .trailing) { HStack (spacing: 0) { VStack (alignment: .trailing) { Text("...") .foregroundColor(.gray) .bold() Image("Image2") .resizable() .frame(width: 60, height: 60) .clipShape(RoundedRectangle(cornerRadius: 10)) } Rectangle() .frame(width: 10, height: 105) } Spacer() .frame(alignment: .trailing) } } } } VStack { Spacer() .frame(alignment: .bottom) VStack (alignment: .trailing) { // Posting buttom VStack { HStack (spacing: 0) { Image("Post") .resizable() .frame(width: 45, height: 45) Rectangle() .frame(width: 12, height: 45) } Rectangle() .frame(width: 50, height: 5) } // Bottom menu ZStack (alignment: .bottom) { Rectangle() .frame(height: 100) VStack (spacing: 0) { let widthSize = UIScreen.main.bounds.width HStack (alignment: .bottom, spacing: widthSize/8) { Image("Home") .resizable() .frame(width: 30, height: 30) Image("Explore") .resizable() .frame(width: 30, height: 30) Image("Card") .resizable() .frame(width: 30, height: 30) Image("Shop") .resizable() .frame(width: 34, height: 33) // Bottom menu_Notifications ZStack (alignment: .topTrailing) { Image("Bell") .resizable() .frame(width: 30, height: 30) Text("4") .font(.system(size: 12)) .frame(width: 15, height: 15) .background(Color.red) .clipShape(Circle()) .offset(x: 5, y: -3) } Image("More") .resizable() .frame(width: 30, height: 30) } Rectangle() .frame(height: 60) } } } } } } } ``` <!-- {%hackmd /@Ateto/BJRpsqII9 %} -->