플러터에서 Navigator를 사용하려면 context를 반드시 받아야 하는데,

만약 Widget을 method로 빼서 사용한다면 context를 인자로 넘겨줘야 할것이다. 

하지만 그렇게 넘겨주게 되면 번거로운작업이 되고 햇갈릴 가능성이 농후하기 때문에 그때는 Builder Widget을 사용하면 된다. 

 

사용방법은 기존에 있는 Widget최상단에서 Builder WIdget으로 감싼뒤 

안에 builder속성에 context를 넣고 기존에 있는 Widget을 리턴하면 

context를 사용할 수 있다. 

 

예제는 아래와 같다. 

 Widget item() {
    return Builder(builder: (context) {
      return GestureDetector(
        onTap: () {
          Navigator.push(
              context, MaterialPageRoute(builder: (context) => DetailPage()));
        },
        child: Container(
          width: double.infinity,
          height: 120,
          child: Stack(
            children: [
              Positioned(
                width: 120,
                height: 120,
                right: 0,
                child: ClipRRect(
                  borderRadius: BorderRadius.circular(20),
                  child: Image.network(
                    'https://picsum.photos/200/300',
                    fit: BoxFit.cover,
                  ),
                ),
              ),
              Container(
                width: double.infinity,
                height: double.infinity,
                margin: EdgeInsets.only(right: 100),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(20),
                ),
                padding: EdgeInsets.all(20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'data',
                      style:
                          TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
                    ),
                    Spacer(),
                    Text(
                      'dighdighdighdighdighdighdighdighdighdighdighdighdighdighdigh',
                      overflow: TextOverflow.ellipsis,
                      style: TextStyle(color: Colors.grey, fontSize: 12),
                    ),
                    SizedBox(
                      height: 4,
                    ),
                    Text(
                      '2024/12/03 : 13:01:05',
                      style: TextStyle(color: Colors.grey, fontSize: 12),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      );
    });
  }

 

728x90

플러터에서 웹뷰는 iOS, Android의 네이티브 컴포넌트를  사용하여 띄움

따라서 패키지를 추가시켜줘야함

크게 2가지 webView가 있는데

  -> flutter_webview: flutter공식팀에서 만들고 관리하지만 기능이 많이 없음

  -> flutter_inappwebview: 3rd party지만 여러 기능이 있음 

기능이 많이 없는관계로 보통 inappwebview를 많이 쓴다고 한다 

 

추가하는것은 간단하게 flutter pub add flutter_inappwebview로 패키지를 추가해주고 

다음과 같이 추가하여 쓸수 있다. 

InAppWebView(
    // InAppWebView 최초 요청할 URL
    initialUrlRequest: URLRequest(
      url: WebUri("https://www.naver.com/"),
    ),
    // WebView 설정 : 외우지 마시오! 버전바뀌면 사용법 바뀌니까 이런설정을 할 수 있다 정도로만 학습바랍니다!
    initialSettings: InAppWebViewSettings(
      // 사용자 제스쳐 없이도 비디오, 오디오 자동재생 가능여부
      mediaPlaybackRequiresUserGesture: true,
      // 페이지 javascript 활성화여부. 웹 브라우저에서는 js 필수불가결한 요소라 true!
      javaScriptEnabled: true,
      // 요청하는 클라이언트의 브라우저 종류, 운영체제, 장치 정보 등을 서버에서 알 수 있게 보낼때 같이 보냄
      // 디폴트로 웹뷰로 되어 있는데 일부 웹페이지에서는 웹뷰로 접속시 차단하는 페이지도 있으니 꼭 설정!
      userAgent:
          'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
    ),
    // WebView 네이티브 컴포넌트가 만들어지면 호출됨
    onWebViewCreated: (controller) {
      print('onWebViewCreated');
    },
    // 페이지 로딩이 시작될 때 호출됨
    onLoadStart: (controller, url) {
      print('onLoadStart');
    },
    // 페이지 로딩이 완료되면 호출됨
    onLoadStop: (controller, url) {
      print('onLoadStop');
    },
    // 웹뷰 내 웹 페이지에서 GPS, 카메라 등의 권한을 요청했을때 호출됨
    onPermissionRequest: (controller, request) async {
      print('onPermissionRequest');
      return null;
    },
  )
728x90

TextField 사용시 반드시 해줘야 하는게 있다. 

바로 controller의 dispose인데

만약 까먹지 않고 하지 않았다고 하면 페이지는 사라져도 controller는 메모리에 계속 남게되어 leak이 된다. 

 

dispose하는 방법은 간단한데, 

Widget을 StatefulWidget으로 변경한뒤 dispose 메서드를 override해주면서 

controller의 dispose함수를 같이 호출해 주는것이다. 

 

아래 코드를 보면 void dispose부분에서 controller의 dispose메서드를 호출하는부분을 확인할 수 있다. 

import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  TextEditingController _controller = TextEditingController();

  @override
  void dispose() {
    // TODO: implement dispose
    _controller.dispose();
    super.dispose();
  }

  void onSearch(String text) {
    print(text);
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        FocusScope.of(context).unfocus();
      },
      child: Scaffold(
        appBar: AppBar(
          title: TextField(
            onSubmitted: onSearch,
            controller: _controller,
            maxLines: 1,
            decoration: InputDecoration(
              hintText: 'Search any book',
              border: MaterialStateOutlineInputBorder.resolveWith((states) {
                if (states.contains(WidgetState.focused)) {
                  return OutlineInputBorder(
                    borderRadius: BorderRadius.circular(10),
                    borderSide: BorderSide(
                      color: Colors.blue,
                      width: 2,
                    ),
                  );
                } else {
                  return OutlineInputBorder(
                    borderRadius: BorderRadius.circular(10),
                  );
                }
              }),
            ),
          ),
        ),
        body: Center(
          child: Text('This is the home page'),
        ),
      ),
    );
  }
}

 

 

728x90

플러터에서 사용자로부터 입력을 받을때 TextField를 사용하는경우가 많을것이다. 

 

TextField를 누르면 보통 유저에게 키보드가 나타나게 되는데

플러터에서는 입력을 마치고 빈화면을 누를때 키보드가 자동으로 사라지지 않는다!

 

이를 해결하기 위해 다음과 같이 코드를 짜야한다 

 

코드는 아래와 같다 

import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        FocusScope.of(context).unfocus();
      },
      child: Scaffold(
        appBar: AppBar(
          title: TextField(),
        ),
        body: Center(
          child: Text('This is the home page'),
        ),
      ),
    );
  }
}

 

잘 보면 Scaffold를 GestureDetector로 감싸서 앱이 클릭되었을때 기능이 실행되게 하고 

클릭되었을때는 현재 포커스를 잡고있는 컨텍스트를 풀어주는 것을 확인 할 수 있다. 

 

사소하지만 필수적으로 구현되어야 하는 기능이다.

728x90

JSON이란 JavaScript Object Notation의 약자로 JS에서 쓰는 객체 표시 방식이다 

 

JSON은 key- value쌍으로 이루어져 있는데

key는 무조건 String 타입이고, value에는 여러가지 타입이 들어갈수 있다 

(String, Numver, Booleanb, Array, Object, null등)

 

Dart에서  JSON데이터 사용방법

데이터를 주고받을떄는 JSON형식의 String으로 주고받음

  직렬화 -> Dart객체 ->  MAP -> String

  역직렬화 -> String -> MAP -> Dart객체 

  (항상 Map을 통해 변환한다)

 

클래스 만들때 fromJson 네임드 생성자, toJson 메서드를 만들어서 직렬화, 역직렬화를 한다

 

서버와 통신을 통해서 직렬화, 역직렬화가 꼭 필요하다(데이터를 주고받기 위해)

728x90

이번 주차는 실제로 앱을 만들어 보는 프로그래밍 과제와 창업 심화(?) 진도를 나갔다 

 

이번주 제공된 프로그래밍 강의는 간단한 앱 3가지를 만들어 보는것으로 UI를 따라서 만들고

기본 StatefulWidget으로 상태도 관리 할 수 있게끔 구성되어있었다. 

 

프로그래밍 강의를 따라감에 있어서 큰 어려움은 없었다.

과제가 하지만 생각보다 생각해야 하는 부분이 많았다. 

 

과제 소개를 읽어보면 얼핏 이해가 되는듯 싶었으나 중요한 부분에서 설명이 빠져있는 부분이 있는거같아

그부분을 추측하면서 과제를 진행해야 헀다. 

기본 + 도전 과제까지 완료하는데 소요시간은 하루꼬박 하고 반나절정도 걸렸으며

나중에는 '이거 한번 도표를 그리고 해야하나' 싶은 생각도 들었다 

 

비전공자 팀원분들은 과제UI을 그리다가 마무리가 되었다고 한다(완성하시지 못함 ㅠ)

프로그래밍을 한달정도 배우면서 과제가 비전공자들에게는 매우 어렵겠다고 생각이 들었다. 

 

다른 한편으로 창업 과제도 해보았는데

원래 아이디어는 창업 튜터님이 오셔서 5whys를 하는동안 엎어졌고 

새로운 아이디어를 내야하는동안에 팀원분들이 프로그래밍을 쫒아가느라 시간이 없어서 

혼자서 생각해보는 시간이 많았다. 

 

아이디어 내기가 쉽지 않았고 나오는 아이디어도 별로 신통치 못한와중에

창업강의는 계속 진행되어 페르소나, 시장분석등 여러 창업 기술을 배우는 세션이 있었는데

사실 들으면서 이해가 잘 안되었다. 나중에 다시 한번 들으면서 정리하는 시간이 필요한듯 싶다 

 

나에게는 창업과제가 프로그래밍보다 훨씬더 난이도 있게 느껴졌다 만

결국 1인창업이던 팀 창업이던 배워야 하는것이기 때문에 다음 주차도 화이팅을 해보려고 한다 

 

화이팅이다 

728x90

'창업 > WIL(Weekly I Learned)' 카테고리의 다른 글

[내일배움] WIL-3  (1) 2024.11.08
[내일배움] WIL-2  (2) 2024.11.01
[내일배움] WIL-1  (6) 2024.10.25

페르소나 

 

고객 파헤치기 ->

  첫째 고객페르소나 분석의 중요성을 이해하는것 

  둘째 페르소나를 설정하는 방법을 습득하는것

  셋째 실제 창업 과정에서의 적용을 배우는 것 

 

페르소나란 ->

  내 솔루션의 필요성을 느끼는 구체적인 가상의 인물 

  내 서비스를 써줄 사람이 누구인가?

 

페르소나를 설정하면 특성에 맞는 맞춤형 MVP를 설계할 수 있음

 

페르소나를 하는 이유

  효율적인 접근을 할수 있음(일반적인 타겟이 아닌 인원이 아니고 실제적인 타겟을 가정함)

  스타트업에서 넓은 대상을 타겟을 하면 소요되는 리소스가 많기 때문에 매출을 낼수있는 특정 고객군에게 어필해보기 위함

 

페르소나 작성 가이드

  기본정보

  이름,나이,성별

  직업,소득, 교육 수준

 

  가족구성,거주지역

  심리적 및 행동적특성

  가치관, 관심사

 

  주요문제점

  집중하는 목표

  구매행동, 소비패턴

 

  상황적 정보

  하루일과, 생활 패턴

  자주방문하는 장소

  온라인 활동 등

 

최대한 디테일하게 묘사하는게 포인트

가상인물에게 목표를 만들어주는게 아니고, 목표를 파악하는게 목표다 

 

[사용자]는, [사용자의필요]가 핋요하다 왜냐하면 [인사이트] 이기 때문이다 

 

고객은 무엇을 원하는가

 

유져 리서치를 왜하는가?

사용자의 행위와 동기를 이해하는 활동

고객의 진짜 문제와 니즈를 발견하고 제품의 개선방안을 도출

 

리서치에서 질문을할때 절대 하지말아야 할 질문은?

만약으로 시작하는 질문, 주관에 기대면 안된다 

 

728x90

flutter create를 통해 프로젝트를 생성하면 아래 사진과 같은 구조로 파일구조가 생성되게 된다. 

파일구조를 살펴보자 

 

제일먼저 lib 폴더는 프로그램에서 사용되는 dart파일을 넣어두는 폴더이다.(사진에서도 main.dart가 포함되어있다)
실제 여기서 여러 폴더구조를 만들고 파일을 생성하여 코딩을 하는 폴더이다 

 

다음 android, ios, linux, macos, web폴더인데 각각 디바이스에서 사용할 수 있는 센서등을 사용할때
native언어로 코드를 작성해서 사용하면 된다고 한다 

 

test폴더는 TDD를 위해 lib폴더의 테스트를 생성하기 위한 폴더이다 

 

다음으로 pubspec.yaml은 프로젝트 구성에 대해 선언이 있는곳인데, SDK버전이나, 사용할 라이브러리등을 선언한다
사용방법은 pub.dev에서 선언되있는 dependency를 긁어서 복붙하거나 flutter pub add명령어를 사용해서 라이브러리를 추가하는 방식이다 

 

그 외 파일들은 딱히 프로젝트 사용에 있어 건드릴 필요가 없어 소개는 여기까지 하기로 한다. 

728x90

+ Recent posts