การพัฒนาส่วนต่อประสานของแอปมือถือเริ่มต้นด้วยการทำความเข้าใจส่วนประกอบ UI และเฟรมเวิร์ก บทความนี้ครอบคลุม Material Design, Human Interface Guidelines, SwiftUI, Jetpack Compose, Flutter Widgets, ระบบหน่วยวัด (dp, sp, pt, px) และองค์ประกอบ UI ที่สำคัญทั้งหมด — ตั้งแต่ NavigationView และ RecyclerView ไปจนถึง Safe Area และ Dark Mode เนื้อหานี้เหมาะสำหรับผู้เริ่มต้นที่เปลี่ยนจากทฤษฎีไปสู่โปรเจกต์แรกของพวกเขา สำหรับรายละเอียดเพิ่มเติม โปรดดู เอกสารทางการของ Material Design
ประเด็นสำคัญ
แต่ละแพลตฟอร์มมีชุดกฎและส่วนประกอบของตัวเอง สำหรับ Android นั่นคือ Material Design ซึ่งพัฒนาโดย Google ในปี 2014 Material Design ใช้คำอุปมาของวัสดุทางกายภาพ — ชั้น, เงา (Elevation), การเปลี่ยนภาพแบบเคลื่อนไหว และเค้าโครงที่ปรับเปลี่ยนได้ หลักการสำคัญรวมถึงลำดับชั้นผ่านความสูง, การเคลื่อนไหวที่มีความหมาย และความสามารถในการปรับให้เข้ากับฟอร์มแฟคเตอร์ต่างๆ เราขอแนะนำให้สำรวจ Material Design 3 (Material You) — เวอร์ชันล่าสุดที่มีธีมไดนามิกและสีส่วนบุคคล
Apple นำเสนอ Human Interface Guidelines (HIG) — ชุดกฎสำหรับ iOS, iPadOS, macOS, watchOS และ tvOS HIG เน้นการพิมพ์ที่ชัดเจน (San Francisco), Safe Area เพื่อรองรับ Notch และ Dynamic Island, การนำทางด้วยท่าทาง และความสอดคล้อง แตกต่างจาก Material Design ตรงที่ HIG ไม่ใช้ "ชั้น" และ Elevation — แต่ใช้ความเบลอ (vibrancy), เงา และตัวคั่นที่ละเอียดอ่อนแทน เอกสาร HIG ฉบับสมบูรณ์ ได้รับการอัปเดตเป็นประจำกับ iOS รุ่นใหม่
ที่ IT Sectr เราใช้ทั้งสองระบบการออกแบบขึ้นอยู่กับแพลตฟอร์มของลูกค้า สำหรับโปรเจกต์ข้ามแพลตฟอร์ม Flutter เราพัฒนาระบบการออกแบบแบบรวมที่รวมแนวทางปฏิบัติที่ดีที่สุดของ Material Design และ HIG วิธีการนี้รักษา UX ดั้งเดิมบนแต่ละแพลตฟอร์มโดยไม่ต้องทำซ้ำโค้ด
วิธีการแบบดั้งเดิมในการสร้าง UI คือเค้าโครงแบบจำเป็นผ่าน XML (Android) หรือ Interface Builder / โค้ด (iOS) ทางเลือกสมัยใหม่คือ เฟรมเวิร์กแบบประกาศ ซึ่งนักพัฒนาอธิบายว่าส่วนต่อประสานควรมีลักษณะอย่างไรในแต่ละสถานะ และเฟรมเวิร์กจัดการกับการอัปเดต
Jetpack Compose เป็นชุดเครื่องมือที่ทันสมัยจาก Google สำหรับสร้าง UI ดั้งเดิมใน Kotlin แทนที่จะใช้เค้าโครง XML จะใช้ฟังก์ชันประกอบได้ของ Kotlin (@Composable) Compose เป็นแบบประกาศอย่างสมบูรณ์: เมื่อข้อมูลเปลี่ยนแปลง เฉพาะส่วนที่เปลี่ยนแปลงของหน้าจอเท่านั้นที่ถูกวาดใหม่ ตัวอย่างหน้าจออย่างง่ายพร้อมข้อความและปุ่ม:
@Composable
fun GreetingScreen() {
var count = remember { mutableStateOf(0) }
Column {
Text(text = "Нажато: $count")
Button(onClick = { count++ }) {
Text("Нажми меня")
}
}
}
SwiftUI เป็นเฟรมเวิร์กแบบประกาศของ Apple ที่เปิดตัวในปี 2019 ทำงานบนทุกแพลตฟอร์มของ Apple (iOS, iPadOS, macOS, watchOS, tvOS) ผ่าน API แบบรวม SwiftUI ใช้โครงสร้าง View, คุณสมบัติ @State และ @Binding สำหรับการจัดการข้อมูล และตัวปรับแต่งสำหรับการจัดแต่งทรงผม เทียบเท่ากับตัวอย่างด้านบนใน SwiftUI:
struct GreetingView: View {
@State private var count = 0
var body: some View {
VStack {
Text("Нажато: \(count)")
Button("Нажми меня") {
count += 1
}
}
}
}
Flutter จาก Google ใช้ไลบรารีวิดเจ็ตของตัวเอง ทุกอย่างใน Flutter คือวิดเจ็ต — จาก padding ไปจนถึงทั้งหน้าจอ วิดเจ็ตแบ่งออกเป็น StatelessWidget (ไม่เปลี่ยนรูป) และ StatefulWidget (มีสถานะ) คอนเทนเนอร์พื้นฐานคือ Container, Row, Column, Stack Flutter ไม่ใช้ส่วนประกอบดั้งเดิมของแพลตฟอร์ม — มันวาดทุกอย่างผ่าน Skia Engine ซึ่งทำให้แน่ใจว่ารูปลักษณ์ที่สอดคล้องกันทั้งบน Android และ iOS
class GreetingWidget extends StatefulWidget {
@override
State createState() => _GreetingWidgetState();
}
class _GreetingWidgetState extends State<GreetingWidget> {
int count = 0;
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Нажато: $count'),
ElevatedButton(
onPressed: () => setState(() => count++),
child: Text('Нажми меня'),
),
],
);
}
}
แม้จะมีการแพร่กระจายของเฟรมเวิร์กแบบประกาศ แต่การทำความเข้าใจส่วนประกอบดั้งเดิมยังคงมีความสำคัญสำหรับการสนับสนุนโปรเจกต์ดั้งเดิมและการปรับแต่งเชิงลึก
การนำทางใน Android สร้างขึ้นบน Activity (หน้าจอกิจกรรม) และ Fragment (ส่วนย่อยภายใน Activity เดียว) Jetpack Navigation Component ทำให้การเปลี่ยนระหว่างหน้าจอง่ายขึ้นผ่านกราฟการนำทาง ใน iOS การนำทางถูกดำเนินการผ่าน NavigationController — สแต็กของตัวควบคุมที่มีการเปลี่ยนภาพแบบเคลื่อนไหว Tab Bar และ Bottom Navigation ช่วยให้สลับระหว่างส่วนหลักของแอป Drawer (เมนูด้านข้าง) และ Toolbar/ActionBar ใช้สำหรับการดำเนินการเพิ่มเติม Android Navigation Component ได้รับการแนะนำสำหรับโปรเจกต์ใหม่ทั้งหมด
สำหรับการแสดงข้อมูลปริมาณมาก Android ใช้ RecyclerView — คอนเทนเนอร์ที่มีประสิทธิภาพพร้อมการนำ ViewHolder กลับมาใช้ใหม่ ส่วนที่เทียบเท่าใน iOS คือ UITableView (รายการแนวตั้ง) และ UICollectionView (ตาราง) Jetpack Compose นำเสนอ LazyColumn และ LazyVerticalGrid ในขณะที่ SwiftUI มี List และ LazyVStack/LazyHStack ข้อได้เปรียบหลักของส่วนประกอบ Lazy คือการแสดงผลเฉพาะองค์ประกอบที่มองเห็นได้
| แพลตฟอร์ม | ส่วนประกอบรายการ | ส่วนประกอบตาราง | โหลดแบบขี้เกียจ |
|---|---|---|---|
| Android (View System) | RecyclerView + ListView | RecyclerView GridLayoutManager | ใช่ |
| Android (Compose) | LazyColumn | LazyVerticalGrid | ใช่ |
| iOS (UIKit) | UITableView | UICollectionView | ใช่ |
| iOS (SwiftUI) | List / LazyVStack | LazyVGrid | ใช่ |
| Flutter | ListView.builder | GridView.builder | ใช่ |
Android View System มีคอนเทนเนอร์เค้าโครงหลายแบบ: ConstraintLayout (ระบบข้อจำกัดที่ยืดหยุ่น), LinearLayout (การจัดเรียงเชิงเส้น), RelativeLayout (การวางตำแหน่งแบบสัมพัทธ์), FrameLayout (การซ้อนชั้น) ใน iOS, Core Auto Layout ใช้ระบบข้อจำกัด (NSLayoutConstraint) เพื่ออธิบายการวางตำแหน่งขององค์ประกอบ SwiftUI และ Flutter ใช้ VStack/HStack/ZStack และ Row/Column/Stack ตามลำดับ
ส่วนประกอบ UI ของอุปกรณ์มือถือแสดงผลโดยคำนึงถึงความหนาแน่นของพิกเซลที่แตกต่างกัน เพื่อให้ส่วนต่อประสานดูเหมือนกันบนทุกหน้าจอ จะใช้ หน่วยที่ไม่ขึ้นกับความหนาแน่น
| หน่วย | แพลตฟอร์ม | คำอธิบาย |
|---|---|---|
| dp | Android | พิกเซลที่ไม่ขึ้นกับความหนาแน่น — หน่วยนามธรรมเท่ากับ 1px บนหน้าจอ mdpi |
| sp | Android | พิกเซลที่ไม่ขึ้นกับสเกล — สำหรับแบบอักษร, เคารพการตั้งค่าขนาดตัวอักษรของผู้ใช้ |
| pt | iOS | จุด — หน่วยการพิมพ์, 1pt = 1px บนหน้าจอ 1x (ไม่ใช่ Retina) |
| px | ทั้งหมด | พิกเซลของหน้าจอจริง — ไม่แนะนำสำหรับเค้าโครงเนื่องจากความหนาแน่นต่างกัน |
ความหนาแน่นของหน้าจอถูกจำแนกเป็น: mdpi (160 dpi, 1x), hdpi (240 dpi, 1.5x), xhdpi (320 dpi, 2x), xxhdpi (480 dpi, 3x), xxxhdpi (640 dpi, 4x) เมื่อเตรียมรูปภาพ คุณต้องสร้างทรัพยากรสำหรับทุกความหนาแน่น: icon.png, icon_hdpi.png, icon_xhdpi.png และอื่นๆ รูปแบบเวกเตอร์ (VectorDrawable ใน Android, SF Symbols ใน iOS) แก้ปัญหาทรัพยากรแรสเตอร์หลายรายการ
ที่ IT Sectr เราใช้ปัจจัยการปรับขนาดสำหรับการส่งออกไอคอนจาก Figma: เราส่งออกที่ 1x, 2x, 3x สำหรับ iOS และ mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi สำหรับ Android ซึ่งรับประกันการแสดงผลที่คมชัดบนทุกอุปกรณ์รวมถึงแท็บเล็ตและสมาร์ทโฟนแบบพับได้
ส่วนประกอบ UI ของแอปมือถือสมัยใหม่ต้องรองรับมาตรฐานหลายอย่าง หากไม่มีสิ่งเหล่านี้ประสบการณ์ผู้ใช้จะไม่สมบูรณ์
โหมดมืด เป็นตัวเลือกบังคับในแอปพลิเคชันสมัยใหม่ Material Design 3 และ iOS 13+ มีการรองรับธีมมืดในตัว สิ่งสำคัญคือไม่ต้องกลับสี แต่ใช้จานสีแยกต่างหาก: พื้นหลังสีเข้ม, ข้อความสีสว่าง, ความคมชัดลดลงสำหรับองค์ประกอบรอง การสลับอัตโนมัติสามารถเชื่อมโยงกับธีมระบบของอุปกรณ์
iPhone สมัยใหม่มี Notch (รอยบากสำหรับกล้องหน้า) และ Dynamic Island อุปกรณ์ Android ก็มีรอยบากและมุมโค้งมน (Corner Radius) เช่นกัน Safe Area คือพื้นที่หน้าจอที่รับประกันว่าไม่มีองค์ประกอบระบบ (แถบสถานะ, ตัวบ่งชี้หน้าแรก), แถบนำทางและรอยบาก iOS ใช้ Safe Area Insets โดยอัตโนมัติ; Android ต้องการการตรวจสอบอย่างชัดเจนผ่าน WindowInsets หรือ DisplayCutout
การเข้าถึง ช่วยให้ผู้พิการสามารถใช้แอปได้ ข้อกำหนดสำคัญ: การรองรับ TalkBack (Android) และ VoiceOver (iOS), contentDescription ที่ถูกต้องสำหรับ ImageView, ความคมชัดของสีที่เพียงพอ (ขั้นต่ำ 4.5:1 สำหรับข้อความ), การรองรับ Dynamic Type (iOS) สำหรับการปรับขนาดแบบอักษร, การนำทางโดยไม่ใช้การมองเห็น และทางเลือกอื่นสำหรับท่าทาง WCAG 2.1 เป็นมาตรฐานการเข้าถึงระดับสากล
การทำให้เป็นสากล (i18n) คือการเตรียมแอปให้รองรับหลายภาษาและรูปแบบภูมิภาค การแปลเป็นท้องถิ่น (l10n) คือการแปลสตริง, วันที่, สกุลเงิน และลักษณะเฉพาะทางวัฒนธรรม Android ใช้ไดเรกทอรีทรัพยากร (values-ru, values-de), iOS ใช้ Localizable.strings และ XLIFF Flutter รองรับ flutter_localizations ด้วยไฟล์แปล ARB
การโต้ตอบแบบสัมผัสมีท่าทางมากมาย: แตะ, กดค้าง, ปัด, บีบเพื่อซูม, ดึงเพื่อรีเฟรช, ลากและวาง Android ใช้ GestureDetector, iOS ใช้ UIGestureRecognizer iOS ยังรองรับ 3D Touch (Force Touch) และ Haptic Touch พร้อมการตอบสนองแบบสัมผัสผ่าน Taptic Engine
คำถามที่พบบ่อย
Material Design (Google) ใช้คำอุปมา "วัสดุ" ที่มีเงา, ชั้น และการเปลี่ยนภาพแบบเคลื่อนไหว ในขณะที่ HIG (Apple) อาศัยความชัดเจน, Safe Area และ Dynamic Type Material Design แนะนำสำหรับ Android, HIG สำหรับ iOS การเลือกระบบการออกแบบยังส่งผลต่อการนำทาง: Android นิยมการนำทางด้านล่างและเมนูนำทางแบบดึงออก ในขณะที่ iOS นิยมแถบแท็บและตัวควบคุมการนำทาง
Jetpack Compose เป็นเฟรมเวิร์กแบบประกาศสำหรับ Android, SwiftUI สำหรับ iOS ทั้งสองใช้วิธีการแบบประกาศและทำให้การพัฒนา UI ง่ายขึ้น Compose ผสานรวมกับ Kotlin และ Android Architecture Components อย่างใกล้ชิดยิ่งขึ้น SwiftUI ผสานรวมกับ Combine และระบบนิเวศ Apple ทั้งหมด
การออกแบบที่ปรับเปลี่ยนตามอุปกรณ์เป็นวิธีการที่ส่วนต่อประสานปรับให้เข้ากับขนาดหน้าจอ, การวางแนว และความหนาแน่นของพิกเซล ใช้หน่วยสัมพัทธ์ (dp, sp, pt), Auto Layout หรือ ConstraintLayout แท็บเล็ต, อุปกรณ์พับได้ และหน้าต่างเดสก์ท็อป (iPad Stage Manager) ต้องการการปรับเพิ่มเติม: มุมมองแยก, เค้าโครงหลัก-รายละเอียด
dp (พิกเซลที่ไม่ขึ้นกับความหนาแน่น) และ sp (พิกเซลที่ไม่ขึ้นกับสเกล) ใน Android, pt (จุด) ใน iOS px คือพิกเซลฮาร์ดแวร์ dp และ pt ให้ขนาดทางกายภาพเดียวกันบนความหนาแน่นของหน้าจอที่แตกต่างกัน: mdpi (1x), hdpi (1.5x), xhdpi (2x), xxhdpi (3x), xxxhdpi (4x)
การเข้าถึงทำให้ส่วนต่อประสานใช้งานได้สำหรับผู้พิการ: การรองรับโปรแกรมอ่านหน้าจอ, ข้อความขนาดใหญ่, ความคมชัด หากไม่มี a11y แอปจะไม่ได้รับการยอมรับให้เผยแพร่ใน App Store หรือ Google Play นอกจากนี้ การเข้าถึงยังช่วยปรับปรุง UX สำหรับผู้ใช้ทุกคน — ตัวอย่างเช่น การรองรับ Dynamic Type ช่วยผู้ที่มีสายตาเลือนราง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ