입력값 출력하기 (TextEditingController,  addListener)

  • TextEditingController : 입력값 출력하는 클래스
  • addListener : TextField위젯의 값이 변경될 때마다 무언가를 수행함

 

 

폼의 입력값 검증하기 (Form,  GlobalKey<FormState>,  TextFormField)

  • 입력값을 받기 위해 사용 -> Form, TextFormField
  • Form 을 검증하기 위해 -> 폼의 상태를 얻기 위한 key가 필요함 -> GlobalKey<FormState>()를 이용해 key를 구함 ->
    Form의 key 프로퍼티에 할당

  • TextFormField : validator 프로퍼티를 활용하여 검증 기능 제공,
                                검증할 내용 전체를 Form 위젯으로 감싸야함 (Form 위젯에는 유니크한 키를 지정해야함)
    • currentState.validate() 를 사용하여 ->Form내부의 모든 자식들의 validator가 실행됨
  • SnackBar :  하단에 메시지를 표시

더보기
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "폼 입력값 검증",
      home: Scaffold(
        appBar: AppBar(
          title: Text('폼 검증 데모'),
        ),

        body: MyCustomForm(),
      ),
    );
  }
}


class MyCustomForm extends StatefulWidget {

  @override
  _MyCustomFormState createState() => _MyCustomFormState();
}

class _MyCustomFormState extends State<MyCustomForm> {

  // Form 위젯에 유니크한 키값을 부여하고 검증시 사용하기
  final _formKey = GlobalKey<FormState>();


  @override
  void initState(){
    super.initState();

  }

  @override
  void dispose(){
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    //      ↱ 입력값을 검증하기 위해 Form과 TextFormField를 사용
    return Form(
      // ↱ Form의 key 값에는 유니크한 키를 지정해야함
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[

          // ↱ validator 프로퍼티를 활용한 검증 기능 제공
          TextFormField(
            //           ↱ 입력된 값을 인수로 받음
            validator: (value){
              if(value.isEmpty){
                return '글자를 입력시오.';
              }
              return '굿~';
            },
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16.0),
            child: ElevatedButton(
              onPressed: (){

                //            ↱폼을 검정하여 통과하면 true, 실패하면 false 리턴 함
                //            ↱Form 내부의 모든 자식들의 validator가 실행됨
                if (_formKey.currentState.validate()){
                  Scaffold.of(context).showSnackBar(SnackBar(content: Text('검증완료'),));
                //                                    ↳하단에 메시지를 표시하는 클래스
                }
              },
              child: Text('검증'),
            ),
          ),
        ],
      ),
    );
  }
}

 

 

 

공지사항 느낌의 글 목록 만들기

  • shrinkWrap :  스크롤 가능한 객체 안에 또 스크롤 가능한 객체를 넣는 경우 (예. ListView 안에 ListView) -> true로 설정해야 함

 

전체코드⬇︎ 

더보기
import 'dart:math';

import 'package:first_app/main_backUp.dart';
import 'package:flutter/material.dart';
import 'package:carousel_slider/carousel_slider.dart';


// 이미지 주소목록
final dummyItem =[
  'https://img1.daumcdn.net/thumb/R720x0.q80/?scode=mtistory2&fname=http%3A%2F%2Fcfile28.uf.tistory.com%2Fimage%2F99BDD14D5BB078DA146127',
  'https://img1.daumcdn.net/thumb/R720x0.q80/?scode=mtistory2&fname=http%3A%2F%2Fcfile3.uf.tistory.com%2Fimage%2F9966A24D5BB078E406D14B',
  'https://t1.daumcdn.net/blogfile/fs3/29_blog_2007_07_27_21_08_46a9e00365158?x-content-disposition=inline&filename=coilmimi_24.jpg',
];


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {

  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,

        // ↱ 전체 테마를 변경하는 방법.
        // primaryColor: Colors.white,

      ),

      // ↱실행될 때 보여지는 것을 설정 (첫 페이지 설정)
      home: MyHomePage(),


    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스
// 첫 번째 페이지
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  var _index = 0; // 페이지 인덱스

  // 각각의 페이지를 리스트로 구성
  var _pages =[
    Page1(),
    Page2(),
    Page3(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.white,
        title: Text('복잡한 UI',
          style: TextStyle(color: Colors.black),
        ),

        centerTitle: true,  // 제목을 가운데로!

        // actions을 이용해 어떠한 위젯도 리스트로 배치가능
       actions: <Widget>[
          IconButton(  // AppBar 메뉴를 작성
              icon: Icon(
                Icons.add,
                color: Colors.blue,
              ),
              onPressed: (){

              })
        ],
      ),

      // 화면이 갱신될 때마다 _index를 활용하여 -> 해당 페이지를 찾게해줌
      body: _pages[_index],


      bottomNavigationBar: BottomNavigationBar(
        onTap: (index11){
          setState(() {
            _index = index11;  // 선택된 탭의 인덱스로 인덱스를 변경
          });
        },

        currentIndex: _index,   // 선택된 인덱스

        // ↱ items에 BottomNavigationBarItem의 위젯 리스트를 정의
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            label: '홈',
            icon: Icon(Icons.home)
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.assignment),
            label: '이용서비스',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.account_circle),
            label: '내 정보',
          ),
        ],
      ),
    );
  }
}


class Page1 extends StatelessWidget {
  const Page1({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    //      컬럼을 이용해 메서드를 세 영역으로 배치
    return ListView(
      children: <Widget> [
        _buildTop(),
        _buildMiddle(),
        _buildBottom(),
      ],
    );
  }


  // 메서드를 이용해 상단, 중단, 하단을 나눔
  // 상단
  Widget _buildTop(){

    return GestureDetector(
      onTap: (){
        print('클릭!~');
      },
      child: Padding(
        padding: const EdgeInsets.only(top: 20, bottom: 20),

        child: Column(
          children: [
            Row(
              // ↱가로를 꽉 채우면서 적당한 각격을 유지하도록 정렬
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('택시'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('승용차'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('우버택시'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('테슬라'),
                  ],
                ),
              ],
            ),

            // 여백 주기
            SizedBox(
              height: 20,
            ),

            Row(
              // ↱가로를 꽉 채우면서 적당한 각격을 유지하도록 정렬
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('포르쉐'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('마세라티'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('서울택시'),
                  ],
                ),
                Opacity(
                  opacity: 0.0, // 투명하게 설정
                  child: Column(
                    children: <Widget>[
                      Icon(
                        Icons.local_taxi,
                        size: 40,
                      ),
                      Text('테슬라'),
                    ],
                  ),
                ),
              ],
            ),

          ],
        ),
      ),
    );
  }

  // 중단
  Widget _buildMiddle(){
    //      ↱ pub.dev의 Readme의 예제 붙여 넣기
    return CarouselSlider(
      options: CarouselOptions(
        height: 159.0,
        autoPlay: true,  // 슬라이드가 자동으로 넘어감
      ),
      //       ↱ 5페이지로 만듦  (map을 이용해 리스트의 숫자를 다른 요소로 변경)
      items: dummyItem.map((url) {
        return Builder(
          builder: (BuildContext context){
            return Container(
              width: MediaQuery.of(context).size.width,
              margin: EdgeInsets.symmetric(horizontal: 5.0),
              child: ClipRRect( // child를 사각형의 모서리를 둥글게 만듦
                borderRadius: BorderRadius.circular(8.0),
                child: Image.network(
                  url,
                  fit: BoxFit.cover, // 화면에 여백이 남지 않도록 함
                ),
              ),
            );
          },
        );
      }).toList(),
    );
  }

  // 하단
  Widget _buildBottom(){
    final items = List.generate(10, (i) {
      // i 값을 받아서 ListTile 위젯 형태로 변환하여 -> 리스트 형태로 줌... 총  9개가 만들어 지겠지?
      return ListTile(
        leading: Icon(Icons.notifications_none),
        title: Text('$i [이벤트~] 이것은 공지사항임'),
      );
    });
    return ListView(
      physics: NeverScrollableScrollPhysics(),  // 이게 없으면 하단부분이 스크롤이 안 됨 ->
                                                // 스크롤안에 스크롤이 있는 경우 이므로 안 쪽 스크롤을 막아서 작동하도록 함
      shrinkWrap: true, // 이 리스트가 다른 스크롤 객체 안에 있을 경우 true로 설정 (ListView안에 ListView가 있는 경우임)
      children: items,
    );
  }

}

class Page2 extends StatelessWidget {
  const Page2({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        '사용서비스~',
        style: TextStyle(fontSize: 40),
      ),
    );
  }
}

class Page3 extends StatelessWidget {
  const Page3({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        '내정보',
        style: TextStyle(fontSize: 40),
      ),
    );
  }
}

 

라이브러리 추가하기

  • pub.dev 홈페이지로 가기 -> 아래 그림처럼 원하는 라이브러리 검색하기

  • 라이브러리 클릭 후 -> 안드로이드 스튜디오 가서 그림처럼 추가하기

 

슬라이더 추가하기

  • Readme 탭에 있는 How to use에 있는 코드를 복사해서 붙여넣기

아랫부분의 공사장그림은 -> 화면 크기보다 더 크다고 알려주는 것임

 

공사중 그림 없애기

  • column 및 row 위젯은 화면 크기를 벗어나는 UI를 작성할 수 없기에 공사중 그림으로 표시됨
  • column의 경우 -> ListView로 변경해서 스크롤이 가능하게 하면 됨

  • Page1 클래스의 -> build() 메서드를 구성하는 최상단 column을 ListView로 변경하기

 

 

 

슬라이더에 이미지넣고 자동으로 슬라이딩 되게 하기

- 제일 위에 이미지 주소 적기

 

- 원하는 슬라이더 부분 수정하기 (_buildMiddle() 수정)

 

⬇︎전체 코드⬇︎

더보기
import 'dart:math';

import 'package:first_app/main_backUp.dart';
import 'package:flutter/material.dart';
import 'package:carousel_slider/carousel_slider.dart';


// 이미지 주소목록
final dummyItem =[
  'https://img1.daumcdn.net/thumb/R720x0.q80/?scode=mtistory2&fname=http%3A%2F%2Fcfile28.uf.tistory.com%2Fimage%2F99BDD14D5BB078DA146127',
  'https://img1.daumcdn.net/thumb/R720x0.q80/?scode=mtistory2&fname=http%3A%2F%2Fcfile3.uf.tistory.com%2Fimage%2F9966A24D5BB078E406D14B',
  'https://t1.daumcdn.net/blogfile/fs3/29_blog_2007_07_27_21_08_46a9e00365158?x-content-disposition=inline&filename=coilmimi_24.jpg',
];


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {

  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,

        // ↱ 전체 테마를 변경하는 방법.
        // primaryColor: Colors.white,

      ),

      // ↱실행될 때 보여지는 것을 설정 (첫 페이지 설정)
      home: MyHomePage(),


    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스
// 첫 번째 페이지
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  var _index = 0; // 페이지 인덱스

  // 각각의 페이지를 리스트로 구성
  var _pages =[
    Page1(),
    Page2(),
    Page3(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.white,
        title: Text('복잡한 UI',
          style: TextStyle(color: Colors.black),
        ),

        centerTitle: true,  // 제목을 가운데로!

        // actions을 이용해 어떠한 위젯도 리스트로 배치가능
       actions: <Widget>[
          IconButton(  // AppBar 메뉴를 작성
              icon: Icon(
                Icons.add,
                color: Colors.blue,
              ),
              onPressed: (){

              })
        ],
      ),

      // 화면이 갱신될 때마다 _index를 활용하여 -> 해당 페이지를 찾게해줌
      body: _pages[_index],


      bottomNavigationBar: BottomNavigationBar(
        onTap: (index11){
          setState(() {
            _index = index11;  // 선택된 탭의 인덱스로 인덱스를 변경
          });
        },

        currentIndex: _index,   // 선택된 인덱스

        // ↱ items에 BottomNavigationBarItem의 위젯 리스트를 정의
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            label: '홈',
            icon: Icon(Icons.home)
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.assignment),
            label: '이용서비스',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.account_circle),
            label: '내 정보',
          ),
        ],
      ),
    );
  }
}


class Page1 extends StatelessWidget {
  const Page1({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    //      컬럼을 이용해 메서드를 세 영역으로 배치
    return ListView(
      children: <Widget> [
        _buildTop(),
        _buildMiddle(),
        _buildBottom(),
      ],
    );
  }


  // 메서드를 이용해 상단, 중단, 하단을 나눔
  // 상단
  Widget _buildTop(){

    return GestureDetector(
      onTap: (){
        print('클릭!~');
      },
      child: Padding(
        padding: const EdgeInsets.only(top: 20, bottom: 20),

        child: Column(
          children: [
            Row(
              // ↱가로를 꽉 채우면서 적당한 각격을 유지하도록 정렬
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('택시'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('승용차'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('우버택시'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('테슬라'),
                  ],
                ),
              ],
            ),

            // 여백 주기
            SizedBox(
              height: 20,
            ),

            Row(
              // ↱가로를 꽉 채우면서 적당한 각격을 유지하도록 정렬
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('포르쉐'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('마세라티'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('서울택시'),
                  ],
                ),
                Opacity(
                  opacity: 0.0, // 투명하게 설정
                  child: Column(
                    children: <Widget>[
                      Icon(
                        Icons.local_taxi,
                        size: 40,
                      ),
                      Text('테슬라'),
                    ],
                  ),
                ),
              ],
            ),

          ],
        ),
      ),
    );
  }

  // 중단
  Widget _buildMiddle(){
    //      ↱ pub.dev의 Readme의 예제 붙여 넣기
    return CarouselSlider(
      options: CarouselOptions(
        height: 159.0,
        autoPlay: true,  // 슬라이드가 자동으로 넘어감
      ),
      //       ↱ 5페이지로 만듦  (map을 이용해 리스트의 숫자를 다른 요소로 변경)
      items: dummyItem.map((url) {
        return Builder(
          builder: (BuildContext context){
            return Container(
              width: MediaQuery.of(context).size.width,
              margin: EdgeInsets.symmetric(horizontal: 5.0),
              child: ClipRRect( // child를 사각형의 모서리를 둥글게 만듦
                borderRadius: BorderRadius.circular(8.0),
                child: Image.network(
                  url,
                  fit: BoxFit.cover, // 화면에 여백이 남지 않도록 함
                ),
              ),
            );
          },
        );
      }).toList(),
    );
  }

  // 하단
  Widget _buildBottom(){
    return Text('Bottom~');
  }

}

class Page2 extends StatelessWidget {
  const Page2({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        '사용서비스~',
        style: TextStyle(fontSize: 40),
      ),
    );
  }
}

class Page3 extends StatelessWidget {
  const Page3({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        '내정보',
        style: TextStyle(fontSize: 40),
      ),
    );
  }
}

 

 

 

 

BottomNavigationBar

 

 

AppBar 오른쪽에 메뉴 추가하기

 

 

 

화면이 3개인 UI 만들기

 

 

화면구성(페이지)을 크게 세부분으로 나누기

 

 

한 줄에 메뉴 4개 만들기

  // 상단
  Widget _buildTop(){
    return Row(

      // ↱가로를 꽉 채우면서 적당한 각격을 유지하도록 정렬
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        Column(
          children: <Widget>[
            Icon(
              Icons.local_taxi,
              size: 40,
            ),
            Text('택시'),
          ],
        ),
        Column(
          children: <Widget>[
            Icon(
              Icons.local_taxi,
              size: 40,
            ),
            Text('승용차'),
          ],
        ),
        Column(
          children: <Widget>[
            Icon(
              Icons.local_taxi,
              size: 40,
            ),
            Text('우버택시'),
          ],
        ),
        Column(
          children: <Widget>[
            Icon(
              Icons.local_taxi,
              size: 40,
            ),
            Text('테슬라'),
          ],
        ),
      ],
    );
  }

 

메뉴를 2줄로 만들기,   그리고 8개의 메뉴를 7개로 변경하기

  • Row 위젯을 -> 다시 Column 위젯으로 감싸고 -> Row전체를 복사해서 Column안에 붙여 넣어주기
더보기
  // 상단
  Widget _buildTop(){

    return Column(
      children: [
        Row(
          // ↱가로를 꽉 채우면서 적당한 각격을 유지하도록 정렬
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Column(
              children: <Widget>[
                Icon(
                  Icons.local_taxi,
                  size: 40,
                ),
                Text('택시'),
              ],
            ),
            Column(
              children: <Widget>[
                Icon(
                  Icons.local_taxi,
                  size: 40,
                ),
                Text('승용차'),
              ],
            ),
            Column(
              children: <Widget>[
                Icon(
                  Icons.local_taxi,
                  size: 40,
                ),
                Text('우버택시'),
              ],
            ),
            Column(
              children: <Widget>[
                Icon(
                  Icons.local_taxi,
                  size: 40,
                ),
                Text('테슬라'),
              ],
            ),
          ],
        ),

        // 여백 주기
        SizedBox(
          height: 20,
        ),

        Row(
          // ↱가로를 꽉 채우면서 적당한 각격을 유지하도록 정렬
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Column(
              children: <Widget>[
                Icon(
                  Icons.local_taxi,
                  size: 40,
                ),
                Text('포르쉐'),
              ],
            ),
            Column(
              children: <Widget>[
                Icon(
                  Icons.local_taxi,
                  size: 40,
                ),
                Text('마세라티'),
              ],
            ),
            Column(
              children: <Widget>[
                Icon(
                  Icons.local_taxi,
                  size: 40,
                ),
                Text('서울택시'),
              ],
            ),
            Opacity(
              opacity: 0.0, // 투명하게 설정
              child: Column(
                children: <Widget>[
                  Icon(
                    Icons.local_taxi,
                    size: 40,
                  ),
                  Text('테슬라'),
                ],
              ),
            ),
          ],
        ),

      ],
    );
  }

 

  • 마지막 메뉴 코드를 삭제할 경우 정렬이 흐트러짐 -> Opacity를 사용하여 안 보이게 해야 함

 

 

 

클릭 가능하게 하고 전체 여백주기

  • 클릭가능하게 하기 : Column을 -> GestureDetector ( 또는 InkWell )로 감싼다.

 

  • 전체 여백주기 : 최상단 Column을 padding으로 감싸기

 

 

전체코드⬇︎ 

더보기
import 'dart:math';

import 'package:first_app/main_backUp.dart';
import 'package:flutter/material.dart';
import 'package:carousel_slider/carousel_slider.dart';


// 이미지 주소목록
final dummyItem =[
  'https://img1.daumcdn.net/thumb/R720x0.q80/?scode=mtistory2&fname=http%3A%2F%2Fcfile28.uf.tistory.com%2Fimage%2F99BDD14D5BB078DA146127',
  'https://img1.daumcdn.net/thumb/R720x0.q80/?scode=mtistory2&fname=http%3A%2F%2Fcfile3.uf.tistory.com%2Fimage%2F9966A24D5BB078E406D14B',
  'https://t1.daumcdn.net/blogfile/fs3/29_blog_2007_07_27_21_08_46a9e00365158?x-content-disposition=inline&filename=coilmimi_24.jpg',
];


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {

  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,

        // ↱ 전체 테마를 변경하는 방법.
        // primaryColor: Colors.white,

      ),

      // ↱실행될 때 보여지는 것을 설정 (첫 페이지 설정)
      home: MyHomePage(),


    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스
// 첫 번째 페이지
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  var _index = 0; // 페이지 인덱스

  // 각각의 페이지를 리스트로 구성
  var _pages =[
    Page1(),
    Page2(),
    Page3(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.white,
        title: Text('복잡한 UI',
          style: TextStyle(color: Colors.black),
        ),

        centerTitle: true,  // 제목을 가운데로!

        // actions을 이용해 어떠한 위젯도 리스트로 배치가능
       actions: <Widget>[
          IconButton(  // AppBar 메뉴를 작성
              icon: Icon(
                Icons.add,
                color: Colors.blue,
              ),
              onPressed: (){

              })
        ],
      ),

      // 화면이 갱신될 때마다 _index를 활용하여 -> 해당 페이지를 찾게해줌
      body: _pages[_index],


      bottomNavigationBar: BottomNavigationBar(
        onTap: (index11){
          setState(() {
            _index = index11;  // 선택된 탭의 인덱스로 인덱스를 변경
          });
        },

        currentIndex: _index,   // 선택된 인덱스

        // ↱ items에 BottomNavigationBarItem의 위젯 리스트를 정의
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            label: '홈',
            icon: Icon(Icons.home)
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.assignment),
            label: '이용서비스',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.account_circle),
            label: '내 정보',
          ),
        ],
      ),
    );
  }
}


class Page1 extends StatelessWidget {
  const Page1({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    //      컬럼을 이용해 메서드를 세 영역으로 배치
    return ListView(
      children: <Widget> [
        _buildTop(),
        _buildMiddle(),
        _buildBottom(),
      ],
    );
  }


  // 메서드를 이용해 상단, 중단, 하단을 나눔
  // 상단
  Widget _buildTop(){

    return GestureDetector(
      onTap: (){
        print('클릭!~');
      },
      child: Padding(
        padding: const EdgeInsets.only(top: 20, bottom: 20),

        child: Column(
          children: [
            Row(
              // ↱가로를 꽉 채우면서 적당한 각격을 유지하도록 정렬
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('택시'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('승용차'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('우버택시'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('테슬라'),
                  ],
                ),
              ],
            ),

            // 여백 주기
            SizedBox(
              height: 20,
            ),

            Row(
              // ↱가로를 꽉 채우면서 적당한 각격을 유지하도록 정렬
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('포르쉐'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('마세라티'),
                  ],
                ),
                Column(
                  children: <Widget>[
                    Icon(
                      Icons.local_taxi,
                      size: 40,
                    ),
                    Text('서울택시'),
                  ],
                ),
                Opacity(
                  opacity: 0.0, // 투명하게 설정
                  child: Column(
                    children: <Widget>[
                      Icon(
                        Icons.local_taxi,
                        size: 40,
                      ),
                      Text('테슬라'),
                    ],
                  ),
                ),
              ],
            ),

          ],
        ),
      ),
    );
  }

  // 중단
  Widget _buildMiddle(){
    //      ↱ pub.dev의 Readme의 예제 붙여 넣기
    return CarouselSlider(
      options: CarouselOptions(
        height: 159.0,
        autoPlay: true,  // 슬라이드가 자동으로 넘어감
      ),
      //       ↱ 5페이지로 만듦  (map을 이용해 리스트의 숫자를 다른 요소로 변경)
      items: dummyItem.map((url) {
        return Builder(
          builder: (BuildContext context){
            return Container(
              width: MediaQuery.of(context).size.width,
              margin: EdgeInsets.symmetric(horizontal: 5.0),
              child: ClipRRect( // child를 사각형의 모서리를 둥글게 만듦
                borderRadius: BorderRadius.circular(8.0),
                child: Image.network(
                  url,
                  fit: BoxFit.cover, // 화면에 여백이 남지 않도록 함
                ),
              ),
            );
          },
        );
      }).toList(),
    );
  }

  // 하단
  Widget _buildBottom(){
    final items = List.generate(10, (i) {
      // i 값을 받아서 ListTile 위젯 형태로 변환하여 -> 리스트 형태로 줌... 총  9개가 만들어 지겠지?
      return ListTile(
        leading: Icon(Icons.notifications_none),
        title: Text('$i [이벤트~] 이것은 공지사항임'),
      );
    });
    return ListView(
      physics: NeverScrollableScrollPhysics(),  // 이게 없으면 하단부분이 스크롤이 안 됨 ->
                                                // 스크롤안에 스크롤이 있는 경우 이므로 안 쪽 스크롤을 막아서 작동하도록 함
      shrinkWrap: true, // 이 리스트가 다른 스크롤 객체 안에 있을 경우 true로 설정 (ListView안에 ListView가 있는 경우임)
      children: items,
    );
  }

}

class Page2 extends StatelessWidget {
  const Page2({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        '사용서비스~',
        style: TextStyle(fontSize: 40),
      ),
    );
  }
}

class Page3 extends StatelessWidget {
  const Page3({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        '내정보',
        style: TextStyle(fontSize: 40),
      ),
    );
  }
}
  • build() 메서드는 -> 화면에 UI를 새로 그리는 역할을 하기 때문에 앱 성능에 지장을 주는 코드는 작성하면 안된다.

  • stack 구조로 메모리에 쌓인다. (나중에 들어간 것이 먼저 나오는 구조임)
  • stack에서 모든 화면이 제거되면 앱이 종료된다.

 

  • 화면이 표시되면서(화면이 생성될 때마다) -> build() 메서드가 호출 된다.  (stack에 남아 있다면 호출 되지 않음)

 

initState,  didChangeDependencies,  didUpdateWidget,  dispose

  • 생명주기 메서드 :  특정 타이밍에 실행되는 메서드

  • createState()함수가 호출 되면 -> mounted == true 가 됨. (위젯을 화면에 장착한 경우 true가 됨)

  • initState() -> 위젯을 초기화할 때 한 번만 호출됨 (주로 데이터 목록을 만들거나, 처음 필요한 데이터 주고 받을 때 호출)
                          위젯이 생성될 때 호출 (StatefulWidget 클래스가 생성 될 때)
                           총 10개의 페이지가 있는 경우 ->  10번째에 있는 페이지를 표시할 경우 ->
                           아래의 9개 페이지 모두 buld() 메서드가 호출될 수 있으므로 계산이나, 네트워크 요청 등은 -> initState()를 추천

  • didChangeDependencies() ->  initState() 함수가 호출된 후에 이어서 바로 호출 됨.
                                                          데이터에 의존하는 위젯이라면 화면에 표시하기 전에 꼭 호출 해야함.
                                                          상속받은 위젯을 상용할 때 피상속자가 변경되면 호출 함.

  • didUpdateWidget() ->  부모 위젯이나 데이터가 변경되어 위젯을 갱신해야 할 때 호출함.
                                            initState() 함수는 위젯을 초기화할 때 한 번만 호출되므로 위젯이 변경되었을때 호출하는 
                                            didUpdateWidget() 같은 함수가 필요함.

  • setState() -> 데이터가 변경된 것을 알려주고, 변경된 데이터를 이용해 화면의 UI를 다시 구성

  • deactivate() -> State 객체가 플러터의 구성트리로부터 제거될 때 호출 됨. (메모리에는 남아 있음)
                              dispose()함수를 호출하기 전까지는 State객체 사용 가능.

  • dispose() -> 위젯이 완전히 종료될 때 호출 (pop될 때)

 

import 'dart:math';

import 'package:flutter/material.dart';

// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {

  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // ↱실행될 때 보여지는 것을 설정 (첫 페이지 설정)
      home: FirstStatefullPage(),


    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스
// 첫 번째 페이지

class FirstStatefullPage extends StatefulWidget {
  const FirstStatefullPage({Key key}) : super(key: key);

  @override
  _FirstStatefullPageState createState() => _FirstStatefullPageState();
}


class _FirstStatefullPageState extends State<FirstStatefullPage> {

  @override
  void initState(){
    super.initState();
    print('FirtstPage - initstate() 호출');
  }

  @override
  void dispose(){
    super.dispose();
    print('FirstPage - dispose() 호출');
  }


  @override
  Widget build(BuildContext context) {

    print('FirstPage build() 메서드 호출');

    return Scaffold(
      appBar: AppBar(
        title: Text('Fisrt 페이지'),
      ),
      body: ElevatedButton(
        child: Text("다음 페이지로~"),
        onPressed: (){
          final person = Person("김길동", 99);
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => SecondStatefulPage(person1: person)),
          );
        },
      ),
    );
  }
}


class SecondStatefulPage extends StatefulWidget {
  final Person person1;

  const SecondStatefulPage({Key key, @required this.person1}) : super(key: key);


  @override
  _SecondStatefulPageState createState() => _SecondStatefulPageState();
}

class _SecondStatefulPageState extends State<SecondStatefulPage> {

  @override
  void initState(){
    super.initState();
    print("SecondPage - initState() 호출");
  }

  @override
  void dispose(){
    super.dispose();
    print('SecondPage - dispose() 호출');
  }


  @override
  Widget build(BuildContext context) {

    print('SecondPage - build() 메서드 호출');

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.person1.name),
      ),

      body: ElevatedButton(
        child: Text('이전 페이지로~'),
        onPressed: (){
          Navigator.pop(context);
        },
      ),
    );
  }
}



class Person{
  String name;
  int age;

  Person(this.name, this.age);

}

 

'Flutter > 내비게이션' 카테고리의 다른 글

routes를 활용한 내비게이션  (0) 2021.06.18
새로운 화면으로 이동  (0) 2021.06.18

routes 정의

 

routes에 의한 화면 이동

  • push() 메서드 대신 -> pushName() 메서드를 사용

 

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // ↱실행될 때 보여지는 것을 설정 (첫 페이지 설정)
      home: FirstPage(),

      routes: {
        // '/first'는 FirstPage 클래스로, '/second'는 SecondPage클래스로 연결
        '/first':(context) => FirstPage(),
        '/second': (context) => SecondPage(person1: null)
      },
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스
// 첫 번째 페이지
class FirstPage extends StatelessWidget {
  const FirstPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("첫번째 페이지"),
      ),

      body: ElevatedButton(
        child: Text('다음 페이지로~'),
        onPressed: () async {
          final person = Person("홍길동", 20);

          final result = await Navigator.pushNamed(
            context, '/second'); // Navigator.pushName 끝

          print("돌려받은 데이터-> $result");
        },
      ),
    );
  }
}


// 두 번째 페이지
class SecondPage extends StatelessWidget {
  final Person person1;

  // pesrson1 이름으로 person을 받아서 위에 변수에 넣어줌
  SecondPage({@required this.person1});
  // const SecondPage({Key key, this.person1}) : super(key:key);  // 이렇게도 가능

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("두 번째 페이지!"),
      ),

      body: ElevatedButton(
        child: Text('이전 페이지로'),
        onPressed: (){
          Navigator.pop(context, person1.name);  // 현재 화면을 종료하고 이전 화면으로 이동
        },
      ),
    );
  }
}


class Person{
  String name;
  int age;

  Person(this.name, this.age);

}

 

 

 

 

 

 

 

 

 

push로 새로운 화면 호출하기, pop으로 이전화면으로 이동

  • push

 

  • pop

더보기
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // ↱실행될 때 보여지는 것을 설정
      home: FirstPage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스
// 첫 번째 페이지
class FirstPage extends StatelessWidget {
  const FirstPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("첫번째 페이지"),
      ),

      body: ElevatedButton(
        child: Text('다음 페이지로~'),
        onPressed: (){
          Navigator.push(
            context,
            // ↱ 머티리얼 디자인으로 작성된 페이지 사이에 화면 전환할 때 사용
            MaterialPageRoute(builder: (context) => SecondPage()),
          ); // Navigator.push 끝
        },
      ),
    );
  }
}


// 두 번째 페이지
class SecondPage extends StatelessWidget {
  const SecondPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("두 번째 페이지!"),
      ),

      body: ElevatedButton(
        child: Text('이전 페이지로'),
        onPressed: (){
          Navigator.pop(context);  // 현재 화면을 종료하고 이전 화면으로 이동
        },
      ),
    );
  }
}

 


새로운 화면에 값 전달하기 및 이전 페이지로 값 돌려주기

  • push() 메서드는 -> Future 반환 타입을 갖는다.
    그러므로 값을 받기 위해서는 메서드 앞에 -> await 추가,  -> await 사용하는 함수 본문에 async 추가해야 함

더보기
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // ↱실행될 때 보여지는 것을 설정
      home: FirstPage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스
// 첫 번째 페이지
class FirstPage extends StatelessWidget {
  const FirstPage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("첫번째 페이지"),
      ),

      body: ElevatedButton(
        child: Text('다음 페이지로~'),
        onPressed: () async {
          final person = Person("홍길동", 20);
          //                              
          final result = await Navigator.push(
            context,
            // ↱ 머티리얼 디자인으로 작성된 페이지 사이에 화면 전환할 때 사용
            MaterialPageRoute(builder: (context) => SecondPage(person1: person)),
                                                               // ↳SecondPage 클래스 생성자에 pesrson1을 전달
          ); // Navigator.push 끝
          print("돌려받은 데이터-> $result");
        },
      ),
    );
  }
}


// 두 번째 페이지
class SecondPage extends StatelessWidget {
  final Person person1;

  // pesrson1 이름으로 person을 받아서 위에 변수에 넣어줌
  SecondPage({@required this.person1});
  // const SecondPage({Key key, this.person1}) : super(key:key);  // 이렇게도 가능

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("두 번째 페이지!"),
      ),

      body: ElevatedButton(
        child: Text('이전 페이지로'),
        onPressed: (){
          Navigator.pop(context, person1.name);  // 현재 화면을 종료하고 이전 화면으로 이동
        },
      ),
    );
  }
}


class Person{
  String name;
  int age;

  Person(this.name, this.age);

}

 

 

CupertinoNavigationBar

  • leading : 왼쪽
  • middle : 가운데 (주로 제목 표시)
  • trailing : 오른쪽

더보기
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // ↱실행될 때 보여지는 것을 설정
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  var _isOn = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: CupertinoNavigationBar(
        middle: Text('4.10 쿠퍼티노 디자인'),
      ),

      body: Column(
        children: <Widget>[

          // 머티리얼의 Switch와 같음
          CupertinoSwitch(
            value: _isOn,
            onChanged: (bool value1){
              setState(() {
                _isOn = value1;
              });
            }
          ),

          // 머티리얼의 ElevatedButton과 같음
          CupertinoButton(
            borderRadius: BorderRadius.circular(16.0),
            color: Colors.orange,
            child: Text("쿠퍼티노 AlertDialog~"),
            onPressed: (){

            },
          ),
          CupertinoButton(
            child: Text('쿠퍼티노 Picker'),
            onPressed: (){

            },
          ),


        ],
      ),
    );
  }


}


CupertinoAlerDialog

더보기
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // ↱실행될 때 보여지는 것을 설정
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  var _isOn = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: CupertinoNavigationBar(
        middle: Text('4.10 쿠퍼티노 디자인'),
      ),

      body: Column(
        children: <Widget>[

          // 머티리얼의 Switch와 같음
          CupertinoSwitch(
            value: _isOn,
            onChanged: (bool value1){
              setState(() {
                _isOn = value1;
              });
            }
          ),

          // 머티리얼의 ElevatedButton과 같음
          CupertinoButton(
            borderRadius: BorderRadius.circular(16.0),
            color: Colors.orange,
            child: Text("쿠퍼티노 AlertDialog~"),
            onPressed: (){
              _showCupertinoDialog();
            },
          ),
          CupertinoButton(
            child: Text('쿠퍼티노 Picker'),
            onPressed: (){

            },
          ),


        ],
      ),
    );
  }

  _showCupertinoDialog(){
    showDialog(
      context: context,
      builder: (context) => CupertinoAlertDialog(
        title: Text("제목이다"),
        content: Text("내용이다."),
        actions: <Widget>[
          CupertinoDialogAction(
            child: Text("취소여~"),
          ),
          CupertinoDialogAction(
            child: Text("오케이"),
            onPressed: (){
              Navigator.of(context).pop();  // 다이얼로그 닫기
            },
          ),
        ],
      ),
    );
  }

  _showCupertinoPicker(){

  }


}


 

CupertinoPicker

더보기
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';

// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // ↱실행될 때 보여지는 것을 설정
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  var _isOn = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: CupertinoNavigationBar(
        middle: Text('4.10 쿠퍼티노 디자인'),
      ),

      body: Column(
        children: <Widget>[

          // 머티리얼의 Switch와 같음
          CupertinoSwitch(
            value: _isOn,
            onChanged: (bool value1){
              setState(() {
                _isOn = value1;
              });
            }
          ),

          // 머티리얼의 ElevatedButton과 같음
          CupertinoButton(
            borderRadius: BorderRadius.circular(16.0),
            color: Colors.orange,
            child: Text("쿠퍼티노 AlertDialog~"),
            onPressed: (){
              _showCupertinoDialog();
            },
          ),
          CupertinoButton(
            child: Text('쿠퍼티노 Picker'),
            onPressed: (){
              _showCupertinoPicker();
            },
          ),


        ],
      ),
    );
  }

  _showCupertinoDialog(){
    showDialog(
      context: context,
      builder: (context) => CupertinoAlertDialog(
        title: Text("제목이다"),
        content: Text("내용이다."),
        actions: <Widget>[
          CupertinoDialogAction(
            child: Text("취소여~"),
            onPressed: (){
              Navigator.of(context).pop();  // 다이얼로그 닫기
            },
          ),
          CupertinoDialogAction(
            child: Text("오케이"),
            onPressed: (){
              Navigator.of(context).pop();  // 다이얼로그 닫기
            },
          ),
        ],
      ),
    );
  }

  _showCupertinoPicker() async{
    // 0 ~ 9 까지의 숫자 리스트 생성
    final _items = List.generate(10, (index) => index);
    var result = _items[0]; // 기본값 0

    await showCupertinoModalPopup(
      context: context,
      builder: (context) => Container(  // 컨테이너 위젯으로 감싸고 높이를 지정
        height: 600.0, // 피커 높이 설정
        child: CupertinoPicker(
          children: _items.map((e) => Text('No. $e')).toList(), // 0~9까지 숫자 표시
          itemExtent: 50.0,  // 항목 1개의 높이를 설정
          onSelectedItemChanged: (int value){ // 선택된 항목이 들어옴
            result = _items[value];
          },
        ),
      ),
    );
    print(result);
  }


}

 

 

 

CupertinoNavigationBar, CupertinoAlerDialog, CupertinoPicker

Hero

- 화면 전환시 화면을 자연스럽게 연결

더보기
import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HeroPage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable

class HeroPage extends StatelessWidget{

  @override
  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(
        title: Text("Hero~~"),
      ),

      body: Center(
        child: GestureDetector( // 이벤트 발생시킴
          onTap: (){
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context)=> HeroDetailPage()),
            ); //Navigator.push 끝
          },
          child: Hero(
            tag: 'image',  // 여기의 태그 명과 두 번째 페이지의 태그 명이 똑 같아야함!!!
            child: Image.asset(
              'assets/eleiko.png',
              width: 100,
              height: 100,
            ),
          ),
        ),
      ),

    );
  }
} // HeroPage 끝

class HeroDetailPage extends StatelessWidget{

  @override
  Widget build(BuildContext context){
    return Scaffold(
      appBar: AppBar(
        title: Text('Hero Detail~~'),
      ),

      body: Hero(
        tag: 'image',
        child: Image.asset(
          'assets/eleiko.png'
        ),
      ),
    );
  }
}

// class MyHomePage extends StatefulWidget {
//
//   @override
//   _MyHomePageState createState() => _MyHomePageState();
// }
//
//
// class _MyHomePageState extends State<MyHomePage>{
//
//   // 선택한 날짜 저장하기 위한 변수
//   String _selectedTime;
//
//     @override
//     Widget build(BuildContext context) {
//       return Scaffold(
//         appBar: AppBar(
//           title: Text("플러터 마스터"),
//         ),
//
//         // 여기서부터 수정!!!!!
//         body: Padding(
//           padding: const EdgeInsets.all(8.0),
//           child: Center(
//             child: Column(
//               mainAxisAlignment: MainAxisAlignment.center,
//               crossAxisAlignment: CrossAxisAlignment.center,
//
//               children: <Widget>[
//                 GestureDetector(
//                   onTap: (){
//                     print('GestureDetector 클릭함');
//                   },
//                   child: Text('GestureDetector 여기를 터치하시오.'),
//                 ),
//
//                 SizedBox(
//                   height: 50,
//                 ),
//
//                 InkWell(
//                   onTap: (){
//                     print('InkWell 클릭함');
//                   },
//                   child: Text('InkWell 여기를 터치해'),
//                 ),
//
//               ],
//
//             ),
//
//           ),
//         ),
//       );
//
//     }
//
// }

 


AnimatedContainer

- 한 화면내에서 setState() 함수를 호출하여 화면을 새로 그릴 때 -> 변경된 프로퍼티로 인해 애니메이션 효과보여줌

더보기
import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // ↱실행될 때 보여지는 것을 설정
      home: AnimatedContainerPage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
class AnimatedContainerPage extends StatefulWidget {

  const AnimatedContainerPage({Key key}) : super(key: key);

  @override
  _AnimatedContainerPageState createState() => _AnimatedContainerPageState();
}


class _AnimatedContainerPageState extends State<AnimatedContainerPage> {
  var _size = 100.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AnimatedContainer'),
      ),

      body: Center(
        child: GestureDetector(
          onTap: (){
            final random = Random();  // Random 클래스 사용준비
            setState(() {
              // 클릭할 때마다 100.0~299.0 사이의 랜덤 실수 얻기
              _size = random.nextInt(200).toDouble() + 100;
            //                ↳0 ~ 199 정수 발생 ↳ 실수로 변환, + 100을 함으로 -> 100.0 ~ 299.0
            });
          },
          //      ↱이전 _size 변수 값에서 -> 새로 갱신된 _size 값까지 -> 1초 동안 fastOutSlowIn에 정의된 효과가 적용됨
          child: AnimatedContainer(
            duration: Duration(seconds: 1),
            width: _size,  // 랜덤 값을 적용
            height: _size,
            child: Image.asset('assets/eleiko_wei.png'),
            curve: Curves.fastOutSlowIn,
          ),
        ),
      ),
    );
  }
}


 

 


SliverAppBar와 SliverFillRemaining(하나의 정적인 화면)

- 헤더를 동적으로 표현한다.
   헤더를 위로 스크롤 하면 -> 헤더 부분이 작이면서 헤더 하단에 있던 내용이 AppBar 형태로 보여진다. (Sliver 효과라 함)

더보기
import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // ↱실행될 때 보여지는 것을 설정
      home: SliverPage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
class SliverPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,  // 축소할 경우 상단에 AppBar가 고정 되는지 여부를 설정
            expandedHeight: 180.0,    // 헤더의 최대 높이
            flexibleSpace: FlexibleSpaceBar( // 늘어나는 영역의 UI정의
              title: Text('Sliver!!~~'),
              background: Image.asset(
                'assets/eleiko.png',
                fit: BoxFit.cover,
              ),
            ),
          ), // 헤더 영억

          SliverFillRemaining(    // 내용 영역
            child: Center(
              child: Text('center!!~'),
            ),
          ),
        ],
      ),
    );
  }
}

 

 


SliverAppBar와 SliverList(ListView를 사용하면서 Sliver효과를 줌)

더보기
import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      // ↱실행될 때 보여지는 것을 설정
      home: SliverListPage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
class SliverListPage extends StatelessWidget {

  // 0 ~ 49 까지 표시하는 ListTile을 담은 리스트
  final _items = List.generate(50, (index) => ListTile(title: Text('No~. $index')));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            pinned: true,  // 축소할 경우 상단에 AppBar가 고정 되는지 여부를 설정
            expandedHeight: 180.0,    // 헤더의 최대 높이
            flexibleSpace: FlexibleSpaceBar( // 늘어나는 영역의 UI정의
              title: Text('Sliver다!!~~'),
              background: Image.asset(
                'assets/eleiko.png',
                fit: BoxFit.cover,
              ),
            ),

            actions: <Widget>[
              IconButton(
                icon: Image.asset('assets/eleiko_wei.png'),
                onPressed: (){},
              )
            ],
          ), // 헤더 영억


          SliverList(    // 내용 영역
            delegate: SliverChildListDelegate(_items),
          ),
        ],
      ),
    );
  }
}


 

 

 

더보기
import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => _MyHomePageState();
}


class _MyHomePageState extends State<MyHomePage>{

  // 선택한 날짜 저장하기 위한 변수
  String _selectedTime;

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("플러터 마스터"),
        ),

        // 여기서부터 수정!!!!!
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,

              children: <Widget>[
                GestureDetector(
                  onTap: (){
                    print('GestureDetector 클릭함');
                  },
                  child: Text('GestureDetector 여기를 터치하시오.'),
                ),

                SizedBox(
                  height: 50,
                ),

                InkWell(
                  onTap: (){
                    print('InkWell 클릭함');
                  },
                  child: Text('InkWell 여기를 터치해'),
                ),

              ],

            ),

          ),
        ),
      );

    }

}

AlertDialog

- showDialog() 함수의 builder 프로퍼티에 AlertDialog클래스를 반환하도록 한다.

더보기
import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => _MyHomePageState();
}


class _MyHomePageState extends State<MyHomePage>{

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("플러터 마스터"),
        ),

        // 여기서부터 수정!!!!!
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,

              children: <Widget>[
                RaisedButton(
                  child: Text('다이얼로그 열기!~',
                    style: TextStyle(
                      fontSize: 20,
                      color: Colors.green,
                    ),
                  ),
                  onPressed: () => FlutterDialog(),
                ),

              ],

            ),

          ),
        ),
      );

    }

    // ignore: non_constant_identifier_names
    void FlutterDialog() {
      showDialog(
          //위에 상속받은 BuildContext context
          context: context,
          //barrierDismissible - Dialog를 제외한 다른 화면 터치해서 종료 여부
          barrierDismissible: false,
          builder: (BuildContext context) {
            return AlertDialog(
              // RoundedRectangleBorder - Dialog 화면 모서리 둥글게 조절
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10.0)),

              //Dialog Main Title
              title: Column(
                children: <Widget>[
                  Text("Dialog 제목"),
                ],
              ),

              // SingleChildScrollView와 ListBody를 사용하여 -> ListView와 동일한 효과를 가짐
              content: SingleChildScrollView(
                child: ListBody(
                  children: <Widget>[
                    Text('Alert Dialg 입니다~'),
                    Text('Ok를 눌러 닫습니다.'),
                  ],
                ),
              ),

              // 텍스트버튼을 정의
              actions: <Widget>[
                TextButton(
                  child: new Text("Ok~"),
                  onPressed: () {
                    // 다이얼로그 닫기
                    Navigator.of(context).pop();
                  },
                ),
                TextButton(
                  child: Text("Cancel~"),
                  onPressed: (){
                    // 다이얼로그 닫기
                    Navigator.of(context).pop();
                  },
                )
              ],
            );
          });
    }
}

 

 


DatePicker

- 날짜를 선택

더보기
import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => _MyHomePageState();
}


class _MyHomePageState extends State<MyHomePage>{

  // 선택한 날짜 저장하기 위한 변수
  DateTime _selectedTime;

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("플러터 마스터"),
        ),

        // 여기서부터 수정!!!!!
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,

              children: <Widget>[
                ElevatedButton(
                  onPressed: () {
                    Future<DateTime> selectDate = showDatePicker(
                        context: context,
                        initialDate: DateTime.now(), // 초기값 설
                        firstDate: DateTime(2018),
                        lastDate: DateTime(2030),
                        builder: (BuildContext context, Widget child){
                          return Theme(
                            data: ThemeData.dark(),
                            child: child,
                          );
                        },
                    ); // Future 끝
                    // Futuer로 인해 사용자가 날짜를 선택할 때까지 코드가 대기탐
                    selectDate.then((dateTime) {
                      setState(() {
                        _selectedTime = dateTime;
                      });
                    });

                  }, child: Text('Date Picker~~'),
                ),

                // 선택 날짜를 보여줌
                Text('$_selectedTime'),


              ],

            ),

          ),
        ),
      );

    }

}

 

 


TimePicker

- 시간 선택

더보기
import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => _MyHomePageState();
}


class _MyHomePageState extends State<MyHomePage>{

  // 선택한 날짜 저장하기 위한 변수
  String _selectedTime;

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("플러터 마스터"),
        ),

        // 여기서부터 수정!!!!!
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,

              children: <Widget>[
                ElevatedButton(
                  onPressed: () {
                    Future<TimeOfDay> selectedTime = showTimePicker(
                      context: context,
                      initialTime: TimeOfDay.now(), // 초기값 설정
                    ); // Future 끝

                    // Futuer로 인해 사용자가 날짜를 선택할 때까지 코드가 대기탐

                    selectedTime.then((timeOfDay) {
                      setState(() {
                        _selectedTime = "${timeOfDay.hour}:${timeOfDay.minute}";
                      });
                    });

                  }, child: Text('Time Picker~~'),
                ),

                // 선택 날짜를 보여줌
                Text('$_selectedTime'),


              ],

            ),

          ),
        ),
      );

    }

}

 


 

fvm 설치하기

터미널에서 vim ~/.zshrc 입력 후 맨 아래에 아래 코드 넣어주기

export PATH="$PATH":"$HOME/bin/cache/dart-sdk/bin"
export PATH="$PATH":"$HOME/.pub-cache/bin"

그 후 터미널에서 아래 코드 입력해서 새로고침 해주기

source ~/.zshrc

 

그 다음 fvm 설치하기

pub global activate fvm

사용법

// 릴리즈 된 버전들 보기
fvm releases

// 원하는 버전 설치하기
fvm install [원하는 버전 적기]

// 설치된 플러터 버전들 보기
fvm list

 

 

  • 원하는 버전 프로젝트 만들기
    예: FlutterProject폴더에 -> fvm_test라는 이름으로 프로젝트를 만들고 싶은경우
// 먼저 터미널에서 FlutterProject로 이동한 후 아래 명령어 입력
flutter create fvm_test

 

    - 위에서 만든 프로젝트 fvm_test로 이동 후 

fvm use [원 하는 버전 입력]

 


안드로이드 스튜디오 세팅하기

1. 먼저 sdk의 전체 경로를 구해야 한다.
   터미널에서 플러터 프로젝트로 이동한다.

 

2. .fvm 숨김 폴더로 이동하기

 

3. ls로 확인해보면 flutter_sdk라는 폴더가 보임 거기로 이동 후 pwd 명령어로 전체 경로 구하기

 

4. 안드로이드 스튜디오에 적용하기

 

 

 

 


fvm 버전 업그레이드

dart pub global activate fvm

fvm --version

 

 

 

TextField

- labelText : 힌트를 표현

- border : 외곽선 구현

 


CheckBox와 Switch

- 체크박스, 라디오 버튼, 스위치를 표현

import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>{

  // 체크 상태를 나타내기 위한 변수
    var _isChecked = false;

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("플러터 마스터"),
        ),

        // 여기서부터 수정!!!!!
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,

              children: <Widget>[
                Checkbox(
                  value: _isChecked, // 위에서 선언한 변수를 사용

                  // ↱ 체크값이 변경되면 작동해서 -> value 인수로 넘어옴 -> setState() 통해 value의 변수 값이 변경되고 UI를 다시그림
                  onChanged: (value) {
                    setState(() {
                      _isChecked = value;
                    });
                  },
                ),
                SizedBox( // 위의 Checkbox의 크기를 조정
                  height: 70,
                ),

                Switch(
                  value: _isChecked,
                  onChanged: (value) {
                    setState(() {
                      _isChecked = value;
                    });
                  },
                ),
              ],
            ),

          ),
        ),
      );

    }
}

 


Radio와 RadioListTitle

- Radio는 그룹네에서 하나만 선택할 때 사용

- ListTitle은 ->라디오 선택하는 부분만 터치가능

- RadioListTitle은 -> 가로 전체 영역을 터치해서 선태가능

ListTitle
RadioListTitle

import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

// 라디오버튼의 내용들 (클래스와 동일한 레벨로 해야 함)
enum Gender {Man, Women}

class _MyHomePageState extends State<MyHomePage>{


  // 화면에 선택되어 보여지는 라디오 버튼 값 (현재 Women으로 되어 있으므로 첫 화면에는 Women이 체크되어 있음)
  Gender _gender = Gender.Women;

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("플러터 마스터"),
        ),

        // 여기서부터 수정!!!!!
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,

              children: <Widget>[
                ListTile(
                  title: Text("남자"),
                  leading: Radio(

                    // ↱라디오 버튼의 고유값
                    value: Gender.Man,

                    // ↱화면에 선택되어 보여지는 라디오 버튼의 값 (즉 체크를 하면-> 현재 라디오 버튼의 고유값으로 변경되어 보여지게 됨)
                    groupValue: _gender,
                    onChanged: (value){
                      setState(() {
                        _gender = value;
                      });
                    },
                  ),
                ),
                ListTile(
                  title: Text("여자"),
                  leading: Radio(
                    value: Gender.Women,
                    groupValue: _gender,
                    onChanged: (value){
                      setState(() {
                        _gender = value;
                      });
                    },
                  ),
                ),
                SizedBox(
                  height: 70,
                ),

                // 가로 화면 전체를 터치해서 선택되게 만들기!!
                RadioListTile(
                  title: Text("남자임"),
                  // ↱라디오 버튼의 고유값
                  value: Gender.Man,

                  // ↱화면에 선택되어 보여지는 라디오 버튼의 값 (즉 체크를 하면-> 현재 라디오 버튼의 고유값으로 변경되어 보여지게 됨)
                  groupValue: _gender,
                  onChanged: (value){
                    setState(() {
                      _gender = value;
                    });
                  }
                ),
                RadioListTile(
                  title: Text("여자임"),
                  value: Gender.Women,
                  groupValue: _gender,
                  onChanged: (value){
                    setState(() {
                      _gender = value;
                    });
                  },
                ),

              ],
            ),

          ),
        ),
      );

    }
}

 


DropDownButton

import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => _MyHomePageState();
}


class _MyHomePageState extends State<MyHomePage>{

  final _valueList = ['1-사과', '2-키위', '3-바나나'];
  var _selectedValue = '1-사과';

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("플러터 마스터"),
        ),

        // 여기서부터 수정!!!!!
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,

              children: <Widget>[
                DropdownButton(
                  value: _selectedValue,
                  //                ↱map()을 이용하여 -> _valueList의 문자열 3개를->  DropdownMenuItem의 값으로 반복하면서 하나씩 들어감
                  items: _valueList.map((value) {
                      return DropdownMenuItem(
                        value: value,
                        child: Text(value),
                      );
                    },
                    // toList()를 이용하여 -> 다시 위의 items에 리스트로 지정
                  ).toList(),
                  onChanged: (value){
                    setState(() {
                      _selectedValue = value;
                    });
                  },
                ),

              ],
            ),

          ),
        ),
      );

    }
}

 

 

Text

 

 


Image

- Network()메서드 ->  인터넷에 있는 이미지를 표시할 수 있다.

- asset() 메서드 ->  파일 이미지를 표시 한다.

    ↳ pubspec.yaml 파일을 수정해야함

코드
결과

 


Icon

 


Progress

- 로딩중이거나, 오래걸리는 작업을 할 때 -> 사용자에게 진행 중임을 보여줌

 


CircleAvatar

- 원형 위젯

 

 

- 네트워크 상에 존재하는 이미지 표시하기
 backgroundImage프로퍼티에->  NetworkImage 클래스의 인스턴스를 지정하면 된다.

 

ElevatedButton

- 입체감을 가지는 일반적인 버튼

- onPressed -> 버튼이 클릭 되었을 때 실행될 함수를 반드시 정의해줘야 한다.
                           (null을 지정하면 -> 버튼이 클릭되지 않는 비활성 상태가 됨)

import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatelessWidget {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("플러터 마스터"),
      ),

      // 여기서부터 수정!!!!!
      body: Center(
        child: ElevatedButton(
          child: Text("RaisedButton"),
          onPressed: (){
            
          },
        ),
      ),

    );

  }
}

 

 


TextButton

import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatelessWidget {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("플러터 마스터"),
      ),

      // 여기서부터 수정!!!!!
      body: Center(
        child: TextButton(
          child: Text("TextButton"),
          onPressed: (){

          },
        ),
      ),

    );

  }
}

 

 


IconButton

  • 자식 위젯을 포함할 수 없다.
import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatelessWidget {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("플러터 마스터"),
      ),

      // 여기서부터 수정!!!!!
      body: Center(
        child: IconButton(
          icon: Icon(Icons.add),
          color: Colors.red,
          iconSize: 100.0,
          onPressed: () {},
        ),
      ),

    );

  }
}


FloatingActionButton

더보기
import 'dart:math';

import 'package:flutter/material.dart';


// 앱 시작 부분
void main() {
  runApp(MyApp());
}


// 시작 클랙스, 머티리얼 디자인 앱 생성!
class MyApp extends StatelessWidget {
  // StatelessWidget 클래스는 상태를 가지지 않는 위젯을 구성하는 기본 클래스.
  // (상태를 가지지 않는 다는 것은-> 한 번 그려진 후 다시 그리지 않는 경우이며,
  // 프로퍼티로 변수를 가지지 않는다 다만 상수는 가질 수 있다.)

  // StatelessWidget 은 build() 메서드를 가지고 있고 이 메서드는 위젯을 생성할 때 호출 되면서 화면에 그릴 위젯을
  // 반환한다.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // title, theme, home 인수를 설정한다. (위젯의 속성을 표현)
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 시작 클래스가 실제로 표시하는 클래스,
// ignore: must_be_immutable
class MyHomePage extends StatelessWidget {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("플러터 마스터"),
      ),

      // 여기서부터 수정!!!!!
      body: Center(
        child: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: () {},
        ),
      ),
    );

  }
}

 

 

+ Recent posts