페이지 이동 에니메이션

 


애니메이션을 세밀하게 조정하기

secondPage2.dart

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


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

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

class _SecondPageState extends State<SecondPage2>
  with SingleTickerProviderStateMixin {

  // 애니메이션 컨트롤러, 애니메이션 객체 만들기
  //   ↱ AnimationController -> 프레임마다 새로운 값을 생성하는 애니메이션
  //     (지정된 시간 동안 선형보간법을 이용해 시작점부터 끝점 사이의 숫자를 -> 초당 60개씩 생성)
  late AnimationController _animationController;

  late Animation _rotateAnimation;
  late Animation _scaleAnimation;
  late Animation _transAnimation;

  @override
  void initState(){
    super.initState();
    //                                           ↱ 애니메이션 재생시간          ↱애니메이션 표현할 대상
    _animationController = AnimationController(duration: Duration(seconds: 5), vsync: this);
    //                  ↱ 기본적으로 생성해주는 애니메이션 컨트롤러 숫자의 범위는 0.0 ~ 1.0 임 -> 다른 범위, 데이터 유형이 필요한 경우 사용
    _rotateAnimation = Tween<double>(begin: 0, end: pi * 10).animate(_animationController); // 화전
    _scaleAnimation = Tween<double>(begin: 1, end: 0).animate(_animationController);        // 크기
    _transAnimation = Tween<Offset>(begin: Offset(0,0), end: Offset(200,200)).animate(_animationController);  //위젯의 방향
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('애니메이션 예제2'),
      ),

      body: Container(
        child: Center(
          child: Column(
            children: [
              AnimatedBuilder(
                animation: _rotateAnimation,
                //  ↱ 애니메이션 어떻게 보여줄지 정의하기
                builder: (context, widget){
                  return Transform.translate( // 위젯의 방향 설정
                    offset: _transAnimation.value,

                    child: Transform.rotate( // 위젯의 회전
                      angle: _rotateAnimation.value,

                      child: Transform.scale(  // 위젯의 크기를 조절
                        scale: _scaleAnimation.value,
                        child: widget,
                      ),
                    ),
                  );
                },
                child: Hero(
                    tag: 'detail1',
                    child: Icon(Icons.cake, size: 300,)
                ),
              ),
              // ignore: deprecated_member_use
              RaisedButton(
                onPressed: (){
                  _animationController.forward();
                },
                child: Text('로테이션 시작하기'),
              ),
            ],
            mainAxisAlignment: MainAxisAlignment.center,
          ),
        ),
      ),
    );
  }
}

 


 

나만의 인트로 화면 만들기

 

 

인트로 화면의 애니매이션 만들기 saturnLoading.dart

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

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

  @override
  _SaturnLoadingState createState() => _SaturnLoadingState();


  void start(){
    _SaturnLoadingState().start();
  }

  void stop(){
    _SaturnLoadingState().stop();
  }

}


class _SaturnLoadingState extends State<SaturnLoading>
  with SingleTickerProviderStateMixin {

  late AnimationController _animationController;
  late Animation _animation;

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

    // 3초동안 동작하는 애니메이션
    _animationController = AnimationController(vsync :this, duration: Duration(seconds: 3));
    // 애니메이션 시작점과 끝점 정의하기
    _animation = Tween<double>(begin: 0, end: pi * 2).animate(_animationController);
    _animationController.repeat();
  }

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

  void start(){
    _animationController.repeat();
  }

  void stop(){
    _animationController.stop(canceled: true);
  }


  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _animationController,
      builder: (context, child){
        return SizedBox(
          width: 100,
          height: 100,

          child: Stack(
            children: [
              Image.asset(
                'repo/images/circle.png',
                width: 100,
                height: 100,
              ),
              Center(
                child: Image.asset(
                  'repo/images/sunny.png',
                  width: 30,
                  height: 30,
                ),
              ),
              Padding(
                padding: EdgeInsets.all(5),
                child: Transform.rotate(
                  angle: _animation.value,
                  origin: Offset(35, 35),  // 회전의 기준점 지정
                  child: Image.asset(
                    'repo/images/saturn.png',
                    width: 20,
                    height: 20,
                  ),
                ),
              ),
            ],
          ),
        );
      });
  }
}

 

 

애니메이션 보여줄 인트로 화면 (애니메이션 보여주다가 5초 후 메인으로 이동)   animation_intro.dart

더보기
import 'package:flutter/material.dart';
import 'package:psw1/animation/saturnLoading.dart';
import 'dart:async';

import 'package:psw1/main_animation.dart';


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

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

class _AnimationIntroPageState extends State<AnimationIntroPage> {

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


  // 5초후 메인 화면으로 이동하기
  Future<Timer> loadData() async {
    return Timer(Duration(seconds: 5), onDoneLoading);
  }

  onDoneLoading() async{
    Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> AnimationApp()));
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Center(
          child: Column(
            children: [
              Text('애니메이션 앱!~'),
              SizedBox(
                height: 20,
              ),
              SaturnLoading()  // 애니메이션 페이지 풀러오기
            ],
            mainAxisAlignment: MainAxisAlignment.center,
          ),
        ),
      ),
    );
  }
}

 

 

 

Curves 공식 문서

 

그래프 애니메이션 구현

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'main_animation',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: AnimationApp(),
    );
  }
}

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

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

class _AnimationAppState extends State<AnimationApp> {
  List<People> peoples = [];
  int current = 0;

  @override
  void initState(){
    super.initState();
    peoples.add(People('스미스', 100, 92));
    peoples.add(People('메리', 162, 55));
    peoples.add(People('존', 172, 75));
    peoples.add(People('바트', 130, 40));
    peoples.add(People('콘', 192, 140));
    peoples.add(People('디디', 100, 80));
    peoples.add(People('로니콜먼', 185, 110));
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('애니메이션 활용해보기'),
      ),

      body: Container(
        child: Center(
          child: Column(
            children: [
              SizedBox(
                child: Row(
                  children: [
                    SizedBox(
                      width: 100,
                      child: Text('이름 : ${peoples[current].name}'),
                    ),

                    AnimatedContainer(
                      duration: Duration(seconds: 2),
                      curve: Curves.bounceIn,
                      color: Colors.amber,
                      child: Text(
                        '키 ${peoples[current].height}',
                        textAlign: TextAlign.center,
                      ),
                      width: 50,
                      height: peoples[current].height,
                    ),
                    AnimatedContainer(
                      duration: Duration(seconds: 2),
                      curve: Curves.easeInCubic,
                      color: Colors.blue,
                      child: Text(
                        '몸무게 ${peoples[current].weight}',
                        textAlign: TextAlign.center,
                      ),
                      width: 50,
                      height: peoples[current].height,
                    ),
                    AnimatedContainer(
                      duration: Duration(seconds: 2),
                      curve: Curves.linear,
                      color: Colors.pinkAccent,
                      child: Text(
                        'bmi : ${peoples[current].bmi.toString().substring(0, 2)}',
                        textAlign: TextAlign.center,
                      ),
                      width: 50,
                      height: peoples[current].bmi,
                    ),
                  ],
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  crossAxisAlignment: CrossAxisAlignment.end,
                ),
                height: 200,
              ),
              // ignore: deprecated_member_use
              RaisedButton(
                onPressed: (){
                  setState(() {
                    if (current < peoples.length -1){
                      current++;
                    }
                  });
                },
                child: Text('다음'),
              ),
              // ignore: deprecated_member_use
              RaisedButton(
                onPressed: (){
                  setState(() {
                    if(current > 0){
                      current--;
                    }
                  });
                },
                child: Text('이전'),
              ),
            ],
            mainAxisAlignment: MainAxisAlignment.center,
          ),
        ),
      ),
    );
  }
}

 

 

색감 변경 애니메이션

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'main_animation',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: AnimationApp(),
    );
  }
}

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

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

class _AnimationAppState extends State<AnimationApp> {
  List<People> peoples = [];
  int current = 0;

  // 색상 변경하기
  Color weightColor = Colors.blue;

  @override
  void initState(){
    super.initState();
    peoples.add(People('스미스', 100, 92));
    peoples.add(People('메리', 162, 55));
    peoples.add(People('존', 182, 75));
    peoples.add(People('바트', 130, 40));
    peoples.add(People('콘', 192, 140));
    peoples.add(People('디디', 160, 80));
    peoples.add(People('로니콜먼', 185, 110));
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('애니메이션 활용해보기'),
      ),

      body: Container(
        child: Center(
          child: Column(
            children: [
              SizedBox(
                child: Row(
                  children: [
                    SizedBox(
                      width: 100,
                      child: Text('이름 : ${peoples[current].name}'),
                    ),

                    AnimatedContainer(
                      duration: Duration(seconds: 2),
                      curve: Curves.bounceIn,
                      color: Colors.amber,
                      child: Text(
                        '키 ${peoples[current].height}',
                        textAlign: TextAlign.center,
                      ),
                      width: 50,
                      height: peoples[current].height,
                    ),
                    AnimatedContainer(
                      duration: Duration(seconds: 1),
                      curve: Curves.easeInCubic,
                      color: weightColor,
                      child: Text(
                        '몸무게 ${peoples[current].weight}',
                        textAlign: TextAlign.center,
                      ),
                      width: 50,
                      height: peoples[current].height,
                    ),
                    AnimatedContainer(
                      duration: Duration(seconds: 2),
                      curve: Curves.linear,
                      color: Colors.pinkAccent,
                      child: Text(
                        'bmi : ${peoples[current].bmi.toString().substring(0, 2)}',
                        textAlign: TextAlign.center,
                      ),
                      width: 50,
                      height: peoples[current].bmi,
                    ),
                  ],
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  crossAxisAlignment: CrossAxisAlignment.end,
                ),
                height: 200,
              ),
              // ignore: deprecated_member_use
              RaisedButton(
                onPressed: (){
                  setState(() {
                    if (current < peoples.length -1){
                      current++;
                    }
                    _changeWeightColor(peoples[current].weight);
                  });
                },
                child: Text('다음'),
              ),
              // ignore: deprecated_member_use
              RaisedButton(
                onPressed: (){
                  setState(() {
                    if(current > 0){
                      current--;
                    }
                    _changeWeightColor(peoples[current].weight);
                  });
                },
                child: Text('이전'),
              ),
            ],
            mainAxisAlignment: MainAxisAlignment.center,
          ),
        ),
      ),
    );
  }

  void _changeWeightColor (double weight){
    if (weight < 40){
      weightColor = Colors.blueAccent;
    }else if(weight < 60){
      weightColor = Colors.indigo;
    }else if(weight < 80) {
      weightColor = Colors.orange;
    }else {
      weightColor = Colors.red;
    }
  }
}

 

 

 

불투명도 애니메이션

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'main_animation',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: AnimationApp(),
    );
  }
}

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

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

class _AnimationAppState extends State<AnimationApp> {
  List<People> peoples = [];
  int current = 0;

  // 색상 변경하기
  Color weightColor = Colors.blue;

  // 투명도 설정하기
  double _opacity = 1;

  @override
  void initState(){
    super.initState();
    peoples.add(People('스미스', 100, 92));
    peoples.add(People('메리', 162, 55));
    peoples.add(People('존', 182, 75));
    peoples.add(People('바트', 130, 40));
    peoples.add(People('콘', 192, 140));
    peoples.add(People('디디', 160, 80));
    peoples.add(People('로니콜먼', 185, 110));
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('애니메이션 활용해보기'),
      ),

      body: Container(
        child: Center(
          child: Column(
            children: [
              AnimatedOpacity(
                opacity: _opacity,
                duration: Duration(seconds: 1),
                child: SizedBox(
                  child: Row(
                    children: [
                      SizedBox(
                        width: 100,
                        child: Text('이름 : ${peoples[current].name}'),
                      ),

                      AnimatedContainer(
                        duration: Duration(seconds: 2),
                        curve: Curves.bounceIn,
                        color: Colors.amber,
                        child: Text(
                          '키 ${peoples[current].height}',
                          textAlign: TextAlign.center,
                        ),
                        width: 50,
                        height: peoples[current].height,
                      ),
                      AnimatedContainer(
                        duration: Duration(seconds: 1),
                        curve: Curves.easeInCubic,
                        color: weightColor,
                        child: Text(
                          '몸무게 ${peoples[current].weight}',
                          textAlign: TextAlign.center,
                        ),
                        width: 50,
                        height: peoples[current].height,
                      ),
                      AnimatedContainer(
                        duration: Duration(seconds: 2),
                        curve: Curves.linear,
                        color: Colors.pinkAccent,
                        child: Text(
                          'bmi : ${peoples[current].bmi.toString().substring(0, 2)}',
                          textAlign: TextAlign.center,
                        ),
                        width: 50,
                        height: peoples[current].bmi,
                      ),
                    ],
                    mainAxisAlignment: MainAxisAlignment.spaceAround,
                    crossAxisAlignment: CrossAxisAlignment.end,
                  ),
                  height: 200,
                ),
              ),
              // ignore: deprecated_member_use
              RaisedButton(
                onPressed: (){
                  setState(() {
                    if (current < peoples.length -1){
                      current++;
                    }
                    _changeWeightColor(peoples[current].weight);
                  });
                },
                child: Text('다음'),
              ),
              // ignore: deprecated_member_use
              RaisedButton(
                onPressed: (){
                  setState(() {
                    if(current > 0){
                      current--;
                    }
                    _changeWeightColor(peoples[current].weight);
                  });
                },
                child: Text('이전'),
              ),
              // ignore: deprecated_member_use
              RaisedButton(
                onPressed: (){
                  setState(() {
                    _opacity == 1 ? _opacity = 0.2 : _opacity = 1;
                  });
                },
                child: Text('사라지기'),
              ),
            ],
            mainAxisAlignment: MainAxisAlignment.center,
          ),
        ),
      ),
    );
  }

  void _changeWeightColor (double weight){
    if (weight < 40){
      weightColor = Colors.blueAccent;
    }else if(weight < 60){
      weightColor = Colors.indigo;
    }else if(weight < 80) {
      weightColor = Colors.orange;
    }else {
      weightColor = Colors.red;
    }
  }
}

 

 

 


 

import 'package:flutter/material.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';

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

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

class _FileAppState extends State<FileApp> {

  int _count = 0;

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

    // 앱이 실행 될 때 파일에서 가지고온 데이터 표시하기위에 initState에서 실행함
    readCountFile();
  }

  // 문자열 형태로 파일을 만들어 저장하기
  void writeCountFile(int count) async{
    //               ↱ 내부 저장소 경로 가져오기
    var dir = await getApplicationDocumentsDirectory();
    File(dir.path + '/count.txt').writeAsStringSync(count.toString());
  }


  // 파일 읽기
  void readCountFile() async{
    try{
      var dir = await getApplicationDocumentsDirectory();
      var file = await File(dir.path + '/count.txt').readAsString();
      print('파일-> $file');

      setState(() {
        _count = int.parse(file);
      });
    }catch(e){
      print(e.toString());
    }

  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('파일 예제2'),
      ),

      body: Container(
        child: Center(
          child: Text(
            '$_count',
            style: TextStyle(fontSize: 40),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          setState(() {
            _count++;
          });
          writeCountFile(_count);
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

 

 

 

  • 공유 환경설정에 저장하는 데이터 ->   키 : 값 쌍으로 구성되어야함  (키는 중복되지 않아야 함)
  • 공유 환경설정에 저장할 수 있는 값 ->  int,  String,  bool,  double, StringList 등 
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  // 데이터 저장하는 함수
  void _setData(int value) async{
    var key = 'count';

    SharedPreferences pref = await SharedPreferences.getInstance();

    // SharedPreferencesdml 세터 함수
    pref.setInt(key, value);

  }

  //데이터를 가져오는 함수
  void _loadData() async{
    var key = 'count';
    SharedPreferences pref = await SharedPreferences.getInstance();

    setState(() {
      //                      ↱ 키 값으로 데이터 가지고 옴
      var value = pref.getInt(key);

      if (value == null){
        _counter = 0;
      }else{
        _counter = value;
      }
    });
  }


  void _incrementCounter() {
    setState(() {
      _counter++;
      // 숫자사 증가되면 그 숫자를 저장해 놓음
      _setData(_counter);
    });
  }

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

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(

        title: Text(widget.title),
      ),
      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

 

route 페이지 이동 pushNamed, pushReplacementNamed

 

main_todoLIst.dart

import 'package:flutter/material.dart';
import 'package:psw1/todo/secondDetail.dart';
import 'package:psw1/todo/subDetail.dart';
import 'package:psw1/todo/thirdPage.dart';


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

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

  static const String _title = 'Widget Example!!';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      initialRoute: "/",
      routes: {
        '/': (context)=> SubDetail(),
        '/second':(context)=> SecondDetail(),
        '/third':(context)=> ThirdDetail(),
      },
    );
  }
}

 

 

subDetail.dart

import 'package:flutter/material.dart';

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

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

class _SubDetailState extends State<SubDetail> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Sub Detail Example!!'),
      ),

      body: Container(
        child: Center(
          // ignore: deprecated_member_use
          child: RaisedButton(
            onPressed: () {
              //                       ↱ 스택 메모리에 있는 자료를 교체함(스택에 자료를 추가하지 않고 기존 자료를 교체함)
              // Navigator.of(context).pushReplacementNamed('/second');

              //                      ↱ 스택에 새로운 자료를 추가(즉 /second -> secondDetail 등록해 놈)
              Navigator.of(context).pushNamed('/second');
            },
            child: Text('두 번째 페이지로 이동하기'),
          ),
        ),
      ),
    );
  }
}

 

 

secondDetail.dart

import 'package:flutter/material.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('second Page!'),
      ),
      body: Container(
        child: Center(
          // ignore: deprecated_member_use
          child: RaisedButton(
            onPressed: (){
              //                     ↱ 전 페이지에서 스택에 등록한 /second (secondDetail) 를 -> /third (ThirdDetail)로 변경시킴
              Navigator.of(context).pushReplacementNamed('/third');
            },
            child: Text('세 번째 페이지로 이동하기'),

          ),
        ),
      ),
    );
  }
}

 

 

thirdPage.dart

import 'package:flutter/material.dart';

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

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

      body: Container(
        child: Center(
          // ignore: deprecated_member_use
          child: RaisedButton(
            onPressed: (){
              Navigator.of(context).pop();
            },
            child: Text('첫 번째 페이지로 돌아가기'),
          ),
        ),
      ),
    );
  }
}

 

 



 

subDetail.dart

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

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

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

class _SubDetailState extends State<SubDetail> {

  List<String> todoList = [];

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

    todoList.add('낮잠 자기');
    todoList.add('게임 하기');
    todoList.add('하체 운동 하기');
    todoList.add('단백질 먹기');

  }

  @override
  Widget build(BuildContext context) {

    void _addNavigation(BuildContext context) async{
      //              ↱ secondDetail로 이동하고 결과를 가지고 올때까지 기다림
      final result = await Navigator.of(context).pushNamed('/second');

      setState(() {
        if(result != null && result.toString().length != 0){
          todoList.add(result.toString());
        }
      });
    }


    return Scaffold(
      appBar: AppBar(
        title: Text('Sub Detail Example!!'),
      ),

      body: ListView.builder(
        itemBuilder: (context, index){
          return Card(
            child: InkWell(
              child: Text(
                todoList[index],
                style: TextStyle(fontSize: 30),
              ),
              onTap: (){
                //                       ↱ 스택 메모리에 있는 자료를 교체함(스택에 자료를 추가하지 않고 기존 자료를 교체함)
                // Navigator.of(context).pushReplacementNamed('/second');

                //                      ↱ 스택에 새로운 자료를 추가(즉 /third -> thirdPage 등록해 놈)
                Navigator.of(context).pushNamed('/third', arguments: todoList[index]);
              },
            ),
          );
        }, itemCount: todoList.length,
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          _addNavigation(context);
        },
        child: Icon(Icons.add),
      ),
    );
  }
}

 

secondDetail.dart

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

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

  @override
  Widget build(BuildContext context) {

    TextEditingController textController = new TextEditingController();

    return Scaffold(
      appBar: AppBar(
        title: Text('second Detail!'),
      ),
      body: Container(
        child: Center(
          child: Column(
            children: [
              TextField(
                controller: textController,
                keyboardType: TextInputType.text,
              ),
              SizedBox(
                height: 20,
              ),
              // ignore: deprecated_member_use
              RaisedButton(
                onPressed: () {
                  //                         ↱ pop되면서 데이터 가지고감
                  Navigator.of(context).pop(textController.value.text);
                },
                child: Text('저장하기'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

thirdPage.dart

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

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

  @override
  Widget build(BuildContext context) {

    //                  ↱ 라우터로 전달받으 ㄴ데이터 가져오기
    final Object? args = ModalRoute.of(context)!.settings.arguments;

    return Scaffold(
      appBar: AppBar(
        title: Text('Tird Page'),
      ),

      body: Container(
        child: Center(
          // ignore: deprecated_member_use
          child: Text(
            args.toString(),
            style: TextStyle(fontSize: 30),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          Navigator.of(context).pop();
        },
        child: Icon(Icons.arrow_back),
      ),
    );
  }
}

 

 

import 'package:flutter/material.dart';

void main(){
  runApp(MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '서브 페이지 테스트!!',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      // home: FirstPage(),
      initialRoute: '/',
      routes: {'/':(context)=> FirstPage(),
              '/second':(context)=> SecondPage()},
    );
  }
}


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

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

class _FirstPageState extends State<FirstPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('서브 페이지 메인!'),
      ),

      body: Container(
        child: Center(
          child: Text('첫 번째 페이지!'),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          Navigator.of(context).pushNamed('/second');
        },
        child: Icon(Icons.add),
      ),
    );
  }
}


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

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

      body: Container(
        child: Center(
          // ignore: deprecated_member_use
          child: RaisedButton(
            onPressed: (){
              Navigator.of(context).pop();
            },
            child: Text('돌아가기'),
          ),
        ),
      ),
    );
  }
}

 

 

 

 

 

 

import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'dart:core';

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

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

class _LargeFileMainState extends State<LargeFileMain> {
  // 내려받을 이미지 주소
  // final imgUrl = 'https://images.pexels.com/photos/240040/pexels-photo-240040.jpeg'
  //                 '?auto=compress';
  bool downloading = false;  // 지금 내려받는 중인지 확인용 (true 면 현재 파일을 내려받고 있다는 의미)
  var progressString ='';    // 현재 얼마나 내려받았는지 표시
  var file;                  // 내려받을 파일
  TextEditingController? _editingController;

  @override
  void initState(){
    super.initState();
    _editingController = new TextEditingController(
      text: 'https://images.pexels.com/photos/240040/pexels-photo-240040.jpeg'
            '?auto=compress');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: TextField(
          controller: _editingController,
          style: TextStyle(color: Colors.white),
          keyboardType: TextInputType.text,
          decoration: InputDecoration(hintText: 'url을 입력하시오'),
        ),
      ),

      body: Center(
        child: downloading
          ? Container(
              height: 120.0,
              width: 200.0,
              child: Card(
                color: Colors.black,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    CircularProgressIndicator(),
                    SizedBox(
                      height: 20.0,
                    ),
                    Text(
                      '다운로드 진행중: $progressString',
                      style: TextStyle(
                        color: Colors.white,
                      ),
                    ),
                  ],
                ),
              ),
            )

            // downloading이 false일때 실행함 (즉 다운로드를 안 했을때, 또는 다운로드가 완료되었을 때 실행됨)
            // ↱아직 데이터가 없지만 앞으로 데이터를 받아서 처리한 후에 만들겠다는 의미
          :FutureBuilder(
                               //↱ FutureBuilder.future에서 받아온 데이터를 저장한 dynamic 형태의 변수임
            builder: (context, snapshot){
              switch (snapshot.connectionState){
                case ConnectionState.none: // null 일때
                  print('none');
                  return Text('다운 받은 이미지 없음');

                case ConnectionState.waiting:  // 연결되기 전 (아직 데이터 반환 받기전)
                  print('waiting');
                  return CircularProgressIndicator();

                case ConnectionState.active:  // 하나이상의 데이터를 받았을 때
                  print('active');
                  return CircularProgressIndicator();

                case ConnectionState.done:  // 모든 데이터 받아서 연결이 끝났을 때
                  print('done');
                  if(snapshot.hasData){
                    return snapshot.data! as Widget;
                    //    ↳ downloadWidget(file) 함수가 반환하는 데이터 이다..
                  }
              }
              print('end process!!!');
              return Text('데이터 없음');
            },

            future: file == null ? null : downloadWidget(file),
          ),
      ),

      floatingActionButton: FloatingActionButton(
        onPressed: (){
          downloadFile();
        },
        child: Icon(Icons.file_download),
      ),

    );

  }

  // 파일 다운 받기 메서드
  Future<void> downloadFile() async{
    Dio dio = Dio();
    try{
      // ↱ 플러터 앱의 내부 디렉토리를 가져옴
      var dir = await getApplicationDocumentsDirectory();
      // ↱ url에 있는 파일 다운, ↱내부디렉토리에 myimage.jpg 이름으로 저장
      await dio.download(_editingController!.value.text, '${dir.path}/myimage.jpg',
          // ↱ 진행상황을 표시 ↱ rec 는 지금까지 내려받은 데이터, total은 파일의 전체 크기임
          onReceiveProgress: (rec, total){
            print('다운로드 진행: $rec , 파일크기: $total');

            // ↱내려받은 파일의 저장주소 및 파일명을 저장
            file = '${dir.path}/myimage.jpg';
            print('저장된 주소: $file');

            setState(() {
              downloading = true;  // 파일 다운받기 시작하면 true로 변경됨
              // ↱ 파일 다운 진행 상황을 100분율로 계산해서 보여주기
              progressString = ((rec / total) * 100).toStringAsFixed(0) + '%';
            });
          });
    }catch (e){
      print('에러-> $e');
    }

    // ↱ 다운로드 완료되면 실행됨
    setState(() {
      downloading = false;
      progressString = 'Completed!!';
    });
    print('Download 완료');
  }

  Future<Widget> downloadWidget(String filePath) async{
    File file = File(filePath);
    bool exist = await file.exists(); // 파일존재 여부 확인
    new FileImage(file).evict();
    //   ↳ 캐시 초기화 (만약 캐시에 같은 이름의 이미지가 있으면 -> 이미지를 바꾸지 않고 해당하는 이미지를 사용하는데
    //                  evict()을 사용하면 -> 캐시를 비우고 같은 이름이어도 이미지를 갱신함.

    if (exist){
      return Center(
        child: Column(
          children: <Widget>[
            Image.file(file)
          ],
        ),
      );

    }else {
      return Text('데이타가 없군요');
    }
  }
}

탭바 만들기

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

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

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

class _CupertinoMainState extends State<CupertinoMain> {

  late CupertinoTabBar tabBar;

  @override
  void initState(){
    super.initState();
    
    // 탭바생성
    tabBar = CupertinoTabBar(
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(CupertinoIcons.home),),
          BottomNavigationBarItem(icon: Icon(CupertinoIcons.add),),
        ]);
  }

  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoTabScaffold(
        tabBar: tabBar,
        //                    ↱탭 클릭시 해당하는 탭의 인덱스 들어옴
        tabBuilder: (context, value){
          if(value == 0){
            return Container(
              child: Center(
                child: Text('쿠퍼티노 탭 1'),
              ),
            );
          } else{
            return Container(
              child: Center(
                child: Text('쿠퍼티노 탭 2'),
              ),
            );
          }
        },
      ),
    );
  }
}

 

 

 



쿠퍼티노 리스트뷰 만들기

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

class CupertinoFirstPage extends StatelessWidget {
  const CupertinoFirstPage({Key? key, required this.animalList}) : super(key: key);

  final List<Animal> animalList;

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('동물리스트!!'),
      ),
      child: ListView.builder(
        itemBuilder: (context, index){
          return Container(
            padding: EdgeInsets.all(5),
            height: 100,
            child: Column(
              children: <Widget>[
                Row(
                  children: <Widget>[
                    Image.asset(
                      animalList[index].imagePath,
                      fit: BoxFit.contain,
                      width: 80,
                      height: 80,
                    ),
                    Text(animalList[index].animalName)
                  ],
                ),
                Container(
                  height: 2,
                  color: CupertinoColors.systemGrey,
                ),
              ],
            ),
          );
        },itemCount: animalList.length,
      ),
    );
  }
}

 

 

 

 


 

cupertinoMain.dart

더보기
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:psw1/animalItem.dart';
import 'package:psw1/iosSub/cupertinoFirstPage.dart';
import 'package:psw1/iosSub/cupertinoSecondPage.dart';

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

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

class _CupertinoMainState extends State<CupertinoMain> {

  late CupertinoTabBar tabBar;
  List<Animal> animalList = <Animal>[];

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

    // 탭바생성
    tabBar = CupertinoTabBar(
        items: <BottomNavigationBarItem>[
          BottomNavigationBarItem(icon: Icon(CupertinoIcons.home),),
          BottomNavigationBarItem(icon: Icon(CupertinoIcons.add),),
        ]);

    // 동물 리스트 만들기
    animalList.add(Animal(imagePath: 'repo/images/bee.png', animalName: '벌', kind: '곤충'));
    animalList.add(Animal(imagePath: 'repo/images/cat.png', animalName: '고양이', kind: '포유류'));
    animalList.add(Animal(imagePath: 'repo/images/cow.png', animalName: '젖소', kind: '포유류'));
    animalList.add(Animal(imagePath: "repo/images/dog.png", animalName: "강아지", kind: "포유류"));
    animalList.add(Animal(imagePath: "repo/images/fox.png", animalName: "여우", kind: "포유류"));
    animalList.add(Animal(imagePath: "repo/images/monkey.png", animalName: "원숭이", kind: "영장류"));
    animalList.add(Animal(imagePath: "repo/images/pig.png", animalName: "돼지", kind: "포유류"));
    animalList.add(Animal(imagePath: "repo/images/wolf.png", animalName: "늑대", kind: "포유류"));

  }

  @override
  Widget build(BuildContext context) {
    return CupertinoApp(
      home: CupertinoTabScaffold(
        tabBar: tabBar,
        //                    ↱탭 클릭시 해당하는 탭의 인덱스 들어옴
        tabBuilder: (context, value){
          if(value == 0){
            return CupertinoFirstPage(
                animalList: animalList
            );
          } else{
            return CupertinoSecondPage(
              animalList: animalList,
            );
          }
        },
      ),
    );
  }
}

 

 


cupertinoFirstPage.dart

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

class CupertinoFirstPage extends StatelessWidget {
  const CupertinoFirstPage({Key? key, required this.animalList}) : super(key: key);

  final List<Animal> animalList;

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('동물리스트!!'),
      ),
      child: ListView.builder(
        itemBuilder: (context, index){
          return Container(
            padding: EdgeInsets.all(5),
            height: 100,
            child: Column(
              children: <Widget>[
                Row(
                  children: <Widget>[
                    Image.asset(
                      animalList[index].imagePath,
                      fit: BoxFit.contain,
                      width: 80,
                      height: 80,
                    ),
                    Text(animalList[index].animalName)
                  ],
                ),
                Container(
                  height: 2,
                  color: CupertinoColors.systemGrey,
                ),
              ],
            ),
          );
        },itemCount: animalList.length,
      ),
    );
  }
}

 

 

 


cupertinoSecondPage.dart

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


class CupertinoSecondPage extends StatefulWidget {
  const CupertinoSecondPage({Key? key, required this.animalList}) : super(key: key);

  final List<Animal> animalList;

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

class _CupertinoSecondPageState extends State<CupertinoSecondPage> {

  TextEditingController? _textController;  // 동물 이름
  // TextEditingController _textController = TextEditingController();
  int _kindChoice = 0;                                // 동물 종류
  bool _flyExist = false;                             // 날개 유무
  String? _imagePath;                             // 동물 이미지

  // 세그먼트 위젯에 구성할 내용 담기
  Map<int, Widget> segmentWidgets ={
    0:SizedBox(
      child: Text('양서류', textAlign: TextAlign.center,),
      width: 80,
    ),
    1:SizedBox(
      child: Text('포유류', textAlign: TextAlign.center,),
      width: 80,
    ),
    2:SizedBox(
      child: Text('파충류', textAlign: TextAlign.center,),
      width: 80,
    ),
  };

  @override
  void initState(){
    super.initState();
    _textController = TextEditingController();
  }

  @override
  Widget build(BuildContext context) {

    dynamic getKind(int radioValue){
      switch (radioValue){
        case 0:
          return '양서류';
        case 1:
          return '파충류';
        case 2:
          return '포유류';
      }
    }

    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('동물 추가'),
      ),


      //     ↱머테리얼 디자인은 제일 상위에 SafeArea를 함...
      child: SafeArea(
        child: Container(
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Padding(
                  padding: EdgeInsets.all(0),
                  child: CupertinoTextField(
                    controller: _textController,
                    keyboardType: TextInputType.text,
                    maxLines: 1,
                  ),
                ),

                CupertinoSegmentedControl(
                  padding: EdgeInsets.only(bottom: 20, top: 20),
                  groupValue: _kindChoice,
                  children: segmentWidgets,
                  onValueChanged: (int value){
                    setState(() {
                      _kindChoice = value;
                    });
                  }),

                Row(
                  children: <Widget>[
                    Text('날개 있음?'),
                    CupertinoSwitch(
                      value: _flyExist,
                      onChanged: (value){
                        setState(() {
                          _flyExist = value;
                        });
                      }
                    ),
                  ],
                  mainAxisAlignment: MainAxisAlignment.center,
                ),
                SizedBox(
                  height: 100,
                  child: ListView(
                    // ↱ListView를 가로로 스크롤 가능하게 해줌
                    scrollDirection: Axis.horizontal,
                    children: <Widget>[
                      GestureDetector(
                        child: Container(
                            padding: const EdgeInsets.symmetric(horizontal: 10),
                            color: _imagePath=='repo/images/cow.png'?  Colors.blue : Colors.white,
                            child: Image.asset('repo/images/cow.png', width: 80,)),
                        onTap: (){
                          setState(() {
                            _imagePath = 'repo/images/cow.png';

                          });
                        },
                      ),
                      GestureDetector(
                        child: Container(
                            padding: const EdgeInsets.symmetric(horizontal: 10),
                            color: _imagePath=='repo/images/pig.png'?  Colors.blue : Colors.white,
                            child: Image.asset('repo/images/pig.png', width: 80,)),
                        onTap: (){
                          setState(() {
                            _imagePath = 'repo/images/pig.png';
                          });
                        },
                      ),
                      GestureDetector(
                        child: Container(
                            padding: const EdgeInsets.symmetric(horizontal: 10),
                            color: _imagePath=='repo/images/bee.png'? Colors.blue : Colors.white,
                            child: Image.asset('repo/images/bee.png', width: 80,)),
                        onTap: (){
                          setState(() {
                            _imagePath = 'repo/images/bee.png';
                          });
                        },
                      ),
                      GestureDetector(
                        child: Container(
                            padding: const EdgeInsets.symmetric(horizontal: 10),
                            color: _imagePath=='repo/images/cat.png'? Colors.blue : Colors.white,
                            child: Image.asset('repo/images/cat.png', width: 80,)),
                        onTap: (){
                          setState(() {
                            _imagePath = 'repo/images/cat.png';
                          });
                        },
                      ),
                      GestureDetector(
                        child: Container(
                            padding: const EdgeInsets.symmetric(horizontal: 10),
                            color: _imagePath=='repo/images/dog.png'? Colors.blue : Colors.white,
                            child: Image.asset('repo/images/dog.png', width: 80,)),
                        onTap: (){
                          setState(() {
                            _imagePath = 'repo/images/dog.png';
                          });
                        },
                      ),
                      GestureDetector(
                        child: Container(
                            padding: const EdgeInsets.symmetric(horizontal: 10),
                            color: _imagePath =='repo/images/fox.png'? Colors.blue : Colors.white,
                            child: Image.asset('repo/images/fox.png', width: 80,)),
                        onTap: (){
                          setState(() {
                            _imagePath = 'repo/images/fox.png';
                          });
                        },
                      ),
                      GestureDetector(
                        child: Container(
                            padding: const EdgeInsets.symmetric(horizontal: 10),
                            color: _imagePath=='repo/images/monkey.png'? Colors.blue : Colors.white,
                            child: Image.asset('repo/images/monkey.png', width: 80,)),
                        onTap: (){
                          setState(() {
                            _imagePath = 'repo/images/monkey.png';
                          });
                        },
                      ),
                    ],
                  ),
                ),
                CupertinoButton(
                    child: Text('동물 추가하기'),
                    onPressed: (){
                      widget.animalList.add(Animal(
                          imagePath: _imagePath!,
                          animalName: _textController!.value.text,
                          kind: getKind(_kindChoice),
                          flyExist: _flyExist));
                    }
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

 

 

 

 

main.dart

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


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

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

  static const String _title = 'Widget Example!!';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: MyHomePage2(),
    );
  }
}

 

 

 

listview_example.dart

더보기
import 'package:flutter/material.dart';
import 'package:psw1/animalItem.dart';
import 'package:psw1/sub/firstPage.dart';
import 'package:psw1/sub/secondPage.dart';


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

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


//                                                       ↱탭 컨트롤러를 이용해 애니메이션 동작 처리를 제공
class _MyHome2PageState extends State<MyHomePage2> with SingleTickerProviderStateMixin{
  // 탭바 컨트롤러 생성하기
  late TabController controller;

  List<Animal> animalList = <Animal>[];


  @override
  void initState(){
    super.initState();
    //                          ↱탭바의 갯수 ↱탭이 이동했을 때 호출되는 콜백 함수를 어디서 처리할지를 지정
    controller = TabController(length: 2, vsync: this);

      animalList.add(Animal(imagePath: 'repo/images/bee.png', animalName: '벌', kind: '곤충'));
      animalList.add(Animal(imagePath: 'repo/images/cat.png', animalName: '고양이', kind: '포유류'));
      animalList.add(Animal(imagePath: 'repo/images/cow.png', animalName: '젖소', kind: '포유류'));
      animalList.add(Animal(imagePath: "repo/images/dog.png", animalName: "강아지", kind: "포유류"));
      animalList.add(Animal(imagePath: "repo/images/fox.png", animalName: "여우", kind: "포유류"));
      animalList.add(Animal(imagePath: "repo/images/monkey.png", animalName: "원숭이", kind: "영장류"));
      animalList.add(Animal(imagePath: "repo/images/pig.png", animalName: "돼지", kind: "포유류"));
      animalList.add(Animal(imagePath: "repo/images/wolf.png", animalName: "늑대", kind: "포유류"));

    // if(animalList.length != 0){
    //
    //   print(animalList.length);
    //   print(animalList.elementAt(0).imagePath);
    //   print(animalList.elementAt(1).imagePath);
    //   print(animalList.elementAt(2).imagePath);
    // }


  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('탭바 예제'),
      ),

      body: TabBarView( // 같은 탭바에 있기에 animalList를 추가, 삭제, 수정이 가능하다.
        children: <Widget>[
          FirstApp(list1: animalList),
          SecondApp(list2: animalList,),
        ],
        controller: controller,
      ),

      bottomNavigationBar: TabBar(tabs: <Tab>[
        Tab(icon: Icon(Icons.looks_one, color: Colors.blue,),),
        Tab(icon: Icon(Icons.looks_two, color: Colors.red),),
      ],
        controller: controller,
      ),
    );
  }
}

 

 

 

firstPage.dart

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

class FirstApp extends StatelessWidget {
  const FirstApp({Key? key, required this.list1}) : super(key: key);

  final List<Animal> list1;


  @override
  Widget build(BuildContext context) {

    return Scaffold(
      body: Container(
        //                                     ↱위젯의 위치 ↱아이템 순번
        child: ListView.builder(itemBuilder: (context, position){
          return GestureDetector(
            child: Card(
              child: Row(
                children: <Widget>[
                  Image.asset(
                    list1[position].imagePath,
                    height: 100,
                    width: 100,
                    fit: BoxFit.contain,
                  ),
                  Text(list1[position].animalName),
                ],
              ),
            ),

            onTap: (){
              AlertDialog dialog = AlertDialog(
                content: Text(
                  '이 동물은 ${list1[position].kind} 입니다.',
                  style: TextStyle(fontSize: 30.0),
                ),
              );
              showDialog(
                context: context,
                builder: (BuildContext context) => dialog);
            },
          );
        }, itemCount: list1.length // 아이템 갯수만큼 스크롤할 수 있게 제한
        ),

      ),
    );
  }
}

 

 

 

secondPage.dart

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

// ignore: must_be_immutable
class SecondApp extends StatefulWidget {
  final List<Animal> list2;

  const SecondApp({Key? key, required this.list2}) : super(key: key);

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

class _SecondAppState extends State<SecondApp> {

  // 텍스트 필드 사용할 컨트롤러 생성
  final nameController = TextEditingController();

  // 라디오 버튼을 이용하여 동물 종류 선택
  int _radioValue = 0;

  // 동물이 날수 있는지 선택
  bool flyExist = false;

  // 이미지 사진 경로
  var _imagePath;


  @override
  Widget build(BuildContext context) {

    // 라디오 버튼 클릭시 선택된 라디오버튼의 인덱스값으로 변경
    _radioChange(int? value){
      setState(() {
        _radioValue =value!;
      });
    }
    print(_radioValue);

    dynamic getKind(int radioValue){
      switch (radioValue){
        case 0:
          return '양서류';
        case 1:
          return '파충류';
        case 2:
          return '포유류';
      }
    }

    print('--> $_imagePath');

    return Scaffold(
      body: Container(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              TextField(
                controller: nameController,
                keyboardType: TextInputType.text,
                maxLines: 1,
              ),

              // 라디오 버튼 만들기
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: <Widget>[
                  //    ↱ 인덱스값,  ↱라디오 그룹의 선택값
                  Radio(value: 0, groupValue: _radioValue, onChanged: _radioChange),
                  Text('양서류'),

                  Radio(value: 1, groupValue: _radioValue, onChanged: _radioChange),
                  Text('파충류'),

                  Radio(value: 2, groupValue: _radioValue, onChanged: _radioChange),
                  Text('포유류'),
                ],
              ),

              // 체크박스 만들기
              Row(
                // 양쪽 여백사이를 균일하게 배치하기
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: <Widget>[
                  Text('날 수 있나요?'),
                  Checkbox(
                    value: flyExist,
                    onChanged: (check){
                        setState(() {
                          flyExist = check!;
                        });
                    }
                  ),
                ],
              ),

              // 동물이미지 선택하기
              Container(
                height: 100,
                child: ListView(
                  scrollDirection: Axis.horizontal,
                  children: <Widget>[

                    GestureDetector(
                      child: Container(
                          padding: const EdgeInsets.symmetric(horizontal: 10),
                          color: _imagePath=='repo/images/cow.png'?  Colors.blue : Colors.white,
                          child: Image.asset('repo/images/cow.png', width: 80,)),
                      onTap: (){
                        setState(() {
                          _imagePath = 'repo/images/cow.png';

                        });
                      },
                    ),
                    GestureDetector(
                      child: Container(
                          padding: const EdgeInsets.symmetric(horizontal: 10),
                          color: _imagePath=='repo/images/pig.png'?  Colors.blue : Colors.white,
                          child: Image.asset('repo/images/pig.png', width: 80,)),
                      onTap: (){
                        setState(() {
                          _imagePath = 'repo/images/pig.png';
                        });
                      },
                    ),
                    GestureDetector(
                      child: Container(
                          padding: const EdgeInsets.symmetric(horizontal: 10),
                          color: _imagePath=='repo/images/bee.png'? Colors.blue : Colors.white,
                          child: Image.asset('repo/images/bee.png', width: 80,)),
                      onTap: (){
                        setState(() {
                          _imagePath = 'repo/images/bee.png';
                        });
                      },
                    ),
                    GestureDetector(
                      child: Container(
                          padding: const EdgeInsets.symmetric(horizontal: 10),
                          color: _imagePath=='repo/images/cat.png'? Colors.blue : Colors.white,
                          child: Image.asset('repo/images/cat.png', width: 80,)),
                      onTap: (){
                        setState(() {
                          _imagePath = 'repo/images/cat.png';
                        });
                      },
                    ),
                    GestureDetector(
                      child: Container(
                          padding: const EdgeInsets.symmetric(horizontal: 10),
                          color: _imagePath=='repo/images/dog.png'? Colors.blue : Colors.white,
                          child: Image.asset('repo/images/dog.png', width: 80,)),
                      onTap: (){
                        setState(() {
                          _imagePath = 'repo/images/dog.png';
                        });
                      },
                    ),
                    GestureDetector(
                      child: Container(
                          padding: const EdgeInsets.symmetric(horizontal: 10),
                          color: _imagePath =='repo/images/fox.png'? Colors.blue : Colors.white,
                          child: Image.asset('repo/images/fox.png', width: 80,)),
                      onTap: (){
                        setState(() {
                          _imagePath = 'repo/images/fox.png';
                        });
                      },
                    ),
                    GestureDetector(
                      child: Container(
                          padding: const EdgeInsets.symmetric(horizontal: 10),
                          color: _imagePath=='repo/images/monkey.png'? Colors.blue : Colors.white,
                          child: Image.asset('repo/images/monkey.png', width: 80,)),
                      onTap: (){
                        setState(() {
                          _imagePath = 'repo/images/monkey.png';
                        });
                      },
                    ),
                  ],
                ),
              ),


              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  // ignore: deprecated_member_use
                  RaisedButton(
                    child: Text('동물 추가하기'),
                    onPressed: (){
                      var animal = Animal(
                          imagePath: _imagePath,
                          animalName: nameController.value.text,
                          kind: getKind(_radioValue),
                          flyExist: flyExist);
                      AlertDialog dialog = AlertDialog(
                        title: Text('동물 추가하기'),
                        content: Text(
                          '이 동물은 ${animal.animalName} 입니다.'
                          '또 동물의 종류는 ${animal.kind} 입니다. '
                          '\n이미지 주소는 ${animal.imagePath}입니다. \n이 동물을 추가하시겠습니까?',
                        style: TextStyle(fontSize: 15.0),
                        ),
                        actions: [
                          // ignore: deprecated_member_use
                          RaisedButton(
                            child: Text('예'),
                            onPressed: (){

                              widget.list2.add(animal);
                              Navigator.of(context).pop();
                            }
                          ),
                          // ignore: deprecated_member_use
                          RaisedButton(
                            child: Text('아니요'),
                            onPressed: (){
                              Navigator.of(context).pop();
                            }
                          ),
                        ],
                      );
                      showDialog(
                        context: context,
                        builder: (BuildContext context)=> dialog);
                    }
                  ),
                  // ignore: deprecated_member_use
                  RaisedButton(
                    child: Text('동물 삭제하기'),
                    onPressed: (){
                      widget.list2.removeAt(widget.list2.length-1);

                    })
                ],
              ),
            ],
          ),
        ),
      ),
    );


  }
}

 

 

animalItem.dart

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

class Animal{
  late String imagePath;
  late String animalName;
  late String kind;
  bool? flyExist = false;

  // 중괄호 후 this.변수명 하면 -> key값으로 파라미터를 넘길 수 있다.
  Animal({required this.imagePath, required this.animalName, required this.kind, this.flyExist});

// Animal(
//       {@required imagePath, @required animalName, @required kind}
//       );

}
import 'package:flutter/material.dart';
import 'package:psw1/sub/firstPage.dart';
import 'package:psw1/sub/secondPage.dart';

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

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

  static const String _title = 'Widget Example!!';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: MyHomePage(),
    );
  }
}


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

  @override
  _MyHomePageState createState() => _MyHomePageState();
}
//                                                       ↱탭 컨트롤러를 이용해 애니메이션 동작 처리를 제공
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
  // 탭바 컨트롤러 생성하기
  late TabController controller;

  @override
  void initState(){
    super.initState();
    //                          ↱탭바의 갯수 ↱탭이 이동했을 때 호출되는 콜백 함수를 어디서 처리할지를 지정
    controller = TabController(length: 2, vsync: this);

    // 탭컨트롤러 활용하기 addListener()함수는 탭이 이동할 때 호출 됨
    controller.addListener(() {
      //               ↱ 탭이 현재 이동중인지 나타냄 
      if(!controller.indexIsChanging){
        print('이전 index-> ${controller.previousIndex}');
        print('현재 index-> ${controller.index}');
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('탭바 예제'),
      ),

      body: TabBarView(
        children: <Widget>[
          FirstApp(),
          SecondApp(),
        ],
        controller: controller,
      ),

      bottomNavigationBar: TabBar(tabs: <Tab>[
        Tab(icon: Icon(Icons.looks_one, color: Colors.blue,),),
        Tab(icon: Icon(Icons.looks_two, color: Colors.red),),
      ],
        controller: controller,
      ),
    );
  }
}

 

 

 

플러터가 제공하는 키보드 유형

키보드 유형 설명
text 기본 텍스트
mutiline 멀티라인 텍스트, 메모 같이 여러줄을 입력할 때 사용
number 숫자 키보드 표시
phone 전화번호 전용
datetime 날짜 입력
emailAddress @표시 등 이메일 입력
url 주소입력창

 

 


덧셈 계산기 만들기

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  
  static const String _title = 'Widget Example!!';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: WidgetsApp(),
    );
  }
}

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

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

class _WidgetsAppState extends State<WidgetsApp> {

  String sum ='';

  // TextField를 다루기 위해 사용
  TextEditingController value1 = TextEditingController();
  TextEditingController value2 = TextEditingController();


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

      body: Container(
        child: Center(
          child: Column(
            children: <Widget>[
              Padding(
                padding: EdgeInsets.all(15),
                child: Text('flutter!!'),
              ),

              Padding(
                padding: EdgeInsets.all(15),
                child: Text(
                  '결과 : $sum',
                  style: TextStyle(fontSize: 20),
                ),
              ),

              Padding(
                padding: EdgeInsets.only(left:20, right:20),
                //                                ↱숫자 입력용 키보드   ↱ 컨트롤러 연결(입력값을 value1에 넣음)
                child: TextField(keyboardType: TextInputType.number, controller: value1,), // 사용자로부터 입력받을 거임
              ),

              Padding(
                padding: EdgeInsets.only(left: 20, right: 20),
                child: TextField(keyboardType: TextInputType.number, controller: value2,),
              ),
              // ignore: deprecated_member_use
              Padding(
                padding: const EdgeInsets.all(15),
                // ignore: deprecated_member_use
                child: RaisedButton(
                  child: Row(
                    children: <Widget>[
                      Icon(Icons.add),
                      Text('더하기'),
                    ],
                  ),
                  color: Colors.amber,
                  onPressed: (){
                    setState(() {
                      int result = int.parse(value1.value.text) + int.parse(value2.value.text);
                      sum = '$result';
                    });
                }),
              )
            ],
          ),
        ),
      ),
    );
  }
}

 


뺄셈, 곱셈, 나눗셈기능 추가

DropDown버튼 만들기

더하기, 빼기, 곱하기, 나눗셈 코드추가

 

전체코드⬇︎ 

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  
  static const String _title = 'Widget Example!!';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: _title,
      home: WidgetsApp(),
    );
  }
}

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

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

class _WidgetsAppState extends State<WidgetsApp> {

  String sum ='';

  List _buttonList = ['더하기', '빼기', '곱하기', '나누기'];
  List<DropdownMenuItem<String>> _dropDownMenuItems = [];
  String? _buttonText;

  // TextField를 다루기 위해 사용
  TextEditingController value1 = TextEditingController();
  TextEditingController value2 = TextEditingController();

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

    for(var item in _buttonList){
      _dropDownMenuItems.add(DropdownMenuItem(value:item, child:Text(item)));
    }
    _buttonText = _dropDownMenuItems[0].value;
  }


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

      body: Container(
        child: Center(
          child: Column(
            children: <Widget>[
              Padding(
                padding: EdgeInsets.all(15),
                child: Text('flutter!!'),
              ),

              Padding(
                padding: EdgeInsets.all(15),
                child: Text(
                  '결과 : $sum',
                  style: TextStyle(fontSize: 20),
                ),
              ),

              Padding(
                padding: EdgeInsets.only(left:20, right:20),
                //                                ↱숫자 입력용 키보드   ↱ 컨트롤러 연결(입력값을 value1에 넣음)
                child: TextField(keyboardType: TextInputType.number, controller: value1,), // 사용자로부터 입력받을 거임
              ),

              Padding(
                padding: EdgeInsets.only(left: 20, right: 20),
                child: TextField(keyboardType: TextInputType.number, controller: value2,),
              ),
              // ignore: deprecated_member_use
              Padding(
                padding: const EdgeInsets.all(15),
                // ignore: deprecated_member_use
                child: RaisedButton(
                  child: Row(
                    children: <Widget>[
                      Icon(Icons.add),
                      Text(_buttonText!),
                    ],
                  ),
                  color: Colors.amber,
                  onPressed: (){
                    setState(() {
                      var value1Int = double.parse(value1.value.text);
                      var value2Int = double.parse(value2.value.text);
                      var result;

                      if (_buttonText=='더하기'){
                        result = value1Int + value2Int;
                      }else if(_buttonText=='빼기'){
                        result = value1Int - value2Int;
                      }else if (_buttonText == '곱하기'){
                        result = value1Int * value2Int;
                      } else{
                        result = value1Int / value2Int;
                      }

                      sum = '$result';
                    });
                }),
              ),

              Padding(
                padding: EdgeInsets.all(15),
                child: DropdownButton(
                  // ↱드랍버튼 클릭시 보여질 내용들
                  items: _dropDownMenuItems,
                  onChanged: (value){
                    setState(() {
                      _buttonText = value as String?;
                    });
                  },
                  // 드랍다운 버튼에서 첫메뉴 or 선택된 메뉴를 보여줌
                  value: _buttonText,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

 

 

+ Recent posts