UI 작성

시작 / 일시정지 버튼 영역 UI 작성하기

  • bottomNavigationBar : 어떤 위젯도 배치할 수 있음

타이머 영역 UI 작성

  • Positioned

 

 


타이머 구현하기

  • Duration 클래스 주기

 

 

 

타이머 클래스와 필요한 변수들

 

시작 / 일시정지 /초기화 기능

 

시간표시하기

  •  ~/ 몫을 구하는 연산자,   초 부분 구하기
  • 1/100초 구하기 (00~99 표현하기)

 


 

랩타임 기록하기

 

랩타임 표시하기

 

 

전체코드⬇︎

더보기

 

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


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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'StopWatch',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),

      home: StopWatchPage(),
    );
  }
}


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

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

class _StopWatchPageState extends State<StopWatchPage> {

  Timer _timer;  // 타이머 선언

  var _time = 0;    // 0.01초마다 1씩 증가시킬 정수형 변수
  var _isRunning = false;   // 현재 시각 상태를 나타낼 변수 (타이머 시작하거나 멈추기 위함)

  List<String> _lapTimes = [];  // 랩타임에 표시할 시간을 저장할 리스트

  @override
  void dispose(){
    _timer?.cancel();  // 앱화면이 종료되면 타이머가 취소됨
    // ?. 는 타이머를 한 번도 동작시키지 않았을 때도(null인 상태) 안전하게 동작을 취소하기 위해 사용

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('스탑워치!~'),
      ),

      body: _buildBody(),

      bottomNavigationBar: BottomAppBar(
        child: Container(
          height: 50.0,
        ),
      ),

      // ↱ _clickButton() 메서드가 실행됨
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState((){
          _clickButton();
        }),

        // ↱_isRunning이  true인 경우면(스탑워치 진행중) pause아이콘 보여지고,  false면 시작 아이콘 보여짐
        child: _isRunning ? Icon(Icons.pause) : Icon(Icons.play_arrow),
      ),

      // ↱floatingActionButton 위젯의 위치를 지정
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    );
  }

  // 내용 부분
  Widget _buildBody(){

    // 초 부분과, 1/100초 부분을 분리하여 계산하기
    // ↱ _time 변수는 _start() 메서드로 인해 시간을 1/100초 단위로 저장함->
    //   이 것을 100을 나눌경우 몫이 초가 됨, 그리고 나머지가  1/100초 단위가 됨
    var sec = _time ~/ 100;  // " ~/ " 는 몫을 구하는 연산자이다.

    // 1/100 표현하기   ↱ 나머지 구하기  ↱ 문자열을 2자리로, 왼쪽의 빈곳을 0으로 채워 넣음
   var hundredth = '${_time % 100}'.padLeft(2, '0');

    return Center(
      child: Padding(
        padding: const EdgeInsets.only(top: 30),

        child: Stack(
          children: <Widget>[
            Column(
              children: <Widget>[
                // 시간 표시하는 영역
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: <Widget>[
                    Text( // 초
                      '$sec',
                      style: TextStyle(fontSize: 50.0),
                    ),
                    Text('$hundredth'),  //  1/100초
                  ],
                ),

                // 랩타임을 표시하는 영역
                Container(
                  width: 100,
                  height: 200,
                  child: ListView(
                    //        _lapTimes리스트를 -> map을 이용해 각각 Text 형태로 변환 후 -> 다시 리스트 형태로 반환
                    children: _lapTimes.map((t) => Text(t)).toList(),
                  ),
                ),
              ],
            ),

            // 초기화 버튼 (왼쪽 아래에 위치시키기 위해 Positioned 위젯으로 감쌈)
            Positioned(
              left: 10,
              bottom: 10,
              child: FloatingActionButton(
                backgroundColor: Colors.deepOrange,
                onPressed: _reset,  // 리셋 메서드 실행
                child: Icon(Icons.rotate_left),
              ),
            ),

            // 랩타임 버튼
            Positioned(
              right: 10,
              bottom: 10,
              child: ElevatedButton(
                onPressed: (){
                  setState(() {
                    //              ↱ x.xx 형태로 연결하여 전달
                    _recordLapTime('$sec.$hundredth');
                  });
                },
                child: Text('랩타임'),
              ),
            ),
          ],
        ),
      ),
    );
  }

  // 시작 또는 일시정지 버튼 클릭
  void _clickButton(){
    _isRunning = !_isRunning;  // 클릭할 때마다 boolean 값 변경

    if(_isRunning){
      _start();
    }else{
      _pause();
    }
  }


  // Timer 객체를 초기화하고 0.01초에 한 번씩 반복하게 하기
  void _start(){
    // 첫 번째 인수 Duration 인수를 설정하면 -> 두 번째 인수로 받은 함수에서 실행됨
    //                                   ↱0.01초
    _timer = Timer.periodic(Duration(milliseconds: 10), (timer) {
      setState(() {
        _time++; // 0.01초마다 _time변수의 값을 1씩 증가 시킴
      });
    });
  }

  // 타이머 일시정지하기
  void _pause(){
    _timer?.cancel();
  }

  // 초기화
  void _reset(){
    setState(() {
      _isRunning = false;
      _timer?.cancel();
      _lapTimes.clear();
      _time = 0;
    });
  }


  // 랩타임 기록하기
  void _recordLapTime(String time){
    //               ↱_lapTimes 리스트의 맨 앞에 추가하기
    _lapTimes.insert(0, '스탑워치 ${_lapTimes.length +1} 번째 실행 $time');
  }

}

TextFormField에 사용되는 속성

  • decoration : InputDecoration 클래스를 설정하여 외곽선, 힌트 등을 설정
  • controller : TextEditingController 인스턴스를 설정, 텍스트 필드를 조작할 때 사용
  • keyboardType : 입력 타입을 제한할 수 있음
  • validator : 입력값을 검증하고, 에러 메시지를 반환

  • 키와몸구게를 입력하는 화면 작성

더보기

 

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: BmiMain(),
    );
  }
}


// 첫 번째 페이지 (사용자의 입력을 받고 검증하기 위한 페이지)
class BmiMain extends StatefulWidget {

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

class _BmiMainState extends State<BmiMain> {

  // 폼의 상태를 얻기 위한 키
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('비만도 계산!'),
      ),

      body: Container(
        padding: const EdgeInsets.all(16.0),
        // 폼 (TextFormField를 사용하기 위해 Form으로 감싼다.)
        child: Form(
          key: _formKey,  // 키 할당
          child: Column(
            children: <Widget>[
              TextFormField(
                decoration: InputDecoration(
                  // ↱ 외곽선이 있고 힌트로 '키를 입력하시오'를 표시함
                  border: OutlineInputBorder(),
                  hintText: '키를 입력하시오',
                ),
                keyboardType: TextInputType.number,
              ),

              SizedBox(
                height: 16.0,
              ),

              TextFormField(
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: '몸무게'
                ),
                keyboardType: TextInputType.number,
              ),
              Container(
                margin: const EdgeInsets.only(top: 16.0),
                alignment: Alignment.centerRight,
                child: ElevatedButton(
                  onPressed: (){
                    // 폼에 입력된 값 검증하기
                    if(_formKey.currentState.validate()){
                      // 검증시 처리하기
                    }
                  },
                  child: Text('결과'),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}



// 두 번째 페이지 (결과를 보여주는 페이지)
class BmiResult extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

 

StatelessWidget은 -> 변화가 없는 위젯 이므로 클래스 내부에는 상수(final)만 존재가능
                                     상수는 값을 반드시 초기화 해야하므로 생성자를 통해 초기화를 해야함

 

 

결과화면 페이지 만들기

 

값 검증 및 화면전환 하기

키와 몸무게 값을 얻는 컨트롤로 준비하기

- TextFormField 위젯에 입력된 값을 가져오기 위해 -> TextEditingController 클래스 사용 (컨트롤러)

 

 

 

TextFormField 위젯과 컨트롤러 연결하기

 

결과 버튼 클릭 시 -> 폼을 검증하고 다음 화면으로 값 전달하기

 

 


결과 표시하기

BMI 계산하기

 

BMI 값에 따라 결과 표시하기

 

BMI 값에 따라 아이콘 표시하기

 

전체코드⬇︎

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

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

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: BmiMain(),
    );
  }
}


// 첫 번째 페이지 (사용자의 입력을 받고 검증하기 위한 페이지)
class BmiMain extends StatefulWidget {

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


class _BmiMainState extends State<BmiMain> {

  // 폼의 상태를 얻기 위한 키
  final _formKey = GlobalKey<FormState>();

  // 입력된 값 가져오는 컨트롤러 준비하기
  final _heightController = TextEditingController();
  final _weightController = TextEditingController();

  // ↱ 화면이 종료될 때는 반드시 사용한 컨트롤러 종료시켜야함!!
  @override
  void dispose(){
    _heightController.dispose();
    _weightController.dispose();
    super.dispose();
  }



  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('비만도 계산!'),
      ),

      body: Container(
        padding: const EdgeInsets.all(16.0),
        // 폼 (TextFormField를 사용하기 위해 Form으로 감싼다.)
        child: Form(
          key: _formKey,  // 키 할당
          child: Column(
            children: <Widget>[

              // 키 입력 필드
              TextFormField(
                decoration: InputDecoration(
                  // ↱ 외곽선이 있고 힌트로 '키를 입력하시오'를 표시함
                  border: OutlineInputBorder(),
                  hintText: '키를 입력하시오',
                ),

                // 컨트롤러 프로퍼티에 -> 컨트롤러를 지정하여 입력한 값을 컨트롤를 통해 얻음
                controller: _heightController,

                keyboardType: TextInputType.number,

                // 유효성 검사하기
                validator: (value){
                  if(value.trim().isEmpty){ // 입력한 값의 공백을 제거 후 비어 있는지 확인하기
                    return '키를 입력하세요';
                  }
                  return null;  // null을 반환하면 에러가 없는 것임
               },
              ),


              SizedBox(
                height: 16.0,
              ),

              // 몸무게 입력 필드
              TextFormField(
                decoration: InputDecoration(
                  border: OutlineInputBorder(),
                  hintText: '몸무게'
                ),

                keyboardType: TextInputType.number,

                // 컨트롤러 연결하기
                controller: _weightController,

                validator: (value){
                  if(value.trim().isEmpty){
                    return '몸무게를 입력하세요';
                  }
                  return null;
                },

              ),


              Container(
                margin: const EdgeInsets.only(top: 16.0),
                alignment: Alignment.centerRight,
                child: ElevatedButton(
                  onPressed: (){
                    // 폼에 입력된 값 검증하기
                    if(_formKey.currentState.validate()){
                      // 검증시 처리하기
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                          //                    ↱BmiResult 클래스의 생성자를 통해서 키와 몸무게를 double 타입으로 전달
                          builder: (context) => BmiResult(
                            // ↱ 입력받은 문자열을 -> double타입으로 변환하여 전달
                           double.parse(_heightController.text.trim()),
                           double.parse(_weightController.text.trim())),
                        ),
                      );
                    }
                  },
                  child: Text('결과'),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}



// 두 번째 페이지 (결과를 보여주는 페이지)
class BmiResult extends StatelessWidget {
  // StatelessWidget은 -> 변화가 없는 위젯 이므로 클래스 내부에는 상수(final)만 존재가능
  //                      상수는 값을 반드시 초기화 해야하므로 생성자를 통해 초기화를 해야함

  final double height;  // 키
  final double weight;  // 몸무게
  BmiResult(this.height, this.weight);  // 키와 몸무게를 받는 생성자

  @override
  Widget build(BuildContext context) {

    // BMI 값 계산하기
    final bmi = weight /((height / 100) * (height / 100));
    print('bmi-> $bmi');

    // BMI 값에 따라 결과 표시할 메서드
    String _calcBmi(double bmi){

      var result = '저체중';

      if(bmi >= 35){
        result = '고도 비만';
      }else if(bmi >= 30){
        result ='2단계 비만';
      }else if(bmi >= 25){
        result = '1단계 비만';
      }else if(bmi >= 23){
        result ='과체중';
      }else if(bmi >= 18.5){
        result ='정상';
      }
      return result;
    }

    // BMI 값에 따라 아이콘 변경하
    Widget _buildIcon(double bmi){
      if (bmi >= 23){
        return Icon(
          Icons.sentiment_very_dissatisfied,
          color: Colors.red,
          size: 100,
        );
      } else if(bmi >= 18.5){
        return Icon(
          Icons.sentiment_satisfied,
          color: Colors.green,
          size: 100,
        );
      } else{
        return Icon(
          Icons.sentiment_dissatisfied,
          color: Colors.orange,
          size: 100,
        );
      }
    }


    return Scaffold(
      appBar: AppBar(
        title: Text('비만도 계산기'),
      ),

      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              _calcBmi(bmi), // BMI 계산 결과를 문자열로 보여줌
              style: TextStyle(fontSize: 36),
            ),

            SizedBox(
              height: 16,
            ),

            // 계산 결과에 따른 아이콘 변경
            _buildIcon(bmi),
          ]
        ),
      ),
    );
  }
}

 

 

 

 

입력값 출력하기 (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),
      ),
    );
  }
}

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: () {},
        ),
      ),
    );

  }
}

 

 

Center

더보기
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: Container(
          color: Colors.red,
          width: 100,
          height: 100,
        ),
      ),

    );

  }
}

 


Padding

  • 안쪽 여백을 설정
  • EdgeInsets 클래스를 사용하여 설정 
    (앞에 const를 붙여 컴파일 타임 상수로 설정할 경우 -> 다시 사용될 경우 메모리에 있는 값을 재사용하는 장점이 있다.)
  • EdgeInsets.all() -> 4방향 모두를 설정함
  • EdgeInsets.only() -> 상하좌우 중에서 원하는 방향에만 값을 지정한다. (지정하지 않을 경우 기본 값 0.0)
  • EdgeIsets.FromLTRB() -> 4 방향의 값을 각각 지정

 


Align

  • 자식위젯의 정렬 방향을 정함

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: Align(
        alignment: Alignment.bottomRight,
        child: Container(
          color: Colors.red,
          width: 100,
          height: 100,
        ),
      ),

    );

  }
}

 


Expanded

  • 자식 위젯의 크기를 -> 최대로 학장시켜 줌
  • 여러 위젯에 동시에 적용할 경우 ->  flex 프로퍼티에 정숫값을 지정하여 비율을 지정할 수 있음 (기본값은 1)

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: Column(
        children: <Widget>[
          Expanded(
            flex: 3,
              child: Container(
                color: Colors.red,
              ),
          ),
          Expanded(
            flex: 2,
              child: Container(
                color: Colors.yellow,
              ),
          ),
          Expanded(
              flex: 1,
                child: Container(
                  color: Colors.blue,
                ),
          ),
        ],
      )

    );

  }
}

3:2:1 비율

 

 


SizedBox

  • 크기에 관련한 프로퍼티가 없는 위젯을 특정 크기로 만들고 싶을 때 사용

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: SizedBox(
        width: 100,
        height: 100,
        child: Container(
          color: Colors.red,
        ),
      ),

    );

  }
}

 

 


Card

  • 기본적으로 크기가 0이므로 -> 자식 위젯에 따라 크기가 결정된다.
  • elevation -> 그림자의 깊이 조절 가능
  • shape ->  카드 모양을 변경 
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: Card(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(16.0),
          ),
          elevation: 7.0,
          child: Container(
            width: 100,
            height: 100,
            color: Colors.yellow,
          ),
        ),
      ),

    );

  }
}

 

+ Recent posts