ChatGPT said:
คุณต้องการสร้างแอปสมุดโทรศัพท์ใน Flutter ซึ่งมีฟีเจอร์ดังนี้:
✅ แสดงรายชื่อ (ชื่อ + เบอร์โทร + รูปภาพ)
✅ ค้นหาชื่อผู้ติดต่อได้
✅ กดโทรออกได้
✅ ไม่ต้องซิงค์กับ Contact ในเครื่อง
ผมจะสร้างโค้ดตัวอย่างให้คุณด้านล่างนี้:
🔹 สิ่งที่ใช้ใน Flutter
-
1ListView.builder()
→ แสดงรายชื่อ
-
1TextField
→ ช่องค้นหา
-
1url_launcher
→ ใช้โทรออก
-
1StatefulWidget
→ เพื่ออัปเดตรายการขณะค้นหา
🚀 โค้ดตัวอย่าง Flutter
1️⃣ ติดตั้งแพ็กเกจ
1
url_launcher
1 | url_launcher |
เพิ่มใน
1 | pubspec.yaml |
:
dependencies: flutter: sdk: flutter url_launcher: ^6.1.14
กด pub get
ไฟล์
1 | main.dart |
import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: ContactListScreen(), ); } } class Contact { final String name; final String phone; final String imageUrl; Contact({required this.name, required this.phone, required this.imageUrl}); } class ContactListScreen extends StatefulWidget { @override _ContactListScreenState createState() => _ContactListScreenState(); } class _ContactListScreenState extends State<ContactListScreen> { List<Contact> contacts = [ Contact(name: "Alice", phone: "123456789", imageUrl: "https://via.placeholder.com/50"), Contact(name: "Bob", phone: "987654321", imageUrl: "https://via.placeholder.com/50"), Contact(name: "Charlie", phone: "555666777", imageUrl: "https://via.placeholder.com/50"), ]; List<Contact> filteredContacts = []; @override void initState() { super.initState(); filteredContacts = contacts; } void _searchContacts(String query) { setState(() { filteredContacts = contacts .where((contact) => contact.name.toLowerCase().contains(query.toLowerCase())) .toList(); }); } void _callNumber(String phoneNumber) async { final Uri url = Uri(scheme: "tel", path: phoneNumber); if (await canLaunchUrl(url)) { await launchUrl(url); } else { print("ไม่สามารถโทรออกได้"); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("สมุดโทรศัพท์")), body: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: TextField( onChanged: _searchContacts, decoration: InputDecoration( labelText: "ค้นหารายชื่อ...", prefixIcon: Icon(Icons.search), border: OutlineInputBorder(), ), ), ), Expanded( child: ListView.builder( itemCount: filteredContacts.length, itemBuilder: (context, index) { final contact = filteredContacts[index]; return ListTile( leading: CircleAvatar( backgroundImage: NetworkImage(contact.imageUrl), ), title: Text(contact.name), subtitle: Text(contact.phone), trailing: IconButton( icon: Icon(Icons.phone, color: Colors.green), onPressed: () => _callNumber(contact.phone), ), ); }, ), ), ], ), ); } }
แก้ไข
1
AndroidManifest.xml
1 | AndroidManifest.xml |
ให้ไปที่ไฟล์
1 | android/app/src/main/AndroidManifest.xml |
แล้วเพิ่มโค้ดนี้ใน
1 | <manifest> |
(เหนือ
1 | <application> |
)
<uses-permission android:name=“android.permission.CALL_PHONE”/>
การทำแอพเบอร์โทรจาก google sheet ให้สร้าง
1.สร้าง Google Sheet
- ตั้งชื่อเช่น PhoneBook
- ใส่ข้อมูลใน Sheet
ดังตัวอย่างนี้ https://docs.google.com/spreadsheets/d/1Yy6YjaRUeFTVKcCJowll3ZZY3ZrVIFkiH3y0qskmjLo/edit?usp=sharing
2.แชร์ Google Sheet ให้ทุกคนเข้าถึงได้
- ไปที่ File > Share
- ตั้งค่าเป็น “Anyone with the link can view
3. ดึง Sheet ID จาก URL สังเกตุ url https://docs.google.com/spreadsheets/d/1Yy6YjaRUeFTVKcCJowll3ZZY3ZrVIFkiH3y0qskmjLo/edit?usp=sharing ตรงสีแดงคือ ID
4. ปรับให้ดึง url เป็น json file https://docs.google.com/spreadsheets/d/เอาไอดีมาใส่ตรงนี้/gviz/tq?tqx=out:json จะได้เป็น
https://docs.google.com/spreadsheets/d/1Yy6YjaRUeFTVKcCJowll3ZZY3ZrVIFkiH3y0qskmjLo/gviz/tq?tqx=out:json
5. กลับไปที่ android studio เปิดไฟล์ pubspec.yaml
เอาสองตัวนี้ไปวาง
http: ^0.13.6 url_launcher: ^6.1.14
แล้วกด pub get
6. แก้ไขไฟล์ main.dart ดังนี้
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:url_launcher/url_launcher.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: PhoneBookScreen(), ); } } class PhoneBookScreen extends StatefulWidget { @override _PhoneBookScreenState createState() => _PhoneBookScreenState(); } class _PhoneBookScreenState extends State<PhoneBookScreen> { List<Map<String, String>> contacts = []; bool isLoading = true; @override void initState() { super.initState(); fetchContacts(); } Future<void> fetchContacts() async { final String sheetId = "1Yy6YjaRUeFTVKcCJowll3ZZY3ZrVIFkiH3y0qskmjLo"; // 🔹 ใส่ Google Sheet ID ของคุณ final String url = "https://docs.google.com/spreadsheets/d/$sheetId/gviz/tq?tqx=out:json"; try { final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { String jsonData = response.body .replaceAll("/*O_o*/", "") .replaceAll("google.visualization.Query.setResponse(", "") .replaceAll(");", ""); Map<String, dynamic> data = jsonDecode(jsonData); if (!data.containsKey("table") || !data["table"].containsKey("rows")) { print("❌ Error: JSON ไม่มีข้อมูล table/rows"); return; } List<dynamic> rows = data["table"]["rows"]; List<Map<String, String>> tempContacts = []; for (var row in rows) { if (row["c"] == null) { tempContacts.add({"name": "ไม่มีชื่อ", "phone": "ไม่มีเบอร์", "image": ""}); continue; } String name = row["c"][0]?["v"]?.toString() ?? "ไม่มีชื่อ"; String phone = row["c"][1]?["v"]?.toString() ?? "ไม่มีเบอร์"; String image = row["c"][2]?["v"]?.toString() ?? ""; // ✅ ดึง URL รูปภาพ tempContacts.add({"name": name, "phone": phone, "image": image}); } setState(() { contacts = tempContacts; isLoading = false; }); } else { print("❌ โหลดข้อมูลไม่สำเร็จ: ${response.statusCode}"); } } catch (e) { print("❌ เกิดข้อผิดพลาด: $e"); } } void _callNumber(String phoneNumber) async { final Uri url = Uri.parse("tel:$phoneNumber"); if (await canLaunchUrl(url)) { await launchUrl(url, mode: LaunchMode.externalApplication); } else { print("❌ ไม่สามารถโทรออกได้"); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("สมุดโทรศัพท์")), body: isLoading ? Center(child: CircularProgressIndicator()) // กำลังโหลด : contacts.isEmpty ? Center(child: Text("ไม่มีข้อมูลใน Google Sheet")) : ListView.builder( itemCount: contacts.length, itemBuilder: (context, index) { final contact = contacts[index]; return ListTile( leading: contact["image"]!.isNotEmpty ? CircleAvatar( backgroundImage: NetworkImage(contact["image"]!), // ✅ แสดงรูปภาพ radius: 25, ) : CircleAvatar( child: Icon(Icons.person), // ❌ ถ้าไม่มีรูป → แสดงไอคอน radius: 25, ), title: Text(contact["name"]!), subtitle: Text(contact["phone"]!), trailing: IconButton( icon: Icon(Icons.phone, color: Colors.green), onPressed: () => _callNumber(contact["phone"]!), ), ); }, ), ); } }