web analytics

[iOS] การทำ Custom View ของ UITableView

cover

สวัสดีครับ บทความนี้เป็นบทความขณะหัดเขียน iOS ของผม ซึ่งผมกำลังหัดเขียน Swift ใน Xcode เพื่อทำแอป iPhone และเพื่อสร้างความเข้าใจมากขึ้น ผมก็จะมาเขียนเรื่องต่างๆที่ได้เรียนรู้ เป็นการบันทึกความรู้และแชร์ความรู้ไปในตัว และวันนี้ได้ลองเล่น Custom UITableView ซึ่งเป็นเรื่องพื้นฐานมากๆ ก็เลยมาเขียนบล็อกไว้อ่าน หวังว่าจะมีประโยชน์กับผู้เรียนมือใหม่ด้วยกันครับ

TableView ก็เป็นลิสๆ สามารถ scroll เลื่อนได้ ใน Android ก็จะเรียกว่า ListView หรือ RecyclerView

 

วาง Layout

ลาก TableView มาวางใน Storyboard

screen-shot-2018-06-25-at-1-07-52-pm

 

ลาก TableViewCell มาวางใน TableView

screen-shot-2018-06-25-at-1-08-35-pm

 

กำหนด DataSource และ Delegate

กดคลิกขวาที่ TableView แล้ว กดลาก dataSource และ delegate ไปที่จุดเหลืองๆด้านบน ทำทีละอันนะ
หรือกด Ctrl แล้วลากจาก TableView ไปที่จุดเหลืองด้านบน แล้วเลือก dataSource , delegate ก็ได้
DataSource สำหรับจัดการข้อมูล
Delegate สำหรับจัดการ interaction ต่างๆ

swhwtpdbsk

 

เขียนโปรแกรมของ UITableView

ไปที่ ViewController.swift
เพิ่มการ extends class UITableViewDataSource และ UITableViewDelegate

class ViewController: UIViewController,UITableViewDataSource, UITableViewDelegate {

screen-shot-2018-06-25-at-11-17-51-pm

 

จากนั้นจะเขียน Error เพราะ UITableViewDataSource ต้องการให้เรา implement method ที่จำเป็น
ก็ให้เรากด Fix ซะ

screen-shot-2018-06-25-at-11-17-14-pm

 

จากนั้นก็จะสร้าง 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

screen-shot-2018-06-25-at-2-32-42-pm

 

ไปที่ 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 แถว

screen-shot-2018-06-25-at-2-31-16-pm

 

ทำ Custom View

จากนั้นมาวาง Layout ของแถว

screen-shot-2018-06-25-at-5-33-46-pm

 

ลาก constraints ให้ครบ ให้ครบทุกแกนเลย

1

 

สร้างไฟล์ของ view  ที่เป็นตัวแทนของแถว
ไปคลิกขวาที่โฟลเดอร์โปรเจค เลือก New file

screen-shot-2018-06-25-at-5-35-04-pm

 

จากนั้นเลือก Cocoa Touch Class

screen-shot-2018-06-25-at-11-26-20-pm

 

ใส่ชื่อ class ที่ต้องการเป็น class ของ cell
ตรง subclass of เลือก UITableViewCell

screen-shot-2018-06-25-at-11-26-11-pm

 

จากนั้นก็เพิ่ม outlet ของตัวแปรให้เรียบร้อย ซึ่งในที่นี้ เป็น title กับ description
ตัวอย่างการลากเส้นทำ reference outlet

u4llohcpcq

 

ทำทั้งหมดใน 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 ที่เราเพิ่งสร้างไป

screen-shot-2018-06-25-at-11-46-10-pm

 

กลับมา 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
    }

 

ลองรันดู

screen-shot-2018-06-25-at-11-50-47-pm

 

สรุป

ทั้งหมดนี้ก็เป็น step สำหรับ Custom ตัว UITableView ครับ ซึ่งทุกแอปต้องใช้แน่นอน ทำบ่อยๆก็จำได้เองแหละนะ สุดท้ายหวังว่าจะมีประโยชน์กับผู้อ่านนะครับ

 

Reference

https://stackoverflow.com/questions/25902288/detected-a-case-where-constraints-ambiguously-suggest-a-height-of-zero