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"]!),
),
);
},
),
);
}
}

