ทำ app flutter มีเบอร์โทร มีรูป มีชื่อ กดโทรได้ ค้นหาชื่อได้
ChatGPT said:

คุณต้องการสร้างแอปสมุดโทรศัพท์ใน Flutter ซึ่งมีฟีเจอร์ดังนี้:
✅ แสดงรายชื่อ (ชื่อ + เบอร์โทร + รูปภาพ)
✅ ค้นหาชื่อผู้ติดต่อได้
✅ กดโทรออกได้
ไม่ต้องซิงค์กับ Contact ในเครื่อง

ผมจะสร้างโค้ดตัวอย่างให้คุณด้านล่างนี้:

🔹 สิ่งที่ใช้ใน Flutter

  • 1
    ListView.builder()

    → แสดงรายชื่อ

  • 1
    TextField

    → ช่องค้นหา

  • 1
    url_launcher

    → ใช้โทรออก

  • 1
    StatefulWidget

    → เพื่ออัปเดตรายการขณะค้นหา


🚀 โค้ดตัวอย่าง Flutter

1️⃣ ติดตั้งแพ็กเกจ

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
android/app/src/main/AndroidManifest.xml

แล้วเพิ่มโค้ดนี้ใน

1
&lt;manifest&gt;

(เหนือ

1
&lt;application&gt;

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

แล้วรอง run จะได้ผลลัพธ์ดังนี้

By admin

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.