๐ŸŒžโญ๐ŸŒœ๐ŸŒˆ
๋‰ด์ฐจํŠธ
๐ŸŒžโญ๐ŸŒœ๐ŸŒˆ
  • ๋ถ„๋ฅ˜ ์ „์ฒด๋ณด๊ธฐ
    • Flutter
    • Android
    • Algorithm
      • Python
    • Test
    • Python
    • ์ƒ์‚ฐ์„ฑ
    • ๊ฒฝ์ œ
    • ์˜์–ด
    • ์ƒํ™œ ํŒ

๋ธ”๋กœ๊ทธ ๋ฉ”๋‰ด

  • ํ™ˆ
  • ํƒœ๊ทธ
  • ๋ฐฉ๋ช…๋ก

๊ณต์ง€์‚ฌํ•ญ

ํƒœ๊ทธ

  • Flutter ๊ณผ๊ฑฐ
  • ๊ฐ“์ƒ
  • ์ฐฝ๋ถ€์บ 
  • PYTHON
  • null safety
  • ๋ผ์ดํ”„ํ•ดํ‚น์Šค์ฟจ
  • AssetThumb
  • Android
  • python ๋‚ด์žฅํ•จ์ˆ˜
  • Python ๋‚ด์žฅ ํ•จ์ˆ˜
  • ์ฐฝ์—…๋ถ€ํŠธ์บ ํ”„
  • Firebase
  • Flutter ๊ธฐ์ดˆ ์‹œ๋ฆฌ์ฆˆ
  • flutter 2.0
  • Flutter ์˜ ์—ญ์‚ฌ
  • ๋„ค์ด๋น„ ์”ฐ ์ผ์ฐ ์ž๋Š” ๋ฒ•
  • enum
  • ํŒŒ์ด์ฌ
  • flutter
  • Flutter ํ˜„์žฌ
  • getx
  • Flutter ๋ฏธ๋ž˜
  • Flutter Web
  • flutter webview
  • Image.memory
  • ์ผ์ฐ ์ž๋Š” ๋ฒ•
  • cruscal
  • Flutter pattern
  • ํŠน์ง•
  • bloc

์ตœ๊ทผ ๋Œ“๊ธ€

ํ‹ฐ์Šคํ† ๋ฆฌ

hELLO ยท Designed By ์ •์ƒ์šฐ.
๐ŸŒžโญ๐ŸŒœ๐ŸŒˆ

๋‰ด์ฐจํŠธ

Flutter Web 1ํƒ„ : ๊ตฌ๊ธ€ ์ฝ”๋“œ๋žฉ ๊ตฌํ˜„
Flutter

Flutter Web 1ํƒ„ : ๊ตฌ๊ธ€ ์ฝ”๋“œ๋žฉ ๊ตฌํ˜„

2021. 7. 20. 22:32

 

Flutter 2.0 ์ด ์ถœ์‹œ๋จ์— ๋”ฐ๋ผ.

Web ๊ฐœ๋ฐœ ๋˜ํ•œ ์ •์‹์œผ๋กœ ๊ฐ€๋Šฅํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

์˜ค๋Š˜์€ Flutter ๋กœ Web ๊ฐœ๋ฐœ์„ ์–ด๋–ป๊ฒŒ ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋ฒˆ ๊ธ€์€ ์•„๋ž˜์˜ ์ž๋ฃŒ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž‘์„ฑ๋์Šต๋‹ˆ๋‹ค.

 

  1. Write your first Flutter app on the web

 

์ด ๊ธ€์—์„œ ์•Œ์•„๋ณผ ๋‚ด์šฉ

  1. ๊ฐ„๋‹จํ•œ ์‹คํ–‰
  2. ์ฝ”๋“œ๋žฉ ๊ฐœ์š”
  3. ์ฝ”๋“œ๋žฉ ๊ตฌํ˜„
  4. ๊ตฌํ˜„ ์ค‘ ๋А๋‚€ ์ 

 

๊ฐ„๋‹จํ•œ ์‹คํ–‰

๋“ค์–ด๊ฐ€๊ธฐ ์•ž์„œ Web์œผ๋กœ ํ•œ๋ฒˆ ์‹คํ–‰์‹œ์ผœ ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ž‘๋™ ์ฝ”๋“œ๋Š” ์ƒˆ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ์‹œ ์žˆ๋Š” ์นด์šดํŠธ ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค.

 

 

๊ฐ„๋‹จํžˆ ์‹คํ–‰์‹œ์ผœ๋ณด๋‹ˆ ์•ฑ๊ฐœ๋ฐœ๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅธ๊ฒŒ ์—†๋Š” ๋А๋‚Œ์ž…๋‹ˆ๋‹ค.

๋ฌผ๋ก  UI ๋ฐฐ์น˜๋Š” Web ํ™”๋ฉด์— ๋งž๊ฒŒ ์ˆ˜์ •ํ•ด์•ผ๊ฒ ์ง€๋งŒ.

๊ทธ ์™ธ์—๋Š” ๊ทธ๋ƒฅ ์•ฑ๊ฐœ๋ฐœ๊ณผ ๋˜‘๊ฐ™์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

์ฝ”๋“œ๋žฉ ๊ฐœ์š”

ํ•ด๋‹น ์ฝ”๋“œ๋žฉ์€ ์ •๋ง ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

ํšŒ์›๊ฐ€์ž…์„ ํ•˜๊ณ  ์™„๋ฃŒ์‹œ์—๋Š” Welcome ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

ํŠน๋ณ„ํ•œ ์ ์ด๋ผ๊ณ  ํ•œ๋‹ค๋ฉด ํšŒ์›๊ฐ€์ž… ์‹œ์˜ ProgressBar์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ตฌํ˜„ ์ •๋„์ž…๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ๊ทธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ •๋„๊ฐ€ ์–ด๋ ต์ง€ ์•Š์•„์„œ ๊ฑฑ์ •ํ•˜์‹ค ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.

๋” ์ž์„ธํ•œ ๋‚ด์šฉ์„ ํ™•์ธํ•˜๊ณ  ์‹ถ์œผ์‹œ๋ฉด ์•„๋ž˜์˜ ๋งํฌ๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”.

 

Write your first Flutter app on the web

 

์ฝ”๋“œ๋žฉ ๊ตฌํ˜„

์ด๋ฒˆ ์ฝ”๋“œ๋žฉ์—๋Š” Null Safety๊ฐ€ ์ ์šฉ๋์Šต๋‹ˆ๋‹ค.

pubspec.yaml ์—์„œ sdk๋ฅผ 2.12.0 ์ด์ƒ์œผ๋กœ ์„ค์ •ํ•ด์ฃผ์„ธ์š”.

 

์ด๋ฒˆ ๊ตฌํ˜„์€ ์ •๋ง ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์ฐจํ•œ ์„ค๋ช…๋ณด๋‹ค๋Š” ์ •๋ฆฌ๋œ ์ „์ฒด ์ฝ”๋“œ๊ฐ€ ๋” ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. 

์ฝ”๋“œ์™€ ๊ตฌํ˜„๋œ ํ™”๋ฉด์„ ๊ณต์œ ๋“œ๋ฆฌ๋Š” ๊ฒƒ์œผ๋กœ ์„ค๋ช…์„ ๋Œ€์ฒดํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ ๋ฐ”๋กœ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

1. ์ฝ”๋“œ

import 'package:flutter/material.dart';

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

class SignUpApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      routes: {
        '/': (context) => SignUpScreen(),
        '/welcome': (context) => WelcomeScreen(),
      },
    );
  }
}

class SignUpScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[200],
      body: Center(
        child: SizedBox(
          width: 400,
          child: Card(
            child: SignUpForm(),
          ),
        ),
      ),
    );
  }
}

class WelcomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('Welcome!', style: Theme.of(context).textTheme.headline2),
      ),
    );
  }
}

class SignUpForm extends StatefulWidget {
  @override
  _SignUpFormState createState() => _SignUpFormState();
}

class _SignUpFormState extends State<SignUpForm> {
  final _firstNameTextController = TextEditingController();
  final _lastNameTextController = TextEditingController();
  final _usernameTextController = TextEditingController();

  double _formProgress = 0;

  void _updateFormProgress() {
    var progress = 0.0;
    final controllers = [
      _firstNameTextController,
      _lastNameTextController,
      _usernameTextController
    ];

    for (final controller in controllers) {
      if (controller.value.text.isNotEmpty) {
        progress += 1 / controllers.length;
      }
    }

    setState(() {
      _formProgress = progress;
    });
  }

  void _showWelcomeScreen() {
    Navigator.of(context).pushNamed('/welcome');
  }

  @override
  Widget build(BuildContext context) {
    return Form(
      onChanged: _updateFormProgress,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          AnimatedProgressIndicator(value: _formProgress),
          Text('Sign up', style: Theme.of(context).textTheme.headline4),
          Padding(
            padding: EdgeInsets.all(8.0),
            child: TextFormField(
              controller: _firstNameTextController,
              decoration: InputDecoration(hintText: 'First name'),
            ),
          ),
          Padding(
            padding: EdgeInsets.all(8.0),
            child: TextFormField(
              controller: _lastNameTextController,
              decoration: InputDecoration(hintText: 'Last name'),
            ),
          ),
          Padding(
            padding: EdgeInsets.all(8.0),
            child: TextFormField(
              controller: _usernameTextController,
              decoration: InputDecoration(hintText: 'Username'),
            ),
          ),
          TextButton(
            style: ButtonStyle(
              foregroundColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
                return states.contains(MaterialState.disabled) ? null : Colors.white;
              }),
              backgroundColor: MaterialStateProperty.resolveWith((Set<MaterialState> states) {
                return states.contains(MaterialState.disabled) ? null : Colors.blue;
              }),
            ),
            onPressed: _formProgress == 1 ? _showWelcomeScreen : null,
            child: Text('Sign up'),
          ),
        ],
      ),
    );
  }
}

class AnimatedProgressIndicator extends StatefulWidget {
  final double value;

  AnimatedProgressIndicator({
    required this.value,
  });

  @override
  State<StatefulWidget> createState() {
    return _AnimatedProgressIndicatorState();
  }
}

class _AnimatedProgressIndicatorState extends State<AnimatedProgressIndicator>
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<Color?> _colorAnimation;
  late Animation<double> _curveAnimation;

  void initState() {
    super.initState();
    _controller = AnimationController(
        duration: Duration(milliseconds: 1200), vsync: this);

    final colorTween = TweenSequence([
      TweenSequenceItem(
        tween: ColorTween(begin: Colors.red, end: Colors.orange),
        weight: 1,
      ),
      TweenSequenceItem(
        tween: ColorTween(begin: Colors.orange, end: Colors.yellow),
        weight: 1,
      ),
      TweenSequenceItem(
        tween: ColorTween(begin: Colors.yellow, end: Colors.green),
        weight: 1,
      ),
    ]);

    _colorAnimation = _controller.drive(colorTween);
    _curveAnimation = _controller.drive(CurveTween(curve: Curves.easeIn));
  }

  void didUpdateWidget(oldWidget) {
    super.didUpdateWidget(oldWidget);
    _controller.animateTo(widget.value);
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller,
      builder: (context, child) => LinearProgressIndicator(
        value: _curveAnimation.value,
        valueColor: _colorAnimation,
        backgroundColor: _colorAnimation.value?.withOpacity(0.4),
      ),
    );
  }
}

 

2. ํ™”๋ฉด

 

๊ตฌํ˜„ ์ค‘ ๋А๋‚€ ์ 

์ •๋ง ๊ฐ„๋‹จํ•œ ๊ตฌํ˜„์ด๊ธด ํ•˜์˜€์ง€๋งŒ.

Flutter Web์˜ ๋งค๋ ฅ์„ ๋А๋‚€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ธฐ์กด์— Flutter๋กœ ์•ฑ๊ฐœ๋ฐœ์„ ํ•ด๋ณธ ์‚ฌ๋žŒ์ด๋ผ๋ฉด ์ง„์ž…์žฅ๋ฒฝ์ด ์ƒ๋‹นํžˆ ๋‚ฎ์Šต๋‹ˆ๋‹ค.

์ฆ‰ ๋ณ„๋‹ค๋ฅธ ํ•™์Šต์— ๊ณต์„ ๋“ค์ด์ง€ ์•Š์•„๋„ ์›น๊ฐœ๋ฐœ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํผํฌ๋จผ์Šค์— ๊ด€ํ•ด์„œ๋Š” ์•„์ง ์ž˜๋ชจ๋ฅด๋‚˜.

ํ˜„์žฌ Flutter๊ฐ€ IOS, Android ํ™˜๊ฒฝ์—์„œ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ๋Š” ํผํฌ๋จผ์Šค๋ฅผ ๋ณด๋ฉด.

์ถฉ๋ถ„ํžˆ ์‚ฌ์šฉํ•ด๋ณผ๋งŒํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์— Desktop๊นŒ์ง€ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ.

์ž˜๋งŒ ๊ตฌ์„ฑํ•œ๋‹ค๋ฉด ํ•˜๋‚˜์˜ ์ฝ”๋“œ๋กœ Mobile, Web, Desktop ์„ ์ง€์›ํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ.

๋ง‰์—ฐํ•œ ๊ธฐ๋Œ€๋ฅผ ํ•ด๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

๋งˆ์น˜๋ฉด์„œ

์ด๋ฒˆ ๊ตฌํ˜„์€ ๋„ˆ๋ฌด ๊ฐ„๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ๋ฒˆ์—๋Š” ์ข€ ๋” ์‹ฌํ™”๋œ ๊ตฌํ˜„์„ ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ์— ๋”ฐ๋ผ ์ •๋ง ์‹ค์ œ ์„œ๋น„์Šค์— ์‚ฌ์šฉํ• ๋งŒํ•œ์ง€ ํŒŒ์•…ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ธด ๊ธ€ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

 

์งˆ๋ฌธ์€ ์–ธ์ œ๋‚˜ ํ™˜์˜์ž…๋‹ˆ๋‹ค :)

'Flutter' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Flutter BLoC ๊ฟ€ํŒ - 1ํƒ„ : BlocProvider ๋ฐฑ๋ฐฐ ์‚ฌ์šฉํ•˜๊ธฐ  (0) 2022.01.21
Flutter ๊ธฐ์ดˆ - 1ํƒ„ : Flutter ์˜ ๊ณผ๊ฑฐ, ํ˜„์žฌ, ๋ฏธ๋ž˜  (0) 2021.12.17
Flutter Null Safety๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ   (0) 2021.07.02
Flutter์—์„œ Webview(์›น๋ทฐ) ์‚ฌ์šฉํ•˜๊ธฐ  (0) 2021.07.01
Flutter / multi_image_picker Asset์„ Image๋กœ ๋ณด์ด๊ฒŒ ํ•˜๊ธฐ  (0) 2021.02.19
    'Flutter' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€
    • Flutter BLoC ๊ฟ€ํŒ - 1ํƒ„ : BlocProvider ๋ฐฑ๋ฐฐ ์‚ฌ์šฉํ•˜๊ธฐ
    • Flutter ๊ธฐ์ดˆ - 1ํƒ„ : Flutter ์˜ ๊ณผ๊ฑฐ, ํ˜„์žฌ, ๋ฏธ๋ž˜
    • Flutter Null Safety๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ 
    • Flutter์—์„œ Webview(์›น๋ทฐ) ์‚ฌ์šฉํ•˜๊ธฐ
    ๐ŸŒžโญ๐ŸŒœ๐ŸŒˆ
    ๐ŸŒžโญ๐ŸŒœ๐ŸŒˆ

    ํ‹ฐ์Šคํ† ๋ฆฌํˆด๋ฐ”