# 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 %} -->