'Flutter 앱'에 해당되는 글 90건

728x90

https://console.firebase.google.com/

 

로그인 - Google 계정

하나의 계정으로 모든 Google 서비스를 Google 계정으로 로그인

accounts.google.com

사이트에서 Firebase 프로젝트를 등록하는 방법을 순서대로 적었다.

 

 

 

 

 

 

SHA-1 키를 알아내는 과정이다.

https://developers.google.com/android/guides/client-auth 에서 설명된 방법으로 하면 된다.

 

 

파일을 받아서 2번 다음에 나오는 사항을 따라서 적용한다.

 

Project build.gradle 수정사항

buildscript {
    ext.kotlin_version = '1.6.10'
    repositories {
        google()
        mavenCentral()
    }
 
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.0'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.google.gms:google-services:4.3.10'
    }
}
 

 

앱 build.gradle 수정사항

android {
    compileSdkVersion flutter.compileSdkVersion
 
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
 
    kotlinOptions {
        jvmTarget = '1.8'
    }
 
    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }
 
    defaultConfig {
        // TODO: Specify your own unique Application ID
        applicationId "com.link2me.flutter.firebase"
        minSdkVersion flutter.minSdkVersion
        targetSdkVersion flutter.targetSdkVersion
   multiDexEnabled true
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }
 
    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            signingConfig signingConfigs.debug
        }
    }
}
 
flutter {
    source '../..'
}
 
dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation platform('com.google.firebase:firebase-bom:29.0.3')
    implementation 'com.google.firebase:firebase-analytics-ktx'
}
 
apply plugin: 'com.google.gms.google-services'
 

 

구글 인증 사용 방법

 

 

 

 

 

 

'Flutter 앱 > 환경설정' 카테고리의 다른 글

Flutter Upgrade  (0) 2022.06.17
dart-sdk 설치  (0) 2022.01.11
Target of URI doesn't exist 'package:flutter/material.dart'  (0) 2022.01.11
Flutter 시운전  (0) 2021.12.22
Flutter 설치  (0) 2021.12.20
블로그 이미지

Link2Me

,
728x90

플러터 ListView 에 표시할 데이터를 가져올 사이트는 https://jsonplaceholder.typicode.com/posts 이다.

 

 

http 통신을 위한 설정

http 패키지를 사용하면 인터넷으로부터 데이터를 손쉽게 가져올 수 있다.

http패키지를 설치하기 위해서, pubspec.yaml의 의존성(dependencies) 부분에 추가해줘야 한다.

 

 

dependencies 에 http, http_parser 를 위와 같이 추가하고

 

 

 

최신버전에 대한 정보는 https://pub.dev/packages/http/versions 에서 확인한다.

 

최신버전으로 하지 않아서 에러가 발생해서 환경 설정 부분을 수정했다.

 

 

https://www.youtube.com/watch?v=EwHMSxSWIvQ 동영상 자료를 참고해서 데이터 가져오기를 그대로 해보려고 했는데 url 사이트가 연결이 되지 않아서 URL 이 실제 동작하는 것으로 변경했다.

 

http.get() 메소드는 Response를 포함하고 있는 Future를 반환한다.

Future는 비동기 연산에 사용되는 Dart의 핵심 클래스이다.

 

예제 코드

import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
 
class ListView_remoteJSON extends StatefulWidget {
  const ListView_remoteJSON({Key? key}) : super(key: key);
 
  @override
  _ListView_remoteJSONState createState() => _ListView_remoteJSONState();
}
 
class _ListView_remoteJSONState extends State<ListView_remoteJSON> {
  Future<List<PostData>> _getPost() async {
    // http 0.12.2 로 하면 에러가 발생하지 않고 http 0.13.4 로 하면 에러 발생
    final response =
        await http.get("https://jsonplaceholder.typicode.com/posts");
    if (response.statusCode == 200) {
      var jsonData = json.decode(response.body);
      List<PostData> postDatas = [];
 
      for (var item in jsonData) {
        PostData postData =
            PostData(item['userId'], item['id'], item['title'], item['body']);
        postDatas.add(postData);
      }
      //print("데이터 개수 : ${postDatas.length}");
      return postDatas;
    } else {
      throw Exception('Failed to load postData');
    }
  }
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('ListView_Demo with JSON')),
      body: Container(
        child: FutureBuilder(
          future: _getPost(),
          builder: (context, AsyncSnapshot snapshot) {
            
            if (snapshot.hasData) {
              return ListView.builder(
                  itemCount: snapshot.data.length,
                  itemBuilder: (context, index) {
                    return Card(
                      child: ListTile(
                        title: Text(snapshot.data[index].title),
                        subtitle: Text(snapshot.data[index].body),
                        onTap: () {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (context) =>
                                      DetailPage(snapshot.data[index])));
                        },
                      ),
                    );
                  });
            } else {
              return Container(
                child: Center(
                  child: Text("Loading..."),
                ),
              );
            }
          },
        ),
      ),
    );
  }
}
 
class DetailPage extends StatelessWidget {
  final PostData postData;
 
  DetailPage(this.postData); // 생성자를 통해서 입력변수 받기
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Detail Page'),
      ),
      body: Container(
        child: Center(
          child: Text(postData.title),
        ),
      ),
    );
  }
}
 
class PostData {
  final int userId;
  final int id;
  final String title;
  final String body;
 
  PostData(this.userId, this.id, this.title, this.body);
}
 

 

블로그 이미지

Link2Me

,

Flutter Layout

Flutter 앱/Layout 2021. 12. 26. 20:02
728x90

일반적으로 플러터의 레이아웃은 그리드 구조로 이뤄지고, 이는 행과 열을 의미한다.

따라서 행 위젯과 열 위젯이 있다. 각 항목에는 하나 이상의 자식이 있을 수 있고, 행 위젯의 경우 가로로 배치하고, 열 위젯은 세로로 배치한다.

 

플러터 Layout 구성에 필요한 위젯은 https://docs.flutter.dev/development/ui/layout 에 잘 설명되어 있다.

한글 설명 일부는 https://flutter-ko.dev/docs/development/ui/layout/tutorial 를 참조한다.

 

 

 

Container 위젯 : 기본적으로 최대한의 공간을 차지하여 표시된다.

Padding 위젯 : 자식 위젯 주위에 padding을 표시

Center 위젯 : 자식 위젯을 중앙에 표시

Column 위젯 : 자식 위젯들을 세로로 정렬하여 표시

Row 위젯 : 자식 위젯들을 가로로 정렬하여 표시

 

예제 소스코드

import 'package:flutter/material.dart';
 
import 'bottom_navi_bar.dart';
import 'myapp_demo.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  // 화면 표시에 대한 역할은 Scaffold 위젯이 담당한다.
  // MaterialApp 위젯은 화면 이동과 테마 지정이 주요 역할이다.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          brightness: Brightness.light,
          appBarTheme: AppBarTheme(
            color: Color.fromARGB(13152215229),
          ),
          primaryColor: Colors.lightBlue,
          accentColor: Colors.greenAccent,
          fontFamily: 'Raleway'),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
      ),
      //home: const BottomNaviBar(title: '플러터 데모 Main'),
      home: MyAppDemo(),
    );
  }
}
 
 

 

import 'package:flutter/material.dart';
 
// Android Studio 에서 stless 탭키(또는 엔터키)를 누르면 자동으로 만들어진다.
// 여기에서 클래스 이름만 지정하면 된다.
class MyAppDemo extends StatelessWidget {
  //const MyAppDemo({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter layout demo"),
      ),
      body: Column(
        children: <Widget>[titleSelection],
      ),
    );
  }
 
  // 컨테이너 위젯 구현
  Widget titleSelection = Container(
    // 컨테이너 내부 상하좌우에 32픽셀만큼의 패딩 삽입
    padding: const EdgeInsets.all(32),
    // 자식으로 row를 추가
    child: Row(
      // 위젯들(Expanded, Icon, Text)을 자식들로 추가
      children: <Widget>[
        // 1 : Expanded widget안에 Column을 넣으면 row의 남은 공간을 모두 채우게 된다.
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start, // 자식들을 왼쪽정렬로 배치함
            // 컬럼의 자식들로 컨테이너와 텍스트를 추가
            children: <Widget>[
              Container(
                padding: const EdgeInsets.only(bottom: 8),
                // 컨테이너 내부 하단에 8픽셀만큼 패딩 삽입
                child: Text(
                  "서울시 종로구",
                  style: TextStyle(fontWeight: FontWeight.bold // 텍스트 강조 설정
                      ),
                ),
              ),
              Text(
                '세종로 100번지',
                style: TextStyle(color: Colors.grey[600// 텍스트의 색상을 설정
                    ),
              )
            ],
          ),
        ),
 
        Icon(
          Icons.star, // 별모양 아이콘 삽입
          color: Colors.red[500], // 빨간색으로 설정
        ),
        Padding(padding: EdgeInsets.all(4)),
        Text(
          '43',
          style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
        ), // 텍스트 표시
      ],
    ),
  );
}
 

 

Expanded 위젯

 

Expanded 위젯은 Column 위젯, Row 위젯과 함께 사용하여 웹 개발에서 사용되는 flex와 같은 기능을 구현할 수 있다.

 

 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter layout demo"),
      ),
      body: Row(
        children: <Widget>[
          Expanded(
            child: Container(
              color: Colors.blue[200],
            ),
            flex: 3,
          ),
          Expanded(
            child: Container(
              color: Colors.grey[100],
            ),
            flex: 7,
          ),
        ],
      ),
    );
  }

 

Stack 위젯

 

Stack 위젯을 사용하면, 위젯 위에 위젯을 표시할 수 있다.

 

 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter layout demo"),
      ),
      body: Container(
        padding: const EdgeInsets.all(10),
        child: Stack(
          children: [
            Container(
              width: 400,
              height: 200,
              color: Colors.green,
            ),
            Container(
              width: 100,
              height: 100,
              color: Colors.deepOrange,
            ),
            Container(
              width: 50,
              height: 50,
              color: Colors.blue,
            ),
          ],
        ),
      ),
    );
  }
 
 

 

SizedBox 위젯

Container 위젯과 SizedBox 위젯은 둘 다 width와 height를 가진다.

Container 위젯은 width와 height를 넣지 않으면, 최대 크기로 확장해준다.

SizedBox 위젯의 height나 width의 default 값은 double.infinity 이다.
그리고, color 속성이 없어서 색상을 지정할 수 없다.

간단하게 height, width 만 설정하는 것이면 SizedBox 위젯을 사용하는 것이 가볍다.

 

SizedBox는 크게 2가지의 용도가 있다.

1) Container, button과 같은 다른 위젯을 child로 두면서 높이와 너비를 고정시키고 싶을때 사용함.

2) Row나 Column과 같은 위젯의 children들 사이에 간격을 두고 싶을때 공백을 두기 위해서 사용함.

 

 

 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter layout demo"),
      ),
      body: SafeArea(
        child: SizedBox(
          width: 200.0,
          height: 150.0,
          child: Card(
            child: Center(child: Text('Hello World!')),
            color: Color.fromRGBO(11518419019),
          ),
        ),
      ),
    );
  }
 

 

 

SizedBox 위젯의 height와 width 값만큼 위젯 사이의 공간을 만들기 위해 사용하는 경우

Sizedbox가 편리한 이유는, column에서 쓸경우 width가, Row에서 쓸경우 height가 고정되므로 나머지 하나만 지정해 두면 된다는 점과, 복잡한 각 children 내부의 padding대신 다른 children으로 두기만 하면 되서 디버깅이 쉽다.

 

 

 

 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter layout demo"),
      ),
      body: SafeArea(
        child: Container(
          padding: EdgeInsets.all(10),
          child: Column(
            children: [
              Container(
                width: 100,
                height: 100,
                color: Colors.redAccent,
              ),
              SizedBox(height: 10),
              Container(
                width: 100,
                height: 100,
                color: Colors.greenAccent,
              )
            ],
          ),
        ),
      ),
    );
  }
 

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter CustomScrollView  (0) 2022.06.21
Flutter Drawer Widget  (0) 2022.06.16
Flutter Theme(테마) 변경  (0) 2021.12.24
Flutter BottomNavigationBar 예제  (0) 2021.12.22
Flutter TabBar  (0) 2021.12.22
블로그 이미지

Link2Me

,
728x90

Flutter 에서 Toast 메시지를 띄우는 걸 하는 방법이다.

 

https://pub.dev/packages/fluttertoast/install 를 보고 순서대로 진행한다.

현재 실행중인 Project 에서 터미널 창을 열어서 flutter pub add fluttertoast 를 입력한다.

아래 파일에 자동으로 추가된 것을 확인할 수 있다.

Pub get 을 눌러준다. Android Native 앱 Sync Now 와 같은 기능으로 보인다.

여기까지 해주고 예제 소스코드로 테스트하는데 동작이 제대로 안된다. 흐미ㅜㅜ

Hot Reload 기능이 제대로 동작되지 않는 거 같더라.

그래서 완전 종료한 후 버튼을 눌렀더니 제대로 동작되는 걸 확인할 수 있었다.

 

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'listview_demo1.dart';
 
class CallsfloatBtn extends StatefulWidget {
  const CallsfloatBtn({Key? key}) : super(key: key);
 
  @override
  _CallsfloatBtnState createState() => _CallsfloatBtnState();
}
 
class _CallsfloatBtnState extends State<CallsfloatBtn> {
  int _counter = 0;
  late FToast fToast;
 
  @override
  void initState() {
    super.initState();
    fToast = FToast();
    fToast.init(context);
  }
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center, // 중앙정렬
          children: <Widget>[
            Text(
              '당신은 버튼을 눌렀어요 :',
              softWrap: false// 텍스트가 영역을 넘어갈 경우 줄바꿈 여부
              style: Theme.of(context).textTheme.headline5,
            ),
            Text(
              '$_counter 번',
              style: TextStyle(fontSize: 25),
            ),
            ElevatedButton(
              child: Text('화면 이동'),
              onPressed: () {
                Navigator.push(context,
                    MaterialPageRoute(builder: (context) => ListView_Demo1()));
              },
              style: ButtonStyle(
                  backgroundColor: MaterialStateProperty.all(Colors.teal),
                  padding: MaterialStateProperty.all(EdgeInsets.all(15)),
                  textStyle:
                      MaterialStateProperty.all(TextStyle(fontSize: 14))),
            ),
            ElevatedButton(
              child: Text("Show Toast"),
              onPressed: () {
                showToast();
              },
            ),
            ElevatedButton(
              child: Text("Show Custom Toast"),
              onPressed: () {
                showCustomToast();
              },
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
 
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
 
  void showToast() {
    Fluttertoast.showToast(
        msg: "기본 토스트 메시지입니다!",
        toastLength: Toast.LENGTH_LONG,
        fontSize: 14,
        backgroundColor: Colors.green
    );
  }
 
  showCustomToast() {
    Widget toast = Container(
      padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(25.0),
        color: Colors.greenAccent,
      ),
      child: Text("This is a Custom Toast"),
    );
 
    fToast.showToast(
      child: toast,
      toastDuration: Duration(seconds: 3),
    );
  }
  
}
 

 

참고자료

https://codesinsider.com/flutter-toast-message-example-tutorial/

 

Flutter Toast Message Example Tutorial – CODES INSIDER

Toast is nothing but a flash message in flutter. Learn how to create & show toast message and custom toast using FlutterToast dependency.

codesinsider.com

OKToast 는 기회되면 나중에 한번 테스트 해보고자 한다.

https://github.com/OpenFlutter/flutter_oktoast

 

GitHub - OpenFlutter/flutter_oktoast: a pure flutter toast library

a pure flutter toast library. Contribute to OpenFlutter/flutter_oktoast development by creating an account on GitHub.

github.com

 

블로그 이미지

Link2Me

,
728x90

플러터에서는 테마 지정이 엄청 쉽다.

Light 테마와 Dark 테마 지정이 코드 몇줄로 쉽게 해결된다.

테마 지정 안된 코드

import 'package:flutter/material.dart';
 
import 'bottom_navi_bar.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
      ),
      home: const BottomNaviBar(title: '플러터 데모 Main'),
    );
  }
}

 

테마 지정한 코드

import 'package:flutter/material.dart';
 
import 'bottom_navi_bar.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  // 화면 표시에 대한 역할은 Scaffold 위젯이 담당한다.
  // MaterialApp 위젯은 화면 이동과 테마 지정이 주요 역할이다.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          brightness: Brightness.light,
          primaryColor: Colors.lightBlue,
          accentColor: Colors.cyan[600],
          fontFamily: 'Raleway'),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
      ),
      home: const BottomNaviBar(title: '플러터 데모 Main'),
    );
  }
}
 
 

 

Custom Color 를 지정하고 싶은 경우에는

https://flutter-color-picker.herokuapp.com/ 에서 색상을 임의로 선택한 다음에 코드를 아래와 같이 변경하면 된다.

primaryColor 의 색에 적용했더니 에러 발생해서, appBarTheme 에 색상 적용 테스트했다.

// 화면 표시에 대한 역할은 Scaffold 위젯이 담당한다.  
// MaterialApp 위젯은 화면 이동과 테마 지정이 주요 역할이다.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          brightness: Brightness.light,
          appBarTheme: AppBarTheme(
            color: Color.fromARGB(13152215229),
          ),
          //primaryColor: Colors.lightBlue,
          fontFamily: 'Raleway'),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
      ),
      home: const BottomNaviBar(title: '플러터 데모 Main'),
    );
  }
 

 

이전 게시글의 ListView_Demo 클래스에도 테마를 적용했다.

 
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
 
// Android Studio 에서 stless 를 입력후 엔터키를 치면
// 자동완성 코드가 작성되고 클래스명을 지정하면 된다.
class ListView_Demo1 extends StatelessWidget {
  const ListView_Demo1({Key? key}) : super(key: key);
 
  // ListView 위젯 정적 데모
  static const List<String> _data = [
    'Mercury(수성)',
    'Venus(금성)',
    'Earth(지구)',
    'Mars(화성)',
    'Jupiter(목성)',
    'Saturn(토성)',
    'Uranus(천왕성)',
    'Neptune(해왕성)',
    'Pluto(명왕성)',
  ];
 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
          brightness: Brightness.light,
          primaryColor: Colors.lightBlue,
          accentColor: Colors.cyan[600],
          fontFamily: 'Raleway'),
      darkTheme: ThemeData(
        brightness: Brightness.dark,
      ),
      home: Scaffold(
        appBar: CupertinoNavigationBar(
          leading: CupertinoNavigationBarBackButton(
            onPressed: () => Navigator.of(context).pop(),
          ),
          middle: Text('쿠퍼티노 UI'),
          trailing: GestureDetector(
            child: Icon(CupertinoIcons.search),
            onTap: (){},
          ),
          backgroundColor: CupertinoColors.activeGreen,
          border: Border(
              bottom:BorderSide(
                  width: 1,
                  color: CupertinoColors.activeGreen,
                  style: BorderStyle.solid
              )
          ),
        ),
        //body: _buildStaticListView(),
        body: _buildStaticListViewSeperated(),
      ),
    );
  }
 
  Widget _buildStaticListView() {
    return ListView.builder(
      itemCount: _data.length,
      itemBuilder: (BuildContext _context, int i) {
        return ListTile(
          title: Text(_data[i],
              style: TextStyle(
                fontSize: 23,
              )),
          trailing: Icon(
            Icons.favorite_border,
          ),
        );
      },
    );
  }
 
  Widget _buildStaticListViewSeperated() {
    return ListView.separated(
      itemCount: _data.length,
      itemBuilder: (BuildContext _context, int i) {
        return ListTile(
          title: Text(_data[i],
              style: TextStyle(
                fontSize: 23,
              )),
          trailing: Icon(
            Icons.favorite_border,
          ),
        );
      },
      separatorBuilder: (BuildContext _context, int i) {
        return const Divider();
      },
    );
  }
}
 

 

UI 에 대한 사항을 좀더 알아보고 싶다면....

https://github.com/lohanidamodar/flutter_ui_challenges 에 있는 자료를 활용한다.

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter CustomScrollView  (0) 2022.06.21
Flutter Drawer Widget  (0) 2022.06.16
Flutter Layout  (0) 2021.12.26
Flutter BottomNavigationBar 예제  (0) 2021.12.22
Flutter TabBar  (0) 2021.12.22
블로그 이미지

Link2Me

,
728x90

Flutter에서 screen 과 page 는 route 로 불린다.
Route는 Android의 Activity, iOS의 ViewController와 동일하다. 
Flutter에서는 Route 역시 위젯이다.

새로운 route로 이동은 Navigator를 사용한다.
Navigator.push()를 사용하여 두 번째 route로 전환한다.
Navigator.pop()을 사용하여 첫 번째 route로 되돌아 온다.

 

import 'package:link2me/route.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);
 
  @override
  State<MyApp> createState() => _MyAppState();
}
 
class _MyAppState extends State<MyApp> {
 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: FirstRoute(),
    );
  }
}

 

 

import 'package:flutter/material.dart';
 
class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Open route'),
          onPressed: () {
            // 눌렀을 때 두 번째 route로 이동
            // push() 메서드는 Route를 Navigator에 의해 관리되는 route 스택에 추가
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondRoute()),
            );
          },
        ),
      ),
    );
  }
}
 
class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // pop() 메서드는 route 스택에서 현재 Route를 제거
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}
 

자료 출처 : https://docs.flutter.dev/cookbook/navigation/navigation-basics

 

Navigator.pushNamed()를 통한 화면전환

출처 : https://docs.flutter.dev/cookbook/navigation/named-routes

Route 정의하기
다음으로, MaterialApp 생성자에 initialRoute와 routes 이름의 추가 프로퍼티를 제공하여 route를 정의한다.
initialRoute 프로퍼티는 앱의 시작점을 나타내는 route를 정의하고, 
routes 프로퍼티는 이용가능한 named route와 해당 route로 이동했을 때 빌드될 위젯을 정의한다.

 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/',
      routes: {
        // "/" Route로 이동하면, FirstRoute 위젯을 생성한다.
        '/': (context) => FirstRoute(),
        // "/second" route로 이동하면, SecondRoute 위젯을 생성한다.
        '/second': (context) => SecondRoute(),
      },
      //home: FirstRoute(),
    );
  }

 

import 'package:flutter/material.dart';
 
class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Center(
        child: ElevatedButton(
          child: Text('Open route'),
          onPressed: () {
            // 눌렀을 때 두 번째 route로 이동
            // push() 메서드는 Route를 Navigator에 의해 관리되는 route 스택에 추가
            // Navigator.push(
            //   context,
            //   MaterialPageRoute(builder: (context) => SecondRoute()),
            // );
 
            // Named route를 사용하여 두 번째 화면으로 전환
            Navigator.pushNamed(context, '/second');
          },
        ),
      ),
    );
  }
}
 
class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            // pop() 메서드는 route 스택에서 현재 Route를 제거
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

 

 

 

화면 전환 코드가 포함된 예제이다.

import 'package:flutter/material.dart';
import 'package:myapp/listview_demo1.dart';
 
class CallsfloatBtn extends StatefulWidget {
  const CallsfloatBtn({Key? key}) : super(key: key);
 
  @override
  _CallsfloatBtnState createState() => _CallsfloatBtnState();
}
 
class _CallsfloatBtnState extends State<CallsfloatBtn> {
  int _counter = 0;
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center, // 중앙정렬
          children: <Widget>[
            Text(
              '당신은 버튼을 눌렀어요 :',
              softWrap: false// 텍스트가 영역을 넘어갈 경우 줄바꿈 여부
              style: Theme.of(context).textTheme.headline5,
            ),
            Text(
              '$_counter 번',
              style: TextStyle(fontSize: 25),
            ),
            ElevatedButton(
              child: Text('화면 이동'),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => ListView_Demo1())
                );
              },
              style: ButtonStyle(
                  backgroundColor: MaterialStateProperty.all(Colors.teal),
                  padding: MaterialStateProperty.all(EdgeInsets.all(15)),
                  textStyle: MaterialStateProperty.all(TextStyle(fontSize: 14))),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
 
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
}
 

 

 

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
 
// Android Studio 에서 stless 를 입력후 엔터키를 치면
// 자동완성 코드가 작성되고 클래스명을 지정하면 된다.
class ListView_Demo1 extends StatelessWidget {
  const ListView_Demo1({Key? key}) : super(key: key);
 
  // ListView 위젯 정적 데모
  static const List<String> _data = [
    'Mercury(수성)',
    'Venus(금성)',
    'Earth(지구)',
    'Mars(화성)',
    'Jupiter(목성)',
    'Saturn(토성)',
    'Uranus(천왕성)',
    'Neptune(해왕성)',
    'Pluto(명왕성)',
  ];
 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        appBar: CupertinoNavigationBar(
          leading: CupertinoNavigationBarBackButton(
            onPressed: () => Navigator.of(context).pop(),
          ),
          middle: Text('쿠퍼티노 UI'),
          trailing: GestureDetector(
            child: Icon(CupertinoIcons.search),
            onTap: (){},
          ),
          backgroundColor: CupertinoColors.activeGreen,
          border: Border(
              bottom:BorderSide(
                  width: 1,
                  color: CupertinoColors.activeGreen,
                  style: BorderStyle.solid
              )
          ),
        ),
        //body: _buildStaticListView(),
        body: _buildStaticListViewSeperated(),
      ),
    );
  }
 
  Widget _buildStaticListView() {
    return ListView.builder(
      itemCount: _data.length,
      itemBuilder: (BuildContext _context, int i) {
        return ListTile(
          title: Text(_data[i],
              style: TextStyle(
                fontSize: 23,
              )),
          trailing: Icon(
            Icons.favorite_border,
          ),
        );
      },
    );
  }
 
  Widget _buildStaticListViewSeperated() {
    return ListView.separated(
      itemCount: _data.length,
      itemBuilder: (BuildContext _context, int i) {
        return ListTile(
          title: Text(_data[i],
              style: TextStyle(
                fontSize: 23,
              )),
          trailing: Icon(
            Icons.favorite_border,
          ),
        );
      },
      separatorBuilder: (BuildContext _context, int i) {
        return const Divider();
      },
    );
  }
}
 
블로그 이미지

Link2Me

,
728x90

플러터 BottomNavigationBar 예제를 나중에 활용하는데 도움될 수 있게 작성해본 예제다.

BottomNavigationBar 검색하면 단순한 것이 대부분이라 향후 기능 구현시 활용 목적으로 약간 더 추가했다.

 

import 'package:flutter/material.dart';
 
void main() {
  runApp(MyApp());
}
 
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}
 
class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue,
        brightness: Brightness.light,
      ),
      debugShowCheckedModeBanner: false,
      home: const MyHomePage(title: '플러터 데모 Main'),    );
  }
}
 
// Android Studio 에서 stful 엔터를 치면 자동으로 만들어진다.
// 여기에서 클래스 이름만 지정하면 자동으로 만들어진다.
class MyHomePage extends StatefulWidget {
  final String title; // 선언한 변수는 final을 붙여야 한다.
  const MyHomePage({Key? key, required this.title}) : super(key: key);
 
  @override
  _MyHomePageState createState() => _MyHomePageState();
  // Stateless 위젯과 다른 점은 createState() 메소드를 통해
  // 상태를 담당하는 클래스를 지정할 수 있다.
}
 
// 클래스 이름 앞에 _가 붙어 있으면 private 클래스로 본다.
// 다트에서는 Java와 같이 public, protected, private 같은 접근 제어자 키워드 없음
class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0// _를 붙이면 private
  static const TextStyle optionStyle =
  TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
 
  static const List<Widget> _widgetOptions = <Widget>[
    Text(
      'Index 0: Home',
      style: optionStyle,
    ),
    CallsfloatBtn(), // class 호출
    Text(
      'Index 2: School',
      style: optionStyle,
    ),
  ];
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('BottomNavigationBar Sample'),
      ),
      body: Center(
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex, // 선택된 Index
        backgroundColor: Colors.grey[200], //Bar의 배경색
        selectedItemColor: Colors.amber[800],
        selectedFontSize: 15//선택된 아이템의 폰트사이즈
        unselectedFontSize: 12//선택 안된 아이템의 폰트사이즈
        onTap: _onItemTapped,
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business),
            label: 'Business',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.school),
            label: 'School',
          ),
        ],
      ),
    );
  }
 
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }
}
 
class CallsfloatBtn extends StatefulWidget {
  const CallsfloatBtn({Key? key}) : super(key: key);
 
  @override
  _CallsfloatBtnState createState() => _CallsfloatBtnState();
}
 
class _CallsfloatBtnState extends State<CallsfloatBtn> {
  int _counter = 0;
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center, // 중앙정렬
          children: <Widget>[
            Text(
              '당신은 버튼을 눌렀어요 :',
              softWrap: false// 텍스트가 영역을 넘어갈 경우 줄바꿈 여부
              style: Theme.of(context).textTheme.headline5,
            ),
            Text(
              '$_counter 번',
              style: TextStyle(fontSize: 25),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
 
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
}
 

 

참고자료

https://blog.logrocket.com/how-to-build-a-bottom-navigation-bar-in-flutter/

 

How to build a bottom navigation bar in Flutter - LogRocket Blog

This tutorial demonstrates how to build, integrate, and customize a bottom navigation bar in a Flutter app.

blog.logrocket.com

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter CustomScrollView  (0) 2022.06.21
Flutter Drawer Widget  (0) 2022.06.16
Flutter Layout  (0) 2021.12.26
Flutter Theme(테마) 변경  (0) 2021.12.24
Flutter TabBar  (0) 2021.12.22
블로그 이미지

Link2Me

,

Flutter TabBar

Flutter 앱/Layout 2021. 12. 22. 11:04
728x90

Flutter 설치하면 기본 설치되는 소스코드를 수정하여 탭으로 화면 구성하는 방법 연습하고 적어둔다.

TabController 생성 → TabBar 에 Tab 추가 → TabBarView에 각 Tab에 해당하는 콘텐츠 구성

 

import 'package:flutter/material.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
        primaryColor: const Color(0xfff0c0f1),
        accentColor: const Color(0xfff0c0f1),
        canvasColor: const Color(0xFFfafafa),
      ),
      home: const MyHomePage(title: '플러터 데모 Main'),
    );
  }
}
 
// Android Studio 에서 stful 엔터를 치면 자동으로 만들어진다.
// 여기에서 클래스 이름만 지정하면 자동으로 만들어진다.
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
 
  final String title; // 선언한 변수는 final을 붙여야 한다.
 
  @override
  State<MyHomePage> createState() => _MyHomePageState();
// Stateless 위젯과 다른 점은 createState() 메소드를 통해
// 상태를 담당하는 클래스를 지정할 수 있다.
}
 
// 클래스 이름 앞에 _가 붙어 있으면 private 클래스로 본다.
// 다트에서는 Java와 같이 public, protected, private 같은 접근 제어자 키워드 없음
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0// _를 붙이면 private
 
  @override
  Widget build(BuildContext context) {
    // TabController 위젯으로 감싼다.
    return DefaultTabController(
        initialIndex: 1,
        length: 3// 탭의 수 설정
        child: Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
            // TabBar 구현, 각 content를 호출할 탭들을 등록
            bottom: TabBar(
              tabs: <Widget>[
                Tab(icon: Icon(Icons.directions_car), text: '첫번째'),
                Tab(icon: Icon(Icons.directions_transit), text: "Transit"),
                Tab(
                  icon: Icon(Icons.directions_bike),
                  text: "Bike",
                ),
              ],
            ),
          ),
          body: TabBarView(
            children: [
              Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center, // 중앙정렬
                  children: <Widget>[
                    Text(
                      '당신은 버튼을 눌렀어요 :',
                      softWrap: false// 텍스트가 영역을 넘어갈 경우 줄바꿈 여부
                      style: Theme.of(context).textTheme.headline5,
                    ),
                    Text(
                      '$_counter 번',
                      style: TextStyle(fontSize: 25),
                    ),
                  ],
                ),
              ),
              Center(
                child: Text("It's rainy here"),
              ),
              Icon(Icons.directions_bike),
            ],
          ),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter, // 정의하고 alt + Enter 를 눌러서 메소드 생성
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
        ));
  }
 
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
}
 

 

참고하면 도움될 자료

https://www.woolha.com/tutorials/flutter-using-tabbar-tabbarview-examples

 

Flutter - Using TabBar & TabBarView Examples

A tutorial of how to create tab layout in Flutter using TabBar and TabBarView

www.woolha.com

https://blog.logrocket.com/flutter-tabbar-a-complete-tutorial-with-examples/#customizethetabindicatorintabbar

 

Flutter TabBar: A complete tutorial with examples - LogRocket Blog

TabBar enables you to improve the UX of your Flutter app by organizing content with tabs for users to tap and scroll through.

blog.logrocket.com

 

'Flutter 앱 > Layout' 카테고리의 다른 글

Flutter CustomScrollView  (0) 2022.06.21
Flutter Drawer Widget  (0) 2022.06.16
Flutter Layout  (0) 2021.12.26
Flutter Theme(테마) 변경  (0) 2021.12.24
Flutter BottomNavigationBar 예제  (0) 2021.12.22
블로그 이미지

Link2Me

,
728x90

플러터를 처음 실행하는 과정을 적어둔다.

 

 

7번은 반드시 소문자로 적어야 한다.

앱의 이름은 대소문자를 구분하지 않으니 전부 소문자로 적어야 한다.

소문자 사이에 _를 넣는 스네이크 케이스를 추천한다.

test라는 건 인식을 못하더라. 그래서 myapp 으로 입력했다.

 

 

 

 

Android 폰을 연결하고 컴파일을 했더니 데모 앱이 화면에 나온다.

폴더 구조를 보면....

android 와 ios : 각 플랫폼 전용 폴더로 대개 손댈 필요가 없다.

lib : 플러터 소스코드(.dart 파일) 위치

test : 유닛 테스트가 있으면 여기에 넣는다.

 

pubspec.yaml :  프로젝트 파일로 프로젝트 이름, 설명, 의존성 등을 설정한다.

.metadata 와 .package : 중요한 설정파일로 개발자가 열어볼 필요는 없다.

 

앱을 웹 앱으로 실행하면 플러터는 브라우저를 기기로 간주한다.

 

앱을 에뮬레이터로 실행하는 경우이며, 기기를 종료하고자 하면 빨간색 메모 버튼을 누르면 된다.

코드를 추가하거나 수정하고 저장 버튼을 누르면 에뮬레이터(또는 폰)에서 즉시 변경되어 로드된다. 이 기능을 핫 리로드라고 한다.

 

플러터 세계에서는 컴포넌트를 위젯이라고 한다. 위젯을 합쳐서 커스텀 위젯을 만들고, 커스텀 위젯을 합쳐서 더 복잡한 커스텀 위젯을 만든다. 완전한 앱이 만들어질 때까지 이 과정을 계속해야 한다.

값 위젯(Text 위젯, Image 위젯), Layout 위젯, Navigation 위젯, 기타 위젯 등은 앱의 구성요소다.

모든 위젯은 속성과 메소드를 가질 수 있는 클래스이다.

모든 위젯은 생성자를 가지며, 생성자의 매개변수는 있을 수도 있고 없을 수도 있다.

모든 위젯은 BuildContext 를 인수로 받는 build 메소드가 있다는 점이 중요하다.

 

이것으로 Flutter 기본적인 시작 준비가 된 것 같다.

 

플러터 앱은 main()함수에서 시작한다.

main 함수는 runApp()이라는 함수를 호출한다. runApp()은 위젯 하나를 인수로 받는다. 이 위젯은 루트 위젯으로 어떤 이름을 붙여도 상관없지만 플러터의 StatelessWidget을 상속한 클래스여야 한다.

import 'package:flutter/material.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: '플러터 데모 Main'),
    );
  }
}
 
class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
 
  final String title;
 
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}
 
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
 
  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
 

 

Widget build 부분을 변경해가면서 코딩 연습을 해본다.

 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '당신은 버튼을 눌렀어요 :',
              softWrap: false// 텍스트가 영역을 넘어갈 경우 줄바꿈 여부
              style: Theme.of(context).textTheme.headline5,
            ),
            Text(
              '$_counter 번',
              style: Theme.of(context).textTheme.headline5,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

 

화면 구성하는 것을 이해하기 위해 다시 수정해 본다.

import 'package:flutter/material.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      //home: const MyHomePage(title: 'Flutter Demo Home Page'),
      home: HelloPage(title: 'Hello Flutter',));
  }
}
 
// Android Studio 에서 stful 엔터를 치면
// 자동으로 만들어진다. 여기에 클래스 이름만 지정한다.
class HelloPage extends StatefulWidget {
  const HelloPage({Key? key, required this.title}) : super(key: key);
 
  final String title;
 
  @override
  _HelloPageState createState() => _HelloPageState();
  // Stateless 위젯과 다른 점은 createState() 메소드를 통해
  // 상태를 담당하는 클래스를 지정할 수 있다.
}
 
// 클래스 이름 앞에 _가 붙어 있으면 private 클래스로 본다.
// 다트에서는 Java와 같이 public, protected, private 같은 접근 제어자 키워드 없음.
class _HelloPageState extends State<HelloPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Text(
        'Hello, World',
        style: TextStyle(fontSize: 20),
      ),
    );
  }
}
 

 

'Flutter 앱 > 환경설정' 카테고리의 다른 글

Flutter Upgrade  (0) 2022.06.17
dart-sdk 설치  (0) 2022.01.11
Target of URI doesn't exist 'package:flutter/material.dart'  (0) 2022.01.11
Firebase 프로젝트 등록 방법  (0) 2021.12.29
Flutter 설치  (0) 2021.12.20
블로그 이미지

Link2Me

,
728x90

https://flutter.dev/docs/get-started/install/windows 에서 파일을 받아서 압축을 푼다.

그런다음 C 드라이브로 옮겼다. (용량이 충분한 곳에 설치하면 된다) 

 

 

 

위 그림과 같이 환경변수에 Flutter 를 등록해준다.

 

CMD 창을 열고 flutter doctor 를 실행하니까 아래와 같이 나온다.

 

 

 

Flutter Project 를 생성할 수 있는 버튼이 생겼다. Open 버튼 우측을 눌러 SDK Manager 를 선택한다.

 

 

 

 

아래 그림과 같이 이슈가 없다면 Flutter 설치는 준비된 것이다.

 

 

'Flutter 앱 > 환경설정' 카테고리의 다른 글

Flutter Upgrade  (0) 2022.06.17
dart-sdk 설치  (0) 2022.01.11
Target of URI doesn't exist 'package:flutter/material.dart'  (0) 2022.01.11
Firebase 프로젝트 등록 방법  (0) 2021.12.29
Flutter 시운전  (0) 2021.12.22
블로그 이미지

Link2Me

,