플러터 처음 빨리 시작하기~

Computer 비관심/Flutter|2021. 4. 23. 01:04
반응형

1. 폴더구조

플러터개발시작시 유튜버들이 많이 사용하는 폴더구조

 

2. 스타일에 사용될 상수 만들기

디자인과 관련된 상수를 가진 색상 클래스, 엘리먼트 형태관련 클래스를 만들어서 디자인을 쉽게 하기

 

3. 데이터 모델 만들기

사용할 데이터의 형태를 지정하기 위해 데이터 모델만들기

 

4. 실제 사용하거나 UI디자인/테스트를 위한 데이터 만들기

개발중 데이터를 제공할 파일을 만듬

 

5. 여러개의 스크린을 불러올 수 있는 스크린콜랙션파일 생성 (Optional)

 

6. 여러개의 위젯을 불러올 수 있는 위젯콜렉션파일 생성

 

7. 웹을 위한 반응형 위젯 만들기

 

8. 데이터 오브젝트나 오브젝트 리스트를 json으로 바꾸기

 

9. 스트링으로 된 Json을 리스트로 바꾸기

 

10. GetX로 상태관리

GetX를 통해 state를 관리

 

11. GetX List 읽고 쓰고 수정하고 지우기

 

기타 미분류

플러터 위젯에 대해

 

 

 

 

1. 폴더구조

- assets/icons -svg

- assets/images -png

-lib/controllers

-lib/models - xxx_model.dart

-lib/screens - xxx_screen.dart

-lib/services

-lib/widgets 

-lib/configs/palette.dart

 

 

2. 스타일에 사용될 상수 만들기

lib/configs/pallette.dart

공통으로 쓰일 칼러지정

class Palette {
	static const Color PrimaryColor = Color(0xFF473F97);
}

 

materialApp / GetMaterialApp의 theme 속성을 사용할시

 

 

theme: ThemeData(
  // 앱바의 배경색과 글자의 색과 형태를 설정
  appBarTheme: Const AppBarTheme(backgroundColor: Palette.background, title: TextStyle( color: Colors.white, fontSize: 18,)),
  // 배경색을 설정
  sccaffoldBackgroundColor: Palette.background,
  // The background color for major parts of the app (toolbars, tab bars, etc)
  primaryColor: Colors.white,
  //버튼 등 색상
  accentColor: Palette.green,
  iconTheme: const IconThemeData(color: colors.black),
  fontFamily: GoogleFonts.montserrat().fontFamily,
  textTheme: GoogleFonts.montserratTextTheme(),
),
home: 홈스크린으로 사용할 위젯

 

 

 

lib/configs/styles.dart

공통으로 쓰일 엘레멘트의 스타일 지정

class Styles {
	statics const buttonTextStyle = TextStyle(
     fontSize:16.0,
     fontWeight: FontWeight.w600);
    
    statics const ChartTextStyle = TextStyle(
     color:Clors.grey,
     fontSize:16.0,
     fontWeight: FontWeight.w500);
    
    statics const tapTextStyle = TextStyle(
     fontSize:16.0,
     fontWeight: FontWeight.w600);
}

 

or

 

lib/configs/consts.dart

const kTextColor = Color(0xFF535353);
const kTextLightColor = Color(0xFFACACAC);
const kDefaultPadding = 20.0;

 

 

3. 데이터 모델

lib/model/product.dart

class Product {
string a, b, c;
	product ({this.a, this.b, this.c})
}

 

Json로 클래스를 만들어주는 사이트 - 여기서 쉽게 데이터 모델을 만들 수 있다.

javiercbk.github.io/json_to_dart/

 

 

4. 실제 사용하거나 UI디자인/테스트를 위한 데이터 만들기

lib/data/data.dart

List<Map> categories = [{"name":"music","icon": Icons.music_note,} {...},{...}];


List<Product> icecreamProducts = [
Product(a:'a',c:'ass',b:'ddd'),
Product(a:'a',c:'ass',b:'ddd'),
Product(...),
Product(...),
Product(...),
];

List<Product> chocolateProducts = [
Product(a:'a',c:'ass',b:'ddd'),
Product(a:'a',c:'ass',b:'ddd'), 
Product(...)
];

 

 

5. 여러개의 스크린을 불러올 수 있는 스크린콜랙션파일 생성

lib/screens/screens.dart

스크린들을 불러오는데 사용

(Marcus Ng 유튜브 비디오 참조)

 

export 'bottom_nav_screen.dart';
export 'home_screen.dart';
export 'stats_screen.dart;

 

 

6.  여러개의 위젯을 불러올 수 있는 위젯콜렉션파일 생성

lib/widgets/widgets.dart

위젯 불러오는데 사용

(Marcus Ng 유튜브 비디오 참조)

 

 

7. 웹을 위한 반응형 위젯 만들기

lib/widgets/responsive.dart

import 'package:flutter/material.dart';

class Responsive extends StatelessWidget {
  final Widget mobile;
  final Widget tablet;
  final Widget desktop;
  Responsive({Key key, @requred this.mobile, this.tablet, @required this.desktop})
      : super(key: key);

  static bool isMobile(BuildContext context) => 
    MediaQuery.of(context).size.width < 800;
  
  static bool isTablet(BuildContext context) => 
    MediaQuery.of(context).size.width >= 800 &&
    MediaQuery.of(context).size.width < 1200;
    
  static bool isDesktop(BuildContext context) => 
    MediaQuery.of(context).size.width >= 1200;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      if (constraints.maxWidth >= 1200) {
        return desktop;
      } else if (constraints.maxWidth >=800) {
        return tablet ?? mobile;
      } else {
       return mobile;
      }
    });
  }
}

 

 

8. 데이터 오브젝트나 오브젝트 리스트를 json으로 바꾸기

List<Product> dataList =[
Product(name:'Product A', price:3700),
Pproduct(name:'Product B', price:3800),
]

String jsonDataList = jsonEncode(dataList);

 

bezkoder.com/dart-flutter-convert-object-to-json-string/

 

 

9. 스트링으로 된 Json을 리스트로 바꾸기

List dataList = jsonDecode(jsonDataList);
dataList.map((data) => Stock.fromJson(data)).toList();

stackoverflow.com/questions/51053954/how-to-deserialize-a-list-of-objects-from-json-in-flutter

 

 

10. GetX로 상태관리

 


// 데이터를 받아와야 할때
class MyStocksCtr extends GetxController {
  List<dynamic> products = [].obs;
  @override
  void onInit() {
    products.assignAll(datas); // 이렇게 말고 asyn 함수를 만들어야 함
    super.onInit();
  }
}

 

class MyStockScreen extends StatelessWidget {
  final MyStocksCtr controller = Get.put(MyStocksCtr());
  
  ...
  
  
  
  child: Obx(() {
            return ListView.builder(
                 itemCount: controller.products.length,
                 itemBuilder: (context, index) {
                   final Stock stock = controller.products[index];
                   return CustomCard(stock: stock);
                  }
              );
            },
          ),

 

 

쓰기 controller.products.add(쓸객체)

지우기 controller.products.delete(지울엘리먼트)

인덱스로 지우기 controller.products.deleteAt(지울엘리멘트의 인덱스)

 

수정

위젯에서 리스트의 인덱스 받기 

인덱스가 있으면 에디팅컨트롤러의 텍스트에 기존 내용을 넣기 

controller.products[index].속성 = 에디팅컨트롤러의 수정된 내용

 

Get.back

Get.to(() => MyHomePage(title: '전달값')

 

 

 

- 플러터는 레고의 블럭을 껴서 만드는 방식과 비슷하게 만들어 진다. 그 블럭을 위젯이라고 하는데 그런 위젯을 직접만들거나 남들이 제공하는 위젯을 끼워넣는 방식으로 개발이 이루어진다. 이와 같은 플러터의 구성 때문에 위젯간의 데이터 전달(커뮤니케이션)이 개발에서 상당히 중요하다.

 

- 개발시 stateful위젯과 stateless 위젯을 상속하여 자신의 위젯을 만드는데 stateless는 변화되는 상태값을 가지고 있지 않지만 stateful 위젯은 변화되는 상태값을 가지고 있다.

 

stateless 위젯은 직접 위젯을 build 하는 메서드를 가지고 있으며 값은 생성자를 통해 전달받으며 변하지 않는다. 

 

stateful 위젯은 생성자를 통해 값을 전달 받지만 state를 관리하기 위해 state위젯을 상속한 클래스를 불러서 그 클래스의 값을 state로 한다. 그리고 그 스테이트위젯을 상속한 클래스는 build메서드를 가지고 있다. 

 

즉,

class Bird extends StatefulWidget {
  const Bird({
    Key? key,
    this.color = const Color(0xFFFFE306),
    this.child,
  }) : super(key: key);
  
  // 생성자를 통해 얻어올 값 
  final Color color;
  final Widget? child;
 
  // 스테이트를 가질 수 있는 객체를 실행
  _BirdState createState() => _BirdState();
}



class _BirdState extends State<Bird> {

  // 스테이트, 변할수 있는 값들
  double _size = 1.0;

  void grow() {
    setState(() { _size += 0.1; });
  }

  @override
  Widget build(BuildContext context) {
    // 여기에 변수를 사용하면 주로 UI와 관련된 변수 사용
    
    return Container(
      color: widget.color,
      transform: Matrix4.diagonal3Values(_size, _size, 1.0),
      child: widget.child,
    );
  }
}

 

 

 

UI를 개발시 기능은 미구현된 형태로 먼저 개발하면 편함

댓글()

플러터에서 자식 위젯의 메서드 부모에서 호출하기

Computer 비관심/Flutter|2021. 4. 10. 01:12
반응형

플러터는 위젯으로 구성되어 있다. 그렇기 때문에 위젯간의 소통을 할 수 있는 방법을 아는 것이 중요하다. 위젯간의 소통 방법들을 공부하지 않으면 분리되지 않은 거대 위젯으로 앱이 구성이 될 것이다.

 

 

부모의 버튼을 눌렀을때 자식 스크롤 위젯이 자동으로 맨 밑까지 내려오게 하는 기능을 구현해야 했다.

위젯이 나누어지지 않았을 때는 문제가 없었지만 위젯이 부모와 자식으로 나누어 지면서 버튼과 리스트가 분리 되었다.

 

 

이때 부모가 자식의 메서드를 호출해서 그 메서드가 자식을 움직이게 만드려면 어떻게 해야 할까?

StackOverflow에서 두가지 방법을 찾을 수 있었다.

 

 

첫번째는 메서드를 초기화한 클레스의 인스턴트를 전달하는 방법

1. 클레스에 메서드를 초기화 해서 자식 위젯에 인스턴트를 전달한다.

2. 자식위젯에서 구현한 메서드를 전달받은 인스턴트의 메서드에 넣는다.

3. 부모에서 구현한 메서드를 호출한다.

(그러면 자식에서 구현한 메서드가 실행됨)

 

class HomePageController {
  void Function() methodA;
}

class MyApp extends StatelessWidget {

  final HomePageController myController = HomePageController();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: Icon(Icons.help),
            onPressed: () {
              myController.methodA();
            },
          ),// IconButton
        ),// AppBar
        body: HomePage(
          controller: myController,
        ),// HomePage
      ),
    );
  }
}

class HomePage extends StatefulWidget {

  final HomePageController controller;

  HomePage({ this.controller });

  @override
  _HomePageState createState() => _HomePageState(controller);
}

class _HomePageState extends State<HomePage> {

  _HomePageState(HomePageController _controller) {
    _controller.methodA = methodA;
  }

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

  void methodA() {}
}

 

 

 

두번째는 자식위젯에 글로벌키 넣어 접근하는 방법

1. 자식 위젯이 키를 전달 받을 수 있도록 만든다.

2. 자식 위젯에 글로벌 키를 만든뒤 자식에게 전달.

3. 만들어진 글로벌 키로 자식 메서드 접근

 

GlobalKey<_HomePageState> globalKey = GlobalKey();

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: Icon(Icons.help),
            onPressed: () {
             globalKey.currentState.methodA();
            },
          ),
        ),
        body: HomePage(key: globalKey),
      ),
    );
  }
}
class HomePage extends StatefulWidget {
  HomePage({Key key}) : super(key: key);

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

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  void methodA() {}
}

여기서 중요한건 위젯을 파일로 나누었을때 GlobalKey<_HomePageState> globalKey=GlobalKey()에서

_ (언더바) 를 사용하면 참조를 못 한다는 것이다. 

 

코드출처: stackoverflow.com/questions/53692798/flutter-calling-child-class-function-from-parent-class

댓글()

개발이 어려운게 아니라... 기획이 어려운 것일지도.

Computer 관심/이것저것|2020. 10. 25. 01:33
반응형

혼자서 개발을 할때는 기획 역시 혼자서 해야 한다.  

사실 다른 사람들은 혼자 개발할 때 기획과 개발을 정확히 나누면서 하는지 그렇지 않은지 모르겠지만

난 그렇게 하지 않았다. 그래서 문제가 발생한 것이다.

 

모든걸 개발이라고 생각해 버린것...

정확한 기획 없이 코드를 만드려했다.  그러다 보니 애매하다... '어떻게 만들겠다' 정하지 못한체로 만들 생각이 끼어든다.

 

사실 코딩하는 것은 생각보다 단순하다. 왠만한건 구글에 다 나와있다.

명확한 목표가 있으면 그걸 구현하는건 그저 시간투자이다. (물론 깔끔하고 완벽한 코딩은 어렵겠지만)

 

하지만 기획에서 명확한 구현의 목표를 정하지 못하면 코딩이 막혀버리고 

코딩은 어렵다... 라고 잘못된 인식을 가질 수도 있다.

 

기획이 어려운게 정답이 없다...ㅠㅠ

이렇게 할까? 저렇게 할까? 애매하게 생각이 끝나는 경우가 많다... 

생각이 열린 상태에서 닫고 마무리 짓지 못한 것이다.

아마 이건 기획서라도 작성을 하면 도움이 될 것 같다.

 

 

그도 그럴것이.. 기획서를 만들지도 않으니..

그냥 '머리에 있으니 그대로 하지' 라고 생각하지만 얼마뒤 뭘하려는지 까먹게 되는거...

 

기술적인 것과 코딩이 더 어려울거라는 편견 때문에 기획에 집중하거나 시간과 공을 들이지 못한다.

 

어째튼 취미로 하는 코딩 머리아프면 재미 없다.

아이디어를 만드는 일 = 기획

이 기획을 명확히 생각하는게 더 중요할 것 같다. 

그래야 그 아이디어를 코드로 번역할 것 아닌가.......

댓글()

[앱개발] 어플리케이션 성공의 3 요소 중

기타|2020. 9. 12. 00:26
반응형

기획, 개발, 홍보

 

무엇이 더 중요할까.

개발을 못하는 사람에게는 개발이 중요하다 생각이 들겠지만

개발을 하는 사람 역시 개발을 제외한 다른 부분을 소홀이 하는 경우를 많이 보았다. 

 

나 역시

어플리케이션을 만들때...

기획을 소홀히 한 것 같다.

사실 마인드가 그랬었다.

개발에 비중을 더 둔것이다.

 

런칭을 해보고 홍보를 해보니 "사용자가 필요한게 무엇일까" 더 생각을 해봤으면 어땠을까 한다.

물론, 개발은 그 기획이 아이디어가 아닌 현실화가 되는데 있어 중요하다. 아무리 뛰어난 아이디어라도 현실화 시킬수가 없으면 소용이 없는 것이 아닌가.

그런데 다행이도 개발패러다임의 변화라든가 개발환경의 변화로 인해 개발영역은 더 쉬워지고 있는 것 같다. 

 

현실화시키는 중요한 단계가 쉬워진다는 것은 그만큼 홍보와 아이디어가 밀접해진거라 생각해도 되지 않을까?

 

"더 단순화 시키면

아이디어의 구성을 남들에게 알리는 것" 이것이 핵심이다.

 

내 아이디어의 세계에 빠져 보는 시간을 가져야 한다.

 

댓글()

1. [앱 개발 후 홍보 3일차] 개발한 앱 페이스북 홍보 진행

반응형

개발자로 살아간건 단지 5개월 밖에 안되지만 대략 5년 정도를 웹에 시간을 투자한거 같다.

웹사이트를 여러차래 만들었다. 웹만 만들다 보니 나도앱과 윈도우 프로그램을 만들어보고 싶다는 생각이 들었다. 

"어렵다, 생소하다, 앱보단 그래도 미래는 웹아닌가?" 생각하며 미루고 미루다 목표를 정했다.

 

목표는 "쓰레기같은 앱을 만들더라도. 플레이스토어에 올려보자^^" 였다.

(그래도 내가 만든게 쓰레기는 아니길....)

 

그래서 회사가 끝난 저녁시간과 주말 짬을 내어 플러터로 앱을 하나 만들었다. 앱을 만드는데 3개월이라는 시간이 걸렸다.

 

---------

 

홍보 1일차

네이버 블로그를 만들어 앱을 소개했다. 물론 새로 만든 블로그를 방문한 사람은 제로(0)이다.

 

홍보 2일차

역시 방문자 0

 

홍보 3일차

하나의 글을 더 적었고 1명이 읽었다고 하는데 그게 아마 나 아닐까 싶다.

역시 예상했듯 초반 사용자를 확보하는게 어렵다. 

이전에 이런 상황을 경험해보지 않았으면 아마 엄청난 실망감에 좌절을 느꼈을테지만...

이미 그때 좌절을 다해서 지금은 혹시나가 역시나구나 생각이 든다.

 

그리고 페이스북 광고로 작은 돈(커피값 정도)를 10일간 투입해보기로 했다.

해외에 있어서 내 유효기간이 만료된 카드가 작동을 할지모르겠다만 이상하게 작동을 한다. 

30분전에 시작이 되서 그런지 Reach가 10명 많지는 않다.

 

 

사람이 실제 사용하는 서비스를 만들어보고 만들고 운영해보고 싶다.

여기서 보람을 찾고 싶은데 가능할까?

 

 

 

 

댓글()