[iOS] การทำ Custom View ของ UITableView
สวัสดีครับ บทความนี้เป็นบทความขณะหัดเขียน iOS ของผม ซึ่งผมกำลังหัดเขียน Swift ใน Xcode เพื่อทำแอป iPhone และเพื่อสร้างความเข้าใจมากขึ้น ผมก็จะมาเขียนเรื่องต่างๆที่ได้เรียนรู้ เป็นการบันทึกความรู้และแชร์ความรู้ไปในตัว และวันนี้ได้ลองเล่น Custom UITableView ซึ่งเป็นเรื่องพื้นฐานมากๆ ก็เลยมาเขียนบล็อกไว้อ่าน หวังว่าจะมีประโยชน์กับผู้เรียนมือใหม่ด้วยกันครับ
TableView ก็เป็นลิสๆ สามารถ scroll เลื่อนได้ ใน Android ก็จะเรียกว่า ListView หรือ RecyclerView
วาง Layout
ลาก TableView มาวางใน Storyboard
ลาก TableViewCell มาวางใน TableView
กำหนด DataSource และ Delegate
กดคลิกขวาที่ TableView แล้ว กดลาก dataSource และ delegate ไปที่จุดเหลืองๆด้านบน ทำทีละอันนะ
หรือกด Ctrl แล้วลากจาก TableView ไปที่จุดเหลืองด้านบน แล้วเลือก dataSource , delegate ก็ได้
DataSource สำหรับจัดการข้อมูล
Delegate สำหรับจัดการ interaction ต่างๆ
เขียนโปรแกรมของ UITableView
ไปที่ ViewController.swift
เพิ่มการ extends class UITableViewDataSource และ UITableViewDelegate
class ViewController: UIViewController,UITableViewDataSource, UITableViewDelegate {
จากนั้นจะเขียน Error เพราะ UITableViewDataSource ต้องการให้เรา implement method ที่จำเป็น
ก็ให้เรากด Fix ซะ
จากนั้นก็จะสร้าง method ให้เรา มีสองอันคือ
numberOfRowInSection จะ return จำนวนแถว
cellForRowAt จะ return View ของแถวที่จะแสดง
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // }
จากนั้นให้เราไปกำหนด Indentifier ของ TableViewCell
ให้คลิกที่ cell ใน storyboard แล้วแก้ไข Indentifier เป็นชื่อที่ต้องการ เช่น row
ไปที่ ViewController.swift
เขียน method สำหรับ return จำนวนแถวเป็น 50
สมมุติว่าให้แสดง 50 แถว
ส่วน method ที่จะ return View
ให้สร้าง UITableViewCell ขึ้นมา ซึ่งตอนนี้จะลองใช้ default ของมัน โดยมันจะมี textLabel มาให้ 1 ตัว
ก็กำหนดค่าให้กับ textLabel นั้นได้เลย กรณีตัวอย่างนี้ผมจะแสดงค่าเลข index
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 50 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let row = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "row") row.textLabel?.text = "Row = \(indexPath.row)" return row } // }
รันดูผลลัพธ์ครั้งแรก ไม่มีอะไรผิดพลาดก็จะแสดง TableView ที่มี 50 แถว
ทำ Custom View
จากนั้นมาวาง Layout ของแถว
ลาก constraints ให้ครบ ให้ครบทุกแกนเลย
สร้างไฟล์ของ view ที่เป็นตัวแทนของแถว
ไปคลิกขวาที่โฟลเดอร์โปรเจค เลือก New file
จากนั้นเลือก Cocoa Touch Class
ใส่ชื่อ class ที่ต้องการเป็น class ของ cell
ตรง subclass of เลือก UITableViewCell
จากนั้นก็เพิ่ม outlet ของตัวแปรให้เรียบร้อย ซึ่งในที่นี้ เป็น title กับ description
ตัวอย่างการลากเส้นทำ reference outlet
ทำทั้งหมดใน layout จะได้ประมาณนี้
class MyCellView: UITableViewCell { @IBOutlet var tvTitle: UILabel! @IBOutlet var tvDescription: UILabel! override func awakeFromNib() { super.awakeFromNib() // Initialization code } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } }
ไปที่ storyboard กดที่ row แล้วด้านขวา ช่อง classให้เลือก Class ที่เราเพิ่งสร้างไป
กลับมา Implement ที่ ViewController
ที่สำคัญคือที่ CellForRowAt ให้เราเปลี่ยนมาสร้าง Cell จาก Class ที่เราสร้างแทนอันเดิม
แล้วก็จะสามารถกำหนดค่าตัวแปรของเราได้ แล้วก็ต้องเพิ่ม method heightForRowAt เพื่อกำหนดความสูงของ View แถวด้วยนะ
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 50 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let row:MyCellView = tableView.dequeueReusableCell(withIdentifier: "row",for: indexPath) as! MyCellView row.tvTitle.text = "Row = \(indexPath.row)" row.tvDescription.text = "No.\(indexPath.row)" return row }
ลองรันดู
สรุป
ทั้งหมดนี้ก็เป็น step สำหรับ Custom ตัว UITableView ครับ ซึ่งทุกแอปต้องใช้แน่นอน ทำบ่อยๆก็จำได้เองแหละนะ สุดท้ายหวังว่าจะมีประโยชน์กับผู้อ่านนะครับ
Reference
https://stackoverflow.com/questions/25902288/detected-a-case-where-constraints-ambiguously-suggest-a-height-of-zero