카테고리 없음

연락처 앱 업그레이드

신승호. 2023. 2. 9. 23:33
  • 스크린 제외 두 페이지가 존재합니다.
    • 연락처 상세보기 페이지, ContactDetailPage
    • 메인페이지, MainPage
  • MainPage는 3개의 스크린을 가집니다.
    • 연락처, ContactScreen
    • 통화기록, HistoryScreen
    • 설정, SettingScreen
  • BottomNavigationBar의 요소를 클릭시 해당 스크린으로 바뀌어 보여집니다.
  • ContactScreen의 커스텀위젯인 ContactTile을 누르면 연락처 상세보기 페이지로 이동됩니다.
  • ContactDetailPage 안에도 ContactTile 위젯이 포함되어 있습니다.

처음볼땐 할거는 많지만 쉬워보였다... 그런데 파일들을 여러개만들다보니 헷갈려서 강의보고 따라해봤다...

 

 

아래는 메인페이지코드

import 'package:assigment11/screen/contact_screen.dart';
import 'package:assigment11/screen/history_screen.dart';
import 'package:assigment11/screen/setting_screen.dart';
import 'package:assigment11/widget/ContactTile.dart';
import 'package:flutter/material.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  var currentScreenIdx = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('내 연락처'),
        actions: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Icon(Icons.search),
          ),
          Padding(
            padding: const EdgeInsets.all(16),
            child: Icon(Icons.more_vert),
          ),
        ],
      ),
      body: [
        ContactScreen(),
        HistoryScreen(),
        SettingScreen(),
      ][currentScreenIdx],
      floatingActionButton:
          FloatingActionButton(onPressed: () {}, child: Icon(Icons.add)),
      bottomNavigationBar: BottomNavigationBar(
          currentIndex: currentScreenIdx,
          onTap: ((value) {
            currentScreenIdx = value;
            setState(() {});
          }),
          items: [
            BottomNavigationBarItem(
                icon: Icon(Icons.contact_phone), label: '연락처'),
            BottomNavigationBarItem(icon: Icon(Icons.history), label: '통화기록'),
            BottomNavigationBarItem(icon: Icon(Icons.settings), label: '설정'),
          ]),
    );
  }
}

currentScreenIdx라는 변수를 저장해 Index값으로 NavigationBar에 아이콘을 텝해 스크린을 바꿨고 ContactScreen, HistoryScreen, SettingScreen 세 스크린의 파일을 따로만들어서 import했다.

 

아래는 ContactTile 코드

import 'package:assigment11/page/contact_detail_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';

class ContactTile extends StatelessWidget {
  const ContactTile(
      {super.key,
      required this.imgUrl,
      required this.name,
      required this.phone});
  final String imgUrl;
  final String name;
  final String phone;

  @override
  Widget build(BuildContext context) {
    return ListTile(
      onTap: () {
        Navigator.push(
            context,
            MaterialPageRoute(
                builder: (context) => ContactDetailPage(
                    name: name, phone: phone, image: imgUrl)));
      },
      title: Text(name),
      subtitle: Text(phone),
      leading: CircleAvatar(backgroundImage: NetworkImage(imgUrl)),
      trailing: Icon(Icons.call),
    );
  }
}

ListTile을 보기 편하게 정리했고 ListTile을 누르면 ContactDetailPage로 이동하게 된다.

 

아래는 ContactDetailPage코드

import 'package:assigment11/widget/ContactTile.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';

class ContactDetailPage extends StatelessWidget {
  const ContactDetailPage(
      {super.key,
      required this.name,
      required this.phone,
      required this.image});
  final String name;
  final String phone;
  final String image;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        title: Text(name),
        elevation: 0,
        backgroundColor: Colors.transparent,
      ),
      body: Column(
        children: [
          Image.network(
            image,
            width: double.infinity,
            fit: BoxFit.cover,
            height: 240,
          ),
          ContactTile(imgUrl: image, name: name, phone: phone)
        ],
      ),
    );
  }
}
이미지와 name, phone은 ContactTile에서 쓰는것을 가져왔다.
아래는 연락처스크린코드
import 'package:assigment11/widget/ContactTile.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';

class ContactScreen extends StatelessWidget {
  const ContactScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        ContactTile(
            imgUrl: 'http://picsum.photos/150/150',
            name: '이태디',
            phone: '010-1010-2000'),
        ContactTile(
            imgUrl: 'http://picsum.photos/50/150',
            name: '밀리',
            phone: '010-2000-3000'),
        ContactTile(
            imgUrl: 'http://picsum.photos/60/100',
            name: '크리스',
            phone: '010-3000-4000'),
        ContactTile(
            imgUrl: 'http://picsum.photos/70/100',
            name: '주노',
            phone: '010-4000-5000'),
        ContactTile(
            imgUrl: 'http://picsum.photos/80/100',
            name: '해리',
            phone: '010-5000-6000'),
        ContactTile(
            imgUrl: 'http://picsum.photos/90/100',
            name: '벨라',
            phone: '010-6000-7000'),
        ContactTile(
            imgUrl: 'http://picsum.photos/100/100',
            name: '헬렌',
            phone: '010-7000-8000'),
      ],
    );
  }
}

ContactTile에서 정리한덕분에 깔끔해보인다.

 

아래는 설정스크린코드

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';

class SettingScreen extends StatelessWidget {
  const SettingScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
        children: [
          Padding(
            padding: const EdgeInsets.all(16),
            child: Text('차단목록'),
          ),
          Padding(
            padding: const EdgeInsets.all(16),
            child: Text('벨소리설정'),
          ),
          Padding(
            padding: const EdgeInsets.all(16),
            child: Text('전화통계'),
          ),
        ],
      ),
    );
  }
}
아래는 통화기록스크린코드
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';

class HistoryScreen extends StatelessWidget {
  const HistoryScreen({super.key});

  @override
  Widget build(BuildContext context) {
    var history = [
      {"name": "크리스", "icon": "call_missed"},
      {"name": "헬렌", "icon": "north_east"},
      {"name": "크리스", "icon": "north_east"},
      {"name": "크리스", "icon": "north_east"},
    ];
    return Scaffold(
      body: ListView.builder(
        itemCount: history.length,
        itemBuilder: ((context, index) {
          return Padding(
            padding: const EdgeInsets.all(16),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(history[index]['name'].toString()),
                if (history[index]['icon'] == 'north_east')
                  Icon(Icons.north_east),
                if (history[index]['icon'] == 'call_missed')
                  Icon(Icons.call_missed),
              ],
            ),
          );
        }),
      ),
    );
  }
}
ListView.build를 배워서 사용해봤더니 됐다. if문을 써서 아이콘이 맞게 나오게 했다.

 

Android Emulator - Pixel_XL_API_27_5554 2023-02-09 23-29-55.mp4
7.39MB

이번건 너무 어려워서 강의를 보고 한번 해봤다.