[KMOOC X COURSERA] Google Flutter 강좌 실습하기

Heeyoung Joe·2023년 11월 19일
0

Flutter

목록 보기
6/7

Lab 1

목적 : 프로젝트 생성하고 reload 익히기

terminal에서 프로젝트 생성

flutter freate [app name]
cd [app name]
fwr 

hot reload

#terminal
r
#browser
Ctrl + r

Lab 2

목적: ListView를 활용하고 Navigation을 성공하기

ListView.builder를 써서 리스트에 있는 내용으로 tile 만들기

class MyApp extends Stateless<Widget> {

	final List<int> items = ['Jan','Feb','Mar'];
    
    @overrides
    Widget build(BuildContext context)(
    	final title = "my awesome app";
        return MaterialApp(
        	title : title,
            home : Scaffold(
                appbar: Appbar(title : Text(title)),
                body: ListView.builder(
                    itemCount : items.length,
                    itemBuilder : (context, index) {
                      return ListTile(
                          title : Text("$item");
                      ); //ListTIle
                    } //body
                ),//Scaffold
         ,//MateiralApp
     ,//build
}//MyApp

주의할 점

  • build 메소드 함수는 MatterialApp() 함수의 결과를 리턴한다.
  • MaterialApp() 함수에는 title과 home 매개변수가 있다.
  • home 매개변수는 주로 Scaffold 위젯으로 넣는다.
  • Scaffold 위젯은 appbar과 body 매개변수가 있다.
  • Scaffold의 appbar는 Appbar() 위젯 함수, body는 ListView 위젯이나 ListView.builder()의 반환값으로 얻는 위젯이나 일반적인 요소 위젯 (Text() 등)으로 넣을 수 있다.
  • ListView의 builder 메소드 함수를 써야 List 데이터타입으로 만들어진 리스트를 가지고 위젯을 만들 수 있다.
  • ListView.builder() 함수는 itemCount와 itemBuilder를 parameter로 갖는다.
  • itemBuilder의 값은(context, index)를 매개변수로 받는 함수의 결과일 수도 있고 단순 ListTile 위젯일 수도 있다.

2개의 stateless app 사이에 navigate하기

class MyApp extends Stateless<Widget> {

	final List<int> items = ['Jan','Feb','Mar'];
    
    @overrides
    Widget build(BuildContext context)(
    	final title = "my awesome app";
        return MaterialApp(
        	title : title,
            home : Scaffold(
                appbar: Appbar(title : Text(title)),
                body: ListView.builder(
                    itemCount : items.length,
                    itemBuilder : (context, index) {
                      return ListTile(
                          title : Text("$item");
                          onTap: () {
                            Navigator.push(
                              context,
                              MaterialPageRoute(builder: (context) => MyDetails(items[index])), 
                      ); //ListTIle
                    } //body
                ),//Scaffold
         ,//MateiralApp
     ,//build
}//MyApp


class MyDetail extends Stateless<Widget> {

	final month;
    MyDetail(this.month);
    
    @overrides
    Widget build(BuildContext context) (
    	return MaterialApp(
        	title : Text("Detail Page")
            home : Scaffold(
            
                appbar: Appbar(title:Text("My Awesome Detail"),
                body: Text("$month");   
            ),//Scaffold
       	),//MaterialApp
    );
}

주의할 점

  • ListTile에는 interaction에 대한 매개변수 항목이 지정되어있고 onTap도 그 중 하나이다.
  • Navigator는 of로 context를 넣어줘도 괜찮고 바로 .push() 내장함수를 통해 context와 MaterialPageRout()을 전달해줘도 괜찮다.
  • MaterialPageRoute은 builder 매개변수가 있어서 위젯을 호출한 걸을 반환해서 넣어줘야 한다.
  • 위젯 호출시 정보를 넘겨주고 싶다면 그에 맞는 생성자를 만들어줘야 한다.

Lab 3

목적 : tab도 쓰고 Drawer도 쓰고 Icon도 쓰기


디버그 중이라는 팻말을 없애고 home의 정의를 별도의 위젯으로 분리하기

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    const title = 'Google Products';
    return const MaterialApp(
      title: title,
      debugShowCheckedModeBanner: false,
      home: ProductHomeWidget(title),
    );
  }
}

Appbar 꾸미고 ListView 위젯 따로 빼기

// TODO: ProductHomeWidget
class ProductHomeWidget extends StatelessWidget {
  final String title;
  const ProductHomeWidget(this.title, {Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        elevation: 0,
        iconTheme: const IconThemeData(
          color: Colors.grey, //change your color here
        ),
        actions: const [
          AppBarActionsShare(),
        ],
        title: Text(title, style: const TextStyle(color: Colors.black)),
      ),
      body: ProductListView(),
      // TODO: Add Drawer
      // drawer: const MyDrawerWidget(),
    );
  }
}

주의할 점

  • 아직 actions 파라미터에 대해 알려진 바가 없다. 웹에서 찾아봤을 때 Intent 클래스의 확장이고 유저의 행동에 따른 결과를 다루는 부분이라고 한다.

아직은 내용을 다루지 않을 Action에 대한 부분

// TODO: AppBarLeading
class AppBarLeading extends StatelessWidget {
  const AppBarLeading({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return const IconButton(
      icon: Icon(
        Icons.menu,
      ),
      onPressed: null,
    );
  }
}
// TODO: AppBarActionsShare
class AppBarActionsShare extends StatelessWidget {
  const AppBarActionsShare({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return IconButton(
        icon: const Icon(
          Icons.share,
        ),
        onPressed: () {
          const snackBar =
              SnackBar(content: Text('You selected the Action: Share'));
          ScaffoldMessenger.of(context).showSnackBar(snackBar);
        });
  }
}

Drawer 위젯 만들기

// TODO: Enable Drawer
class MyDrawerWidget extends StatelessWidget {
  const MyDrawerWidget({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: ListView(
        children: const [
          DrawerHeader(
            child: Icon(Icons.flutter_dash, size: 35),
          ),
        ],
      ),
    );
  }
}

주의할 점

  • Drawer()라는 MaterialApp 위젯이 따로 있으며 얘는 child로 ListView()를 주어야 리스트를 안에 가질 수 있음
  • ListTile 위젯처럼 DrawerHeader()라는 위젯으로 ListView의 chlidren 매개변수를 채워줘야 함.

Product ListView와 ListTile 따로 빼기

// TODO: ProductListView
class ProductListView extends StatelessWidget {
  final googleProducts = GoogleProducts();
  ProductListView({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: googleProducts.items.length,
      itemBuilder: (context, index) {
        return ProductListTile(googleProducts.items[index]);
      },
    );
  }
}
// TODO: ProductListTile
class ProductListTile extends StatelessWidget {
  final String? productLabel;
  const ProductListTile(this.productLabel, {Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: Text('$productLabel', style: const TextStyle(color: Colors.black)),
      subtitle: const Text('SubTitle', style: TextStyle(color: Colors.black)),
      leading: const Icon(Icons.info, color: Colors.black),
      // When the child is tapped, show a snackbar.
      onTap: () {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => const MyDetails()),
        );
      },
    );
  }
}

Detail View에 TabBar와 TabBarView 추가하기

// TODO: Add a details page
class MyDetails extends StatelessWidget {
  final title = 'Details Page';
  const MyDetails({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: DefaultTabController(
        length: 4,
        child: Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.transparent,
            elevation: 0,
            iconTheme: const IconThemeData(
              color: Colors.grey, //change your color here
            ),
            title: Text(title, style: const TextStyle(color: Colors.grey)),
            actions: const [
              AppBarActionsShare(),
            ],
            // TODO: Add TabBar
            // bottom: const TabBar(
            //   indicatorColor: Colors.black,
            //   tabs: [
            //     Tab(
            //       icon: Icon(Icons.home, color: Colors.grey),
            //       child: Text('Overview',
            //           style: TextStyle(
            //               color: Colors.grey, fontWeight: FontWeight.bold)),
            //     ),
            //     Tab(
            //       icon: Icon(Icons.favorite, color: Colors.grey),
            //       child: Text('Docs',
            //           style: TextStyle(
            //               color: Colors.grey, fontWeight: FontWeight.bold)),
            //     ),
            //     Tab(
            //       icon: Icon(Icons.list, color: Colors.grey),
            //       child: Text('Information',
            //           style: TextStyle(
            //               color: Colors.grey, fontWeight: FontWeight.bold)),
            //     ),
            //     Tab(
            //       icon: Icon(Icons.info, color: Colors.grey),
            //       child: Text('Other',
            //           style: TextStyle(
            //               color: Colors.grey, fontWeight: FontWeight.bold)),
            //     ),
            //   ],
            // ),
          ),
          // TODO: Add TabBarView
          // body: const TabBarView(
          //   children: [
          //     SizedBox(
          //       child: Center(
          //         child: Text('Tab Page 1'),
          //       ),
          //     ),
          //     SizedBox(
          //       child: Center(
          //         child: Text('Tab Page 2'),
          //       ),
          //     ),
          //     SizedBox(
          //       child: Center(
          //         child: Text('Tab Page 3'),
          //       ),
          //     ),
          //     SizedBox(
          //       child: Center(
          //         child: Text('Tab Page 4'),
          //       ),
          //     ),
          //   ],
          // ),
        ),
      ),
    );
  }
}
  • TabBar와 TabBarView는 각각 탭과 탭을 눌렀을 때 나오는 화면이다.
  • TabBar는 이 exercise에서는 appbar 함수의 bottom 매개변수에 넣었으며 TabBar()함수를 썼다.
  • TabBar() 위젯 함수는 tabs라는 매개변수가 있어서 Tab() 위젯의 리스트를 넘겨주면 된다.
  • TabBarView()위젯을 body에 넣어줬는데 이 때 TabBarView()의 children으로 탭의 개수와 매칭되는 개수만큼 위젯을 넣어주면 탭 이동시 순서에 맞게 탭이 변경된다.
profile
SW Engineer

0개의 댓글