[Flutter] 스나이퍼팩토리 Flutter 기초과정 (6)

GONG·2023년 3월 29일
0

6일차 과제 링크 👉 6일차 과제

연락처 앱

  • 아래 연락처 UI를 구현하는 방법은 여러가지가 있다.
  1. 기존 ListTile 활용

    ListTile(
    	title: Text('이테디'),
    	subtitle: Text('010-1000-2000'),
    	leading: CircleAvatar(
    		backgroundImage: NetworkImage('https://picsum.photos/100/100'),
    	),
    )
  2. Constructor Parameter

    ContactTile('이테디', '010-1000-2000', 'https://picsum.photos/100/100')
    1. NamedParameter

      ContactTile(
      	name: '이테디',
      	phone: '010-1000-2000', 
      	imgUrl: 'https://picsum.photos/100/100'
      )

Custom Widget

  • 내가 표현하고자하는 디자인요소를 명확히 선언 가능
  • 내가 자주쓰는 위젯을 따로 빼서 관리하자
  • 코드 유지보수 및 관리에 용이하다
  1. 파일명은 UpperCamelCase로
  2. 매개변수로 전달해야 할 데이터 타입도 명확히 할 것

연락처 앱 만들기

  • 새 프로젝트 > contact_app

기존 ListTile 활용 시 생기는 문제

  • main.dart
    ListView(
      children: [
        ListTile(
          title: Text('이테디'),
          subtitle: Text('010-1000-2000'),
          leading: CircleAvatar(
            backgroundImage: NetworkImage('https://picsum.photos/100/100'),
          ),
          trailing: Icon(Icons.call),
        ),
        ListTile(
          title: Text('밀리'),
          subtitle: Text('010-1000-2000'),
          leading: CircleAvatar(
            backgroundImage: NetworkImage('https://picsum.photos/50/50'),
          ),
          trailing: Icon(Icons.call),
        ),
        ListTile(
          title: Text('크리스'),
          subtitle: Text('010-1000-2000'),
          leading: CircleAvatar(
            backgroundImage: NetworkImage('https://picsum.photos/75/75'),
          ),
          trailing: Icon(Icons.call),
        ),
        ListTile(
          title: Text('주노'),
          subtitle: Text('010-1000-2000'),
          leading: CircleAvatar(
            backgroundImage: NetworkImage('https://picsum.photos/70/70'),
          ),
          trailing: Icon(Icons.call),
        ),
        ListTile(
          title: Text('해리'),
          subtitle: Text('010-1000-2000'),
          leading: CircleAvatar(
            backgroundImage: NetworkImage('https://picsum.photos/60/60'),
          ),
          trailing: Icon(Icons.call),
        ),
        ListTile(
          title: Text('벨라'),
          subtitle: Text('010-1000-2000'),
          leading: CircleAvatar(
            backgroundImage: NetworkImage('https://picsum.photos/80/80'),
          ),
          trailing: Icon(Icons.call),
        ),
        ListTile(
          title: Text('헬렌'),
          subtitle: Text('010-1000-2000'),
          leading: CircleAvatar(
            backgroundImage: NetworkImage('https://picsum.photos/110/110'),
          ),
          trailing: Icon(Icons.call),
        ),
      ],
    ),
  • 우리가 진짜 원하는 것은 원하는 데이터만 넘겨줬을 때 똑같은 화면 구성을 보여주는 것이다. 하지만 위 코드에서는 ListTile 위젯까지 함께 반복 사용되고 있다.
  • 데이터 수정이 필요하면 위젯 하나하나 찾아서 수정해야한다.

해결 - CustomWidget

  • CustomWidget을 사용하면 코드 유지보수, 관리가 쉬워진다.

  • ContactTile.dart 파일 생성

    import 'package:flutter/material.dart';
    
    class ContactTile extends StatelessWidget {
      const ContactTile({Key? key, required this.name, required this.phone, required this.imgUrl}) : super(key: key);
    
      final String name;
      final String phone;
      final String imgUrl;
    
      
      Widget build(BuildContext context) {
        return ListTile(
          title: Text('이테디'),
          subtitle: Text('010-1000-2000'),
          leading: CircleAvatar(
            backgroundImage: NetworkImage('https://picsum.photos/100/100'),
          ),
          trailing: Icon(Icons.call),
        );
      }
    }
  • ContactTile 위젯을 자동완성으로 생성하면 자동으로 상단에

    • import 구문을 통해 ContactTile 파일이 불러와진다.
    • import 'package:contact_app/ContactTile.dart';
      body: ListView(
        children: [
          ContactTile(),
  • 하지만 위 ContactTile 위젯 파일은 문자열이 그대로 들어가있어 수정이 번거롭다.

  • 유동적으로 바꾸기 위해서는 사용할 문자열, 속성을 변수로 만들어서 사용하면 된다.

완성

  • ContactTile.dart
    import 'package:flutter/material.dart';
    
    class ContactTile extends StatelessWidget {
      const ContactTile({Key? key, required this.name, required this.phone, required this.imgUrl}) : super(key: key);
    
      final String name;
      final String phone;
      final String imgUrl;
    
      
      Widget build(BuildContext context) {
        return ListTile(
          title: Text(name),
          subtitle: Text(phone),
          leading: CircleAvatar(
            backgroundImage: NetworkImage(imgUrl),
          ),
          trailing: Icon(Icons.call),
        );
      }
    }
  • main.dart
    // ignore_for_file: prefer_const_literals_to_create_immutables, prefer_const_constructors, file_names
    
    import 'package:contact_app/ContactTile.dart';
    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              elevation: 0,
              title: Text('내 연락처'),
              centerTitle: false,
              actions: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Icon(Icons.search),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Icon(Icons.more_vert),
                )
              ],
            ),
            body: ListView(
              children: [
                ContactTile(
                  name: '이테디',
                  phone: '010-1000-2000',
                  imgUrl: 'https://picsum.photos/100/100',
                ),
                ContactTile(
                  name: '밀리',
                  phone: '010-1000-2000',
                  imgUrl: 'https://picsum.photos/50/50',
                ),
                ContactTile(
                  name: '크리스',
                  phone: '010-1000-2000',
                  imgUrl: 'https://picsum.photos/75/75',
                ),
                ContactTile(
                  name: '주노',
                  phone: '010-1000-2000',
                  imgUrl: 'https://picsum.photos/60/60',
                ),
                ContactTile(
                  name: '해리',
                  phone: '010-1000-2000',
                  imgUrl: 'https://picsum.photos/80/80',
                ),
                ContactTile(
                  name: '벨라',
                  phone: '010-1000-2000',
                  imgUrl: 'https://picsum.photos/110/110',
                ),
                ContactTile(
                  name: '헬렌',
                  phone: '010-1000-2000',
                  imgUrl: 'https://picsum.photos/150/150',
                ),
              ],
            ),
            floatingActionButton: FloatingActionButton(
              onPressed: () {},
              child: Icon(Icons.add),
            ),
            bottomNavigationBar: BottomNavigationBar(
              items: [
                BottomNavigationBarItem(icon: Icon(Icons.contact_phone), label: '연락처'),
                BottomNavigationBarItem(icon: Icon(Icons.history), label: '통화기록'),
                BottomNavigationBarItem(icon: Icon(Icons.settings), label: '설정'),
              ],
            ),
          )
        );
      }
    }

6일차 끝

profile
우와재밋다

0개의 댓글