Developer port RSS 태그 관리 글쓰기 방명록
Flutter (13)
2023-11-01 18:37:15

$$ 이 포스팅은 노 베이스를 대상으로 하지 않는다 $$

$$ 노 베이스는 다른 포스팅을 먼저 보고 오도록 하자 $$

 

저번 시간에 우리는

 

 

버튼을 누르면 숫자가 증가하도록 만들었다

 

그리고 초기화는 숙제였지

 

 

별거 있나,

그냥 0으로 만들면 되는거지

 

 

버튼도 연결해준다

 

이제 기본 시스템은 구현이 끝났다

 

남은건

 

확률 구현하고

확률 적용하고

화면에 표시하는 것 뿐이다

 

자 그러면 확률 구현은 어떻게 할 것이냐

 

구현 방법은 여러가지가 있지만

 

우리는 살짝 노가다 방식을 사용할 것이다

 

걱정하지 말아라

 

확률 데이터 파일은 제공하도록 할테니

 

뭐 연산식을 사용할 수도 있겠지만

 

코린이한테 연산식을 구현해보라고 하는건

 

너무 가혹한 얘기가 아닌가

 

 

좌측의 lib 폴더에

새로운 폴더를 하나 만든다

 

폴더명은 localData

 

파일명은

 

probabily.dart

 

 

파일 내용을 작성하기 전

 

확률 구현에 있어서

 

필요한 로직을 한번 정리해보자

 

뭐 구현하고 싶은 마음대로 하면 되지만

 

나를 따라할거라면

 

다음과 같은 로직을 적용할 수 있다

 

1. 강화 성공 확률은 5 스테이지마다 2%씩 감소한다

2. 강화 하락 확률은 11스테이지마다 0.5%씩 증가하며 최대 7%까지만 증가 한다

3. 강화 성공 확률은 최대 30%까지만 하락하며 그 이하는 내려가지 않는다

4. 10스테이지마다 하락 확률은 0이 된다

5. 강화 스테이지가 50이 되면 하락 확률은 5%로 증가한다

 

그러면 해당 내용을 반영한 노가다 데이터를 만들어보자

 

 

이런 자료를 하나 만든다

이 자료가 담을 수 있는 데이터 형태를 하나 소개한다

 

1: {'success': 1.0, 'maintain': 0.0, 'decrease': 0.0},

 

해당 내용을 풀어보면

 

Map <int> 1 2 3
Map <String> success maintain decrease
Map <Double> 1.0 0.0 0.0

 

이런식으로 배치된다

 

별거 없다

Map 자료란

 

간단하게 말해서

 

내가 보기 쉽게 데이터를 정리 한 것이다

물론 저 대로 사용할 수 있다

 

보통 키:쌍 이렇게 부르는데

키는 Success

쌍은 1.0

 

이런식으로 부른다

 

따라서 1.0을 쓰고싶으면 Success를 가져와 쓰게 된다

 

상세한건 나중에 설명하도록 하고

 

한번 내용을 기술해보자

 

 

다시 말하지만 코린이는

연산식을 만들어 계산하는게 힘들다

 

그게 가능하면 그건 코린이라고 할 수 없지 않을까?

 

확률데이터.txt
0.01MB

 

그래서 확률 데이터가 담긴 파일을 준비했다

 

다운로드 받아서 그대로 복사붙여넣기 하면 된다

 

 

 

이렇게 Map자료를 가져와서 사용하기 위해 변수를 만들고 지정한다

코드를 조금 분석해보자면

 

  Map<String, double> get currentProbability => 

 stageProbabilities[_Stage] ?? {'success': 0.0, 'maintain': 0.0, 'decrease': 0.0};

 

Map 자료를 선언한다 , 키와 쌍은 Stringdouble로 선언되었다

 

이제 파일을 불러와야겠지

 

 

 

그리고 HomePage.dart를 보면

 

 

 

onPreesed 안을 일단 주석처리 해준다

 

 

 

이러면 에러가 안생길 것이다

 

이제 저장하고 다음 작업을 이어가자

 

 

 

일단 스테이지를 1로 만들자

 

보통 게임은 1 스테이지 부터 시작이지 0 스테이지부터 시작이 아니니까

 

 그 다음 데이터가 정말 불러와지는지 확인 해보자

 

 

여기서 확인하는건 실제로 확률 데이터가 불러와지는지,

스테이지는 변화가 되는지에 대한 정보다

 

 

 

이제 강화버튼에 넣고 저장한 다음 버튼을 눌러보자

 

 

로그를 보면

 

확률을 불러오고 있고

 

스테이지가 잘 증가하는 것을 볼 수 있다

 

자 이제 잘 불러오니까 

 

확률적으로

 

성공 , 하락 , 유지를 반환하도록 함수를 만들어보자

 

 

그 전에 DownStage라는 함수를 먼저 하나 만들었다

 

하락이 나왔을때 스테이지는 하락해야한다

하지만 1스테이지 이하로 하락된다면?

 

그건 의도한 결과와 다르니 Max 메서드를 이용해

 

1 이하로 떨어지지 않도록 한다

 

이제 확률을 구현해보자

 

 

일단 DataConfigure 프로바이더 안에

 

함수를 하나 만든다

 

그 다음 랜덤 숫자를 사용하기 위해 패키지 하나를 import 한다

 

 

 

math 패키지는 랜덤숫자를 사용하거나 수식을 계산하거나

 

수학적인 일을 할때 사용한다

 

 

그 다음

Random() 객체를 이용할 random 변수를 하나 만들어주고

 

실제로 랜덤한 숫자를 담을 변수를 하나(randomNumber) 만들어준다

 

저걸 풀어보면

 

final double randomNumber = Random().nextDouble();

 

이런 형태가 될 것이다

 

왜 random = Random() 이런식으로 만드냐고?

 

지금은 우리가 하나의 랜덤값만 뽑아오니까 상관없는데

 

만약 여러개를 뽑아야 한다면

 

final double randomNumber1 = Random().nextDouble();

final double randomNumber2 = Random().nextDouble();

final double randomNumber3 = Random().nextDouble();

 

이런식으로 써야한다

 

이렇게 하면 매번 랜덤 숫자를 만들때

 

새로운 객체를 만들테고

 

성능이 떨어질 수 밖에 없다

 

3가지 일을 한사람한테 시키는것보다

 

하나 끝나고 하나 다시 시키고 

 

또 끝나면 다시 시키는 과정이

 

절대 효율면으로 좋을 수가 없다

 

따라서 하나의 객체를 만들고 돌려쓴다

 

그 다음

콘솔에 출력해보는데

 

print('Random Number : $randomNumber');

 

여기서 print 안에 왜 $ 이런게 들어있냐면
보통 변수를 출력하거나 글자를 출력하거나 한가지만 된다

 

근데 글자랑 변수랑 같이 출력하고 싶을 수도 있으니까

 

$를 쓰면 글자 안에서 변수를 출력할 수 있다

 

이제 테스트해보자

 

 

앞서 강화버튼에 다른거 넣어놨으니

 

이번에 다른 함수로 바꾸고 테스트 해보자

 

 

 

랜덤 숫자는 0.0 ~ 1.0 사이의 숫자를 반환하고

 

숫자 잘 반환하는걸 확인했다 다음 작업을 이어서 진행하자

 

함수를 수정한다

 

 

아까 로그로 확인한

 

성공 , 유지 , 하락에 대한 데이터를 현재 스테이지에 맞게 가져오고

 

lowerBound는 하한선을 나타낸다

 

이를 만들어두는 이유는

 

하한선 - 상한선 사이에 랜덤한 숫자가 있다면

함수에 적용하기 위한 일종의 필터링 같은 것이다

 

이게 왜 필요하냐고?

 

랜덤숫자는 계속 달라진다

 

그러면 값에 대한 검증이라던지, 어떤 모종의 이유로 구현 범위를 넘어설 수 있다

 

이럴경우 정상범위를 초과하므로 저렇게 지정하도록 한다

 

 

자 이제 제일 복잡한게 나왔다

 

구조는 쉽다

 

upperBound라는 상한선을 정하고

 

하한 - 상한 사이에 랜덤 한 숫자가 나오면

 

outcome 의 값으로 성공 ,하락을 구분한다

 

유지는 break를 통해 아무 작업도 하지 않는다

 

마지막으로 하한선을 상한선으로 덮어씌워

 

기존 값에 대한 검증이 확실히 되도록 한다

 

이렇게 작성하고 이제 테스트를 해보면

 

 

 

 

게임 화면과 로그다

 

잘 되는걸 볼 수 있다

 

그러면 실제로 성공했는지 실패했는지 어쨌는지 봐야할거니까

 

로그를 추가해보자

 

 

 

 

자 이제 저장하고 다시 실행해보자

 

 

강화가 하도 잘붙어서

 

실패하기까지 오래걸렸다

 

 

이제 화면에 확률을 표시해보도록 하자

 

HomePage.dart로 넘어와서

 

확률 데이터를 수정한다

 

 

일단 확률이 적힌 Map 자료를 가져오고

 

 

 

확률에 100을 곱해 정수로 만들어준다

 

확률을 0.1% 이런식으로 표시할 순 없으니까 말이다

 

그리고 텍스트를 한번 더 가공한다

double로 만든 데이터는 text 위젯에 넣을 수 없다

 

text위젯은 String , 문자만 지원하니까

 

따라서 String으로 바꿔주는데 이때 12.345455 이런식으로 나오면

 

12.34까지만 출력되게 toStringAsFixed 메서드를 사용한다

 

그 다음 텍스트 위젯에 넣는다

 

 

 

이제 const를 지워야 한다

const는 고정된 값만 지원하는데 확률은 계속 달라지니까 const를 지워야한다

 

const가 어디있냐고?

 

 

 

이 확률의 부모는 Padding 이므로 Padding앞에 const를 지운다

부모의 속성이 자식을 따라가기 마련이다

 

자 그러면

 

 

 

이제 확률이 화면에 표시된다

 

강화를 한번 시도해보자

 

 

 

화면에 잘 표시되는걸 볼 수 있다

 

끝내며

다음 시간엔 이제 기기에 데이터 저장과 불러오기

 

강화 총 횟수 설정 및 화면에 표시하도록 해보자

조금만 더 하면 시리즈가 끝난다 마지막까지 함께 해주길 바란다

2023-10-28 07:17:40

$$ 이 포스팅은 노 베이스를 대상으로 하지 않는다 $$

$$ 노 베이스는 다른 포스팅을 먼저 보고 오도록 하자 $$

 

저번 시간에

 

 

이렇게 레이아웃 작업을 진행했다

 

이번엔 필요한 외부 패키지들을 설치해보자

 

외부패키지에 간단히 설명하자면

 

모든 기능을 내가 구현할 수 있지만

남들이 만들어둔 유용한 패키지들을 가져와

 

내 프로젝트에서 사용할 수 있는 유용한 기능을 얘기한다

 

좌측에 보면

pubspec.yaml 파일이 보일것이다

 

yaml파일은 기본적으로 설정파일을 얘기하며

이곳에 패키지 설치 등 외부와 관련된 내용들이 기술된다 보면된다

 

 

패키지를 살펴보면

참 뭐가 많은데

우리가 건들일 부분만 살펴보도록 하자

 

 

 

이 부분에 설치할 패키지 이름과 버전을 기술할 것이다

 

우리는 기기에 저장하기 위해

 

Shared_preference 라는 패키지와

 

데이터를 보다 효율적으로 관리하기 위한 Provider를 설치할 것이다

 

 

 

이때 위치를 잘 맞춰준다

그렇지 않으면 에러가 뜰 것이다

 

Providerget_it 패키지는 같이 쓰는 패키지라고 보면된다

intl 패키지는 데이터 포맷을 지정하거나 할때 쓴다

 

 

설치가 끝나면

하단 OUTPUT에 오류 없이 설치 된 것을 확인할 수 있다

 

그러면 패키지 사용을 위해 사전 준비를 해보자

 

이번에 먼저 준비할 패키지는

 

ProviderGetIT 패키지다

 

Get_it 패키지는 싱글톤이라는 방법으로 Provider를 지정하게 해주고

해당 방식으로 데이터를 관리해 보다 편하게 사용할 수 있다

 

lib 파일에 새롭게 폴더를 하나 만들어준다

 

 

뉴 폴더를 눌러 폴더명을

Config로 만들어주자

 

 

그리고 폴더 안에 파일을 만들어준다

 

파일명은

dataConfigProvider.dart

singleTon.dart로 만들어준다

 

 

해당 파일을 지정했으면 이제 데이터도 지정하고 해야하지만

 

간단하게 프로바이더에 대해 알고 가자

 

플러터에서 각 위젯간 혹은 파일간에 변수값을 공유하려면

public 을 사용하거나 부모 → 자식 으로만 보낼 수 있다

 

물론 간단한 파일에서는 해당 방법이 유용할 수 있으나

 

살짝의 복잡도만 추가되어도 사용할 수 없는 수준까지 된다

 

본인이 코딩의 신이라 네이티브하게 쓸 수 있다면 모르겠는데

보통 99%의 사람들은 그게 안되므로 그냥 편하게 패키지를 사용하도록 하자

 

Provider말고도 변수를 공유하거나 할 수 있는 방법은 많지만

필자는 주로 Provider를 사용하는 경우가 많다

 

왜냐고?

 

먹던 맛이 무섭다

버릇들었으니까 자주 쓰는거지 뭐

다른거 써도 상관은 없다

 

이제 파일에 기술을 해줘야 하는데

 

4가지 과정을 거쳐야한다

1. Provider 파일 생성

2. 싱글톤 등록

3. 앱 실행시 main.dart 에서 싱글톤 실행

4. 등록한 싱글톤을 정상적으로 사용하기 위한 설정

 

한번 만들어두면 복사붙여넣기를 통해

다양한 프로젝트에 쓸 수 있으니

한번 잘 배워두길 바란다

 

정공법은 아니므로

정공법이 궁금하다면

 

우리의 친구 구글 혹은 챗GPT를 이용하도록 하자

 

 

파일에

 

class DataConfigure with ChangeNotifier {} 를 작성한다

 

이러면 상단에 import 되는건 기본적으로 될 것이다

 

조금 풀어서 설명하자면

 

ChangeNotifier를 사용해 데이터가 변화하면 화면을 업데이트 하도록 만드는 과정이다

 

이때 어떤 데이터가 어디에 담겼는지 확인하기 위해 DataConfigure라는 이름을 만들었다

 

우리가 기존까지 데이터를 변화시키려면

 

Stateful 위젯에 setState를 사용해야 한다고 알고 있었는데

 

이 방식은 Stateless 위젯에서도 작동하는 어-썸한 방식이다

 

프로바이더를 하나 만들었다면

 

이제 싱글톤을 만들러 가자

 

singleTon.dart 파일에서

 

 

패키지를 import 하고

인스턴스를 하나 만들어준다

 

인스턴스는 쉽게 말해

 

나 이거 쓸거임 하고 등록해두는 과정이라고 보면 된다

 

serviceLocator라는 이름을 사용하면 GetIt.instance라는 기능이 따라온다고 보면 되는 것이다

 

그 다음 파일에

 

 

이렇게 함수를 하나 만들어준다

 

함수를 전에 배웠던걸 기억하길 바란다

void란 반환이 없는

 

Return 이라는 것을 사용하지 않아  돌아오는게 없는 함수를 얘기한다

 

이제 setupServiceLocator 라는 함수를 실행하면 이 안에 기술된 내용들이 실행되는 구조다

 

그러면 안에 기술하도록 하자

 

 

기본적인 룰은 다음과 같다

 

serviceLocator 에서 인스턴스 Getit 서비스를 이용하기 위한 준비를 하고

준비가 되었다면 이제 기술될 프로바이더를 가져와 싱글톤에 등록을 진행한다

 

우리는 어떤 프로바이더를 등록해야하느냐

 

아까 만들어둔 프로바이더 DataConfigure가 있으니 이 것을 등록하도록 한다

 

 

등록하려고 봤더니 오류가 생긴다

 

당연하다

 

안불러왔으니까

 

패키지를 불러와야만 한다

 

 

이제 오류가 없음을 확인했다

 

함수를 만들면 뭐해야하는지 생각해보자

 

뭐겠는가 실행이겠지

 

띡 만들어놓는다고 알아서 실행 안된다

 

컴퓨터도 전원 스위치를 눌러야 시작되듯 이것도 마찬가지로 눌러줘야한다

 

main.dart로 이동한 다음 작업을 진행한다

 

 

참으로 간단한 main.dart

 

여기서 함수를 불러와 등록해주도록 한다

 

근데 다른 파일에 있는 함수를 가져오려면 어떻게 해야하지?

 

똑같다

 

import 하면 된다

 

그냥 외워두자

 

다른파일에 있는 기능 쓰고싶으면 불러와야한다

 

 

싱글톤 등록은 끝났다

 

다음 작업은 프로바이더를 정상적으로 사용하기 위한 작업이다

 

 

아까 봤던 구조랑 같다

DataConfigure 프로바이더는 다른파일에 있다

 

다른파일에 있으면 어째야한다고?

 

불러와야지

 

 

이제 버그는 없어졌다

 

이렇게 하면 프로바이더 설정 기본이 끝난다

 

프로바이더는 기본적으로 사용하기 전

 

시스템에서 등록작업이 필요하다

 

이때 필요한게 MultiProvider라는 기능인데

 

이 부분은 runApp에 작성된다

 

 

runApp을 비워두고 작업을 진행한다

 

이때 저장은 하지 말자

 

저장하면 위에 Unused 경고뜬거 지워져서 다시 적어야한다

 

 

 

runApp안에 MultiProvider를 하나 만든다

 

이때 오류에 defined 에러가 있을텐데

 

상단에 패키지를 하나 불러와준다

 

 

이제 경고 메세지가 변했다

 

MultiProvider는 안에 꼭 채워야 할 내용이 있는데

 

프로바이더를 추가해준다

 

자 우리는 여기서 빨간 에러메세지가 사라진것을 확인할 수 있다

 

이로써 프로바이더를 사용하기 위한

전제 조건은 완성이 되었다

 

 

갑자기 뭐가 많아졌다고 놀래지 말아라

 

그저 안에 ChangeNotifierProvider 가 추가됐을 뿐이다

 

저 양식은 그대로를 따라가고 dataConfigure는 위에서 만든 변수 이름이다

 

이렇게 함으로써 우리는 ChangeNotifierProvider 즉 화면 변화를 감지할 수 있게 됐다

 

이제 dataConfigure 에 데이터가 변화하면 화면이 알아서 갱신해줄 것이다

 

그러면 이제 프로바이더 설정도 끝났고 싱글톤 설정도 끝났는데

 

문제가 있다

 

homePage()위젯이랑 연결 안했다

 

 

멀티 프로바이더 안에 child 즉 자식을 하나 만들어준다

 

이는 기본 속성이므로 지정이 가능하다

 

근데 여기에 마테리얼 앱 , 조상도 만들고 자식도 만들고 할 수가 없다

 

그래서 위젯을 하나 main.dart에 만든다

 

 

이렇게 Stateless 위젯으로 하나 만들고 child에 연결해준다

 

 

자 이제 경고도 없어졌겠다

한번 리스타트 해보자

 

패키지 설치 후 안정성을 위해

 

Stop main.dart 에서 재 시작을 권장한다

 

 

 

화면이 우리가 전에 만든 그게 아니다

 

어떻게 해야할까

 

연결하면 되는거지

 

기존에

 

부모인

MaterialApp을 지정하고 home을 만들어 지정했던걸 기억해야만 한다

 

 

일단 조상을 만들고

 

거기에 home을 만들어준다

 

 

이제 HomePage를 연결하자

 

 

 

이제 화면에

 

 

우리가 아까 만든 페이지가 떠 있는걸 볼 수 있다

 

여기까지 에러가 있으면

 

댓글을 남기길 바라며

 

간단하게 화면에 숫자를 바꿔보도록 하자

 

 

아까 만든 프로바이더로 와준다

 

dataConfigure로 오면된다

 

 

이제 여기에 변수를 하나 만든다

 

이 변수 앞에는 _가 붙어있는데 

_ 가 붙은 변수는 DataConfigure에서만 쓸 수 있다

 

왜 이런걸 만드냐면

혹시라도 변수끼리 이름이 같거나 했을때

 

충돌을 방지하고 유지보수가 쉽게 하기 위함이다

 

그러면 다른파일에서 못꺼내쓰지 않냐고?

 

당연하다 _가 있어서 못쓴다

 

그러면 쓸 수 있게 해야하는데 해당 방법을 소개한다

 

 

이렇게 get을 사용해 setter를 만들어주면 다른파일에서 사용이 가능하다

 

그냥 int upStage = 0; 하면 안되냐고?

 

된다

 

본인 편한방식대로 하도록 하자

 

이제 값을 증가시켜줄 함수하나를 만든다

 

 

해당 함수를 살짝 설명해보자면

 

void기 때문에 반환은 없다

 

upStage는 실행되면

 

_upStage += 1; 코드를 실행시킨다

 

해당 내용은 풀어보면

 

_upStage = _upStage + 1 ; 와 같다

 

즉 기존 _upStage에 1을 계속 더하란 얘기다

 

한번 함수가 실행될때마다 숫자가 증가 할 텐데

 

그러면 실제로 증가하는지 봐야하는데

 

콘솔에서 표시하지 말고 바로 화면으로 가도록 하자

 

홈페이지 파일로 넘어와서

 

상단에

 

 Widget build(BuildContext context)

 

찾도록 하자

 

 

내가 프로바이더를 다른 파일에서 쓰기 위해선

양식을 맞춰서 사용해야 한다

 

 

프로바이더를 사용하기 위해선

기본적으로 context라는게 있어야하고

그게 있는 위치에서 프로바이더를 불러와야한다

 

근데 또 오류가 있다

 

패키지 두개를 불러와야 한다

 

지금 프로바이더 기능을 사용하려면

 

main.dart 에서 불러온

프로바이더 패키지를 추가하고

 

dataConfigure 의 기능을 사용할 것이기 때문에 해당 파일도 불러와야한다

 

 

 

main.dart에서 복사해왔다

 

이제 오류가 없는걸 볼 수 있다

 

저기 노란색으로 isn't used 경고가 있는데

 

이건 안쓰니까 지우란 얘기다

 

근데 우린 써줄거니까 무시하도록 한다

 

 

아까 만들어둔 _upStage 변수를 사용하기 위해선 get으로 연결해둔

getUpStage 변수를 사용해야한다

 

따라서

. 을 기준으로

앞은 불러올 주소 . 뒤는 불러올 내용 이렇게 보면 된다

 

dataConfigure라는 변수는 아까 만든 프로바이더를 담고 있고

 

그 안에서 getUpStage를 가져오란 얘기다

 

근데 오류가 있다

 

왜냐면 

 

text라는 위젯은 String 즉 , 문자열만 지원하기 때문이다

 

그럼 못쓰냐고? 다 방법이 있다

 

int는 숫자이기 때문에 문자열로 변환만 해주면 된다

 

.toString을 뒤에 붙여준다

 

 

근데 또 오류가 있다

 

오류를 읽어보면 

constant 관련 오류인데

 

이건 데이터가 변화할 수 있는 변수를 텍스트에 지정하면서

 

데이터를 변화시킬 수 없는 const 키워드가 포함되었을때 경고가 뜬다

 

그냥 const 지우면 된다

 

 

이제 버그가 없다

 

화면을 한번 확인하면

 

 

0 이 화면에 뜬걸 볼 수 있다

 

여기서 왜 0 으로 뜨냐면

 

우리는 앞서 _upStage 변수를 0 으로 초기화 했기 때문이다

 

이제 아까 만든 upStage 함수만 버튼에 연결하면 된다

 

강화버튼을 찾아보자

 

 

여기 onPressed 에 함수를 연결하도록 한다

 

 

이제 버튼을 눌러보자

 

아 홈페이지 파일도 저장하는거 잊지말자

 

강화 버튼을 누르면 화면은

 

 

변화가 없다

 

리스타트나 핫 리로드를 눌러보자

 

바뀌긴한다

 

근데 뭐임?

왜 바로 안바뀜?

 

아깐 바뀐다매

사기 포스팅인가

 

아니다

dataConfigure로 넘어와서 함수를 한번 살펴보자

 

 

변수 값은 확실히 증가시키고 있다

 

다만 데이터가 바뀌었으니까 화면보고 갱신하라고 하는 코드가 빠져있다

 

그럼 왜 이렇게 알려줬냐고?

 

그게 뭐 하는건지 모르고 쓰라니까 쓰면

무슨의미가 있는가

 

알아야 쓰는거지

 

추가할 건 별거 없다

 

notifyListeners();

하나만 추가하면 끝난다

 

 

이제 버튼을 다시 눌러보자

 

 

숫자가 변하는걸 볼 수 있다.

 

이번 시간에는 과제가 있다

 

숫자를 다시 0으로 만드는 함수를 하나 만들고 리셋버튼에 연결해오자

 

답은 다음시간에

 

 

끝내며

 

오늘 처음 외부 패키지를 설치했다

아마 따라오느라 힘들었을 수도 있을거라 생각한다

 

참 많은 패키지를 설치하면서 사용하게 될테니

잘 익혀두길 바란다

2023-10-25 03:54:09

$$ 이 포스팅은 노 베이스를 대상으로 하지 않는다 $$

$$ 노 베이스는 다른 시리즈를 먼저 해보고 오도록 하자 $$

 

이번에는

가챠게임을 만들어보자

 

가챠 란

:: 일정 확률로 아이템을 얻는 것 ::

 

이렇게 정의하고 가자

 

 

그러면 게임이니까

핵심적인 부분을 점검하고 가야한다

 

Q 게임은 어떤 방식으로 진행시킬지?

 

게임을 만들고자 한다면

게임이 어떻게 진행되고 어떤식으로 작동할지에 대해

 

많은 고민을 해야만한다

그런데 우리는 그런 고민하기가 쉽지가 않다

 

왜?

 

게임은 해봤어도

게임은 안만들어봤으니까

 

노 베이스 코린이가 게임을 만든다?

 

책보고 가위바위보 만들어봤으면 잘 만든거 아닐까?

 

더 만들어봤다고?

잘했다

 

우리는 다음과 같은 방법으로 게임을 구현할 것이다

 

1. 사용자는 화면에 버튼을 하나 누를 수 있다

2. 사용자는 버튼을 누르면 일정 확률로 다음 레벨로 갈 수 있다

3. 사용자는 일정 확률로 스테이지가 하락 할 수 있다

4. 각 성공 / 유지 / 하락 확률을 화면에 표시한다

5. 스테이지가 올라갈 수록 스테이지 숫자 색을 변경한다

6. 리셋 버튼을 제공해 게임을 초기화 할 수 있다

 

뭐가 많다

하나씩 하다보면 금방 하겠지

난 시리즈를 길게 쓸 수 있어서 좋다

 

주제 찾는게 여간 어려운게 아니다

 

이번에는 기초 작업을 시작한다

 

1. 외부 패키지 설치

2. 기초 UI 작업

 

원래 시작은 쉽고 짧게 가야한다

 

왜냐고?

처음부터 뭐 많이 보여주면 지레겁먹고 나가니까

 

 

 

플러터를 시작하면 기본 UI가 나온다

또 똑같다 다 지워버리고 시작하자

 

 

이제 기본 ui를 만들어줄건데

오늘은 파일을 분리해보도록 한다

 

어떻게 분리하냐고?

천천히 따라오면 다 할 수 있다

 

좌측에 보면

lib 파일에 main.dart 가 보일것이다

우리가 지금 작업하고 있는 파일인데

 

여기에 파일을 추가하도록 한다

 

플러터는 기본적으로 다트 언어를 기반으로 하기 때문에

dart 확장자를 사용한다

 

파일을 하나 만들자

 

파일명은

 

homePage.dart

 

파일 생성은

 

 

lib 파일이 선택된 상태로

여기서 New File을 선택한다

 

파일을 선택하고

 

작성해준다

 

 

빈 파일이 만들어 졌고

우리는 이 파일에 게임의 핵심 요소 UI들을 배치할 것이다

 

 

stf를 작성하면

자동으로 Stateful 위젯을 만들 수 있게 된다

 

기존에 이미 Stateful 위젯과 Stateless 위젯의 차이를 설명했는데

 

간단하게 다시 짚고 넘어가면

 

Stateful Stateless
데이터에 변화가 있으면 화면을 새롭게 만든다 데이터에 변화가 있어도 화면을 새롭게 만들지 않는다

 

이번에 만들 화면은 스테이지가 변하면 화면의 글씨같은게 변하니까

Stateful 위젯으로 만든다

 

그러면 Stateless 위젯은 어디에 쓰냐고?

 

카톡을 생각해보자

 

상단에 있는 검색이라던지 친구추가라던지

해당 버튼들이 데이터에 큰 변화가 있던가?

 

아니다

 

그런 상황에 쓴다

 

앱 이름이라던지

뭐 그런거

 

그러면 stateless 위젯은

데이터 변화에 대응할 수 없냐?

 

그건 또 아니다

 

대응하는 법은 나중에 설명하도록 한다

 

자, 일단 stateful 위젯을 기본으로 만들고

 

 

이름을 지정한다

 

이름은 가볍게

HomePage로 지정한다

 

 

이렇게 완성되었다면 이제

저장을 한다

 

혹시해서 말해주는건데

 

저거 하나씩 다 바꿀필요 없다

 

 

class HomePage extends StatefulWidget 에서

HomePage를 더블클릭하면 선택 상태가 되는데

거기서 F2를 누르면 이름 바꾸는 화면이 스크린샷처럼 나온다

 

거기 입력하면 전부 다 바뀐다

 

본론으로 돌아와서

이렇게 화면 만들었으면 화면 연결해야하지 않나?

 

연결하도록 해준다

이제 runApp에 작성해야하는데

 

항상 얘기 했던것처럼

조상이 있어야 내가 있다

 

시조를 만들어준다

 

다시 얘기하지만

플러터에서 시조는 MaerialApp 이다

 

 

runApp 안에 마테리얼을 작성해준다

const는 작성 안해도 된다

알아서 넣어줄테니

 

설정을 모르겠다면

플러터 기본 세팅 포스팅을 참고하길 바란다

 

home : home이라 적으면

 

 

아까 만들어둔 위젯을 자동으로 가져온다

엔터를 눌러주자

 

 

자동으로 패키지도 import 해주고 위젯도 넣어준다

 

이게 편의성이지

 

이제 저장하고 핫리로드 혹은 리스타트하면

 

 

정상적으로 화면이 로딩됐다

 

그러면 이제

 

화면을 좀 만들어봐야지?

 

이 상태로 뭘 할 수 있을까

 

 

홈페이지 위젯에서 작업을 시작하자

 

 

scaffold 라는 현조를 넣고 그 안에 자식으로 body 를 설정한다

 

이렇게 설정하면

 

 

다음과 같은 화면이 만들어진다

 

이번에는 appBar BottomNavigator 는 사용하지 않는다

 

 

ui 의 기본구조를 작성하자

 

/*

기본 구조에 대해서는 설명하지 않는다

기본 구조를 설정하는게 궁금하다면

다크모드 만들기 포스팅부터 보길 바란다

*/

 

 

그래도 설명해주는게 안섭섭하겠지?

 

일단 컨테이너를 하나 만든다

 

우리가 만들 모든 내용은 이 안에 담길 예정이다

 

이제 세로로 위젯들을 배치하기 위해

 

Column을 배치한다

 

 

Column 안에 내용물을 배치할건데

 

1. 스테이지가 표시될 텍스트 하나

2. 성공확률 , 하락활률 , 유지확률을 보여줄 텍스트 3개

3. 강화 버튼 , 리셋버튼

 

이런 내용들을 배치할것이다

 

1번과 3번은 Column에 그냥 세로로 배치할것이고

 

2번은 가로로 먼저 배치 할것이다

 

 

앞서 설명한대로

1. 스테이지 텍스트를 배치

2. 가로(Row)로 확률 텍스트 배치

3. 가로(Row)로 텍스트버튼 하나 배치

 

이렇게 배치했다

 

그랬을때 화면은

 

 

이런식으로 엉망진창인걸 볼 수 있는데

 

걱정마라 화면 배치는 바꾸면 그만이다

 

 

맨 위에 있는 컬럼에 정렬을 넣어주었다

 

Column 에서 mainAxisAlignment 는 세로 정렬을 의미한다

뒤에 적힌 내용은 그냥 가운데 정렬하라는 얘기다

 

이렇게 하면

 

 

이렇게 가운데로 내려온것을 볼 수 있다

 

그 다음 각 Row 에도 옵션을 적용한다

 

 

앞서 Column 에서 mainAxisAlignment 세로 정렬을 의미한다고 했다

 

반대로 Row 에서 mainAxisAlignment 가로 정렬을 의미한다

 

따라서 화면에는

 

 

전부 가운데로 온 것을 볼 수 있다

 

이제 조금 더 옵션을 추가해보도록 하자

 

1. 텍스트 크기 변경

2. 내용 채우기

3. 버튼 스타일 변경

4. 각 요소 사이에 빈 공간 만들기

 

 

스테이지 텍스트에 옵션을 추가했다

Style을 지정해 Size를 지정해주었고 fontWeight 는 폰트 굵기다

왜 저렇게 쓰는지는 묻지말자

 

나도 잘 모른다

 

 

 

이제 글자가 좀 커지고 굵어졌다

나머지도 작업하도록 한다

 

 

텍스트를 추가했다

 

Row 안에 Row 를 또 썼냐면

각 내용물들을 관리하기 쉽도록 묶은것 이다

 

중간중간 SizedBox 는 확률 표시 사이에 여백을 주기 위해 사용했다

 

 

이제 확률도 화면에 표시했으니

 

강화버튼 / 리셋버튼만 만들면된다

 

근데 버튼이 좀 심심해보이므로

 

버튼을 다르게 디자인해본다

 

기존에는 textButton 을 사용했는데 

ElevatedButton 을 사용한다

 

 

강화버튼 리셋버튼을 하나씩 만들었고 사이를 띄워주었다

 

 

뭔가 구색은 갖춘것 같다

 

다만 내용물들이 붙어 있어서 별로 같다

 

이 내용물들을 서로 떨어뜨려줄건데

 

sizedBox 를 사용해도 되지만

 

이번에는 padding 을 사용해보도록 한다

 

플러터에는 여백을 지정하는 방식이 여러가지 있지만

 

SizedBox width height 를 조절해 지정하거나

margin Padding 을 이용해 조정한다

 

두개를 간단하게 비교한 내용을 밑에서 기술한다

 

Margin Padding
바깥 여백 내부 여백

 

보통 전체적인 틀을 지정하거나 할때는 Margin

내용물을 지정할땐 Padding 을 사용한다

 

우리는 padding 을 지정한다

 

 

버튼의 Row 을 클릭하고 좌측에 전구를 누르면

빠르게 기능을 추가할 수 있는 메뉴가 나온다

 

여기서 Padding 을 선택한다

 

 

가볍게 설명하자면

내부 여백을 지정하는데

 

all(8.0) 상 하 좌 우를 8픽셀씩 뗀다

 

이번에 우리는 전체 여백을 10으로 지정해본다

8.0을 10으로 바꾸면된다

 

 

조금? 떨어졌다

 

이제 확률도 똑같이 지정해준다

 

 

 

확률을 감싸고 있는 제일 큰 Row 에 패딩을 똑같이 설정한다

 

이번에는 옵션을 바꾸도록 한다

 

 

 

fromLTRB 는 상하좌우를 설정할 수 있다

LTRB 이 순서대로

왼쪽 , 상단 , 오른쪽 , 하단 순서다

 

필자는 상단과 하단에 30씩 여백을 주었다

 

 

좀 떨어진 것 같다

이제 다음 시간부터 여기에 기능들을 연결하고 구현하도록 해보겠다

 

 

끝내며

아마 처음 따라하면 어려울 수도 있다

해당 포스트 말고 다크모드 개발이라던지 텍스트컨트롤 부터 보고 오길 바란다

이제 시작이다 힘내보자

2023-10-13 02:15:48

시리즈 목록

 

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 1 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 2 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 3 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 4 현재 포스트

 


 

저번까지 우리는

String 즉 문자에 대한 것들을 컨트롤하고 다뤄보았다

 

랜덤 기능도 만들어보고 구현을 해봤지만

 

숫자를 계산해서 문자로 표현하는건 안해봤다

 

예를들어

 

tesTInteger1변수에는 1이 들어있고

tesTInteger2변수에는 2가 들어있다고 가정해보자

 

여기서 두 변수는 모두 String 이고

 

계산을 위해

 

testTInteger1 + tesTInteger2를 실행하면

12가 출력될 것이다

 

한번 가볍게 테스트 해보도록 하자

 

 

저번에 구현한 기능은 여기까지다

이제 버튼을 하나 추가하고

결과를 출력할 수 있는 함수를 만들자

 

버튼 추가하는 코드는 안 알려줘도 이제 잘 하겠지만?

그래도 다시한번 보여준다

 

 

아이콘버튼 대신 ElevatedButton으로 만들어보았다

 

 

화면엔 다음과 같이 표시될 것이다

 

 

그리고 앞서 얘기한 변수 두개를 만들어준다

이름은 달라도 상관없지만

명심하자

 

i , j , a , k , e , x 이런 변수이름은 쓰지말아라

 

절대로

무슨일이 있어도

 

그 다음 계산할 수 있는 함수를 하나 만들어준다

 

 

testTextCal 이라는 함수를 하나 만들었다

해당 함수는 void로 반환하는게 없어 return 을 사용하지 않았다

 

함수에 대해서는 이전 포스팅들에서 계속 설명하고 있으므로 이번엔 생략하도록 한다

 

함수를 조금 설명해주자면

 

String tesTResult = ''; 는 결과값을 담을 변수다

 

testTResult = tesTInteger1 + tesTInteger2;

 

이건

testTResult 라는 변수에

tesTInteger1 tesTInteger2를 합친다음

집어넣으라는 얘기다

 

print(tesTResult);

필자가 작성한 강의에서는 처음 등장한 명령어인데

콘솔에 tesTResult에 담긴 내용을 출력하라는 명령어다

 

그러면 콘솔은 어디있냐고?

 

 

 

VSCODE 밑을 보면 Debug ConSole이 있을것이다

 

이게 콘솔이다

 

이제 함수도 만들었겠다

 

버튼이랑 연결하도록 하자

 

 

앞서 만들어둔 함수를 버튼에 연결하고 버튼을 누르면

 

 

 

이런 결과를 볼 수 있다

 

분명 1 + 23이 나와야 하는데

 

저기선 12가 붙어서 나왔다

 

그 이유는

 

String은 실제로 계산을 하지 않고

 

+ 가 있다면

+를 기준으로 좌측에 있는 데이터와 우측에 있는 데이터를

 

하나로 합쳐버린다

 

이건 우리가 바란게 아니므로

 

3 이 출력되도록 만들어야하는데

 

글자 상태에서는 할 수 없다

 

변수의 형태들을 int로 바꿔주자

 

 

 

그렇게 하고 함수를 보면

 

 

뭔가 문제가 생겼다

 

오류를 잘 읽어보면

 

A value of type int can't be assigned to a varialbe of type String

 

이라고 적혀있다

 

한글로 번역하면

 

Int 타입 즉 숫자String 문자가 될 수 없다고 되어있다

 

우리가 이해하기에

 

공책에 숫자 1 쓴거랑 문자로 1 쓴거랑

전혀 다를게 없지만

 

컴퓨터는 저 두개를 다르게 인식한다

 

쉽게 얘기하면

 

Int 는 열쇠고

String은 도어락인데

 

열쇠로 도어락을 열려고 하는 것이다

 

그러면 어떻게 하면 되느냐

 

함수 구조를 바꿔보자

 

 

여기서

TesTResult 변수는 String 이므로 일단 놔둔다

그리고 기존에 계산식을 조금 분리해보자

 

 

int로 계산값을 저장할 변수를 만들고

 

 

해당 함수를 tesTResult에 넣어준다

 

그러면 동일한 오류가 발생하는것을 볼 수 있다

 

그래서 달라진게 없다고?

 

조금만 기다려라

 

 

 

이렇게 변수 뒤에

.toString()을 달아주면 오류가 해결된다

 

여기서 toString이란

 

타입 (Int라던지 String이라던지)이 달라 사용할 수 없는 부분을

해소하고자 만든 간이 함수라고 보면 된다

 

자세하게 설명하면 포스팅 4개는 더 해야하므로 간단하게 사용한다

 

비유하자면

 

int가 열쇠 String이 도어락인데

 

열쇠를 뺏고 도어락 비밀번호를 알려준거라고 보면 된다

 

이해를 돕기 위해 한줄 요약하면

 

타입이 맞지 않는 testIntResult를 toString을 통해 타입이 맞도록 변형해준것이다

 

이제 실행해보면

 

 

정상적으로 3이 출력되는걸 볼 수 있다

 

자 그러면

 

콘솔에만 출력하고 끝낼건가?

 

화면에도 출력해야지

 

앞서 우리는

 

 

텍스트 위젯을 통해

 

화면에 텍스트를 표시했고

 

text변수의 내용을 이리저리 바꾸는 함수들도 만들어놨다

 

 

이런식으로 말이다

 

그러면

 

 

 

이 함수를 변형하면 되는 문제 아닌가?

 

changeText3의 내용을 그대로 긁어와서 일단 아래 작성한다

 

 

그 다음 print() 위젯에 있는 tesTResult를 옮겨주기만 하면 된다

 

 

이렇게 하면 문제없이 실행될 수 있다

 

그래도 구조를 한번 더 살펴보자면

 

 

도어락에 열쇠는 못 꽂는 것처럼

 

text 변수는 String 형태로 만들어서 int는 들어갈 수 없다

 

그래서 우리는

 

 

이렇게 toString을 통해 testIntResult라는 변수의 형태를 String으로 바꿔주었다

 

따라서 타입에 대한 오류가 생기지 않아 오류가 발생하지 않고

 

버튼을 눌러 실행했을때

 

 

이렇게 화면에 숫자가 표시되는걸 볼 수 있다

 

다시 알아두자

 

화면에 표시된건 int타입의 숫자가 아니라 String이 된 3 이라는 문자다

 

 

끝내며

 

항상 프로그래밍을 할때 타입이 맞지 않아 오류가 많이 발생한다

 

범위를 넘어간다던지 들어가선 안될게 들어간다던지

 

항상 프로그래머는 이런 부분을 점검하고 체크해야한다

 

그리고 변수는 절대 i , j , x , t , a , d  이런거 쓰지마라

 

초기 습관이 나중을 결정한다

 

 

텍스트를 컨트롤하는 기본기는 여기서 마무리하도록 한다

 

끝까지 따라오느라 고생했다는 말을 전하며

 

다음 강의는

 

게임의 랜덤 성공 확률을 구현해보는것으로 시작해보자

 

난이도가 있을 수 있다

 

포기 안하면 구현할 수 있다

 

걱정마라 몇번이고 몇번이고 설명해주겠다

 


 

시리즈 목록

 

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 1 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 2 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 3 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 4 현재 포스트

2023-10-07 01:44:20

시리즈 목록

 

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 1 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 2 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 3 현재포스트

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 4 바로가기


 

저번 시간에 텍스트를 바꾸는 기능까지 구현했다

 

이어서 색상을 글자의 색상을 랜덤으로 변경하는 버튼도 구현해보자

 

 

저번에 만들어둔 어플리케이션이다

 

여기에 이어서 작성한다

 

일단 색상을 바꿔줄 버튼을 하나 추가하도록 한다

 

 

Row 밑에 버튼을 하나 만들어주자

이번에는 아이콘 버튼을 만들어보도록 하자

 

 

아이콘 버튼을 만든다

구조는 ElevatedButton과 유사하다

 

적용하면

 

 

이렇게 버튼이 추가된걸 볼 수 있는데

 

버튼이 또 붙어있는 느낌이라 석연치가 않다

 

좀 떨어뜨려주자

 

이번에도 Sizedbox를 사용한다

 

 

이렇게 추가하고 나면

 

 

이렇게 떨어진 것을 볼 수 있다

 

이제 텍스트 색상의 변경을 위해

속성을 좀 지정해두자

 

 

 

우리는 앞서 텍스트에 스타일을 지정해두었다

 

기억이 안난다면 나와 비슷한 코드를 찾아보길 바란다

 

이 코드에 color: 옵션을 지정하면 글자색을 지정할 수 있다

 

위 처럼 색상을 지정해보자

 

 

텍스트가 빨간색으로 변경된것을 알 수 있다

 

 

다른 글자를 눌러도 색상은 빨간색으로 지정되어있다

 

이제 색상을 랜덤으로 바꿀 수 있도록 함수를 만들어보자

 

랜덤한 값을 만들어낼때는

 

특정한 패키지가 필요하다

 

최 상단에

 

 

import 'dart:math';

 

이 패키지를 import 시켜준다

 

여기서 처음 import를 하게 되는데

 

import다른 기능들이 담긴 파일을 불러와 해당 파일의

함수 또는 기능들을 이용하기 위한 선 작업이다

 

이번에는 dart 패키지의 math 라이브러리가 필요하므로

 

저렇게 불러와준다

 

옆에 Unused 경고는 안쓰고 있는 패키지는 지우라고 뜨는건데

 

어차피 쓰면서 없어질 경고이기 때문에 무시한다

 

다만 이때 저장을 하면 vscode가 알아서 안쓰는 패키지를 지워버리므로

 

저장하지 않고

 

함수를 작성한 다음 저장하도록 한다

 

 

일단 변수를 하나 만들고 색상을 지정해준다

 

플러터는 색상도 변수로 만들 수 있다

 

변수를 분해하자면

 

Color : 변수의 형태

textColor : 변수 이름

Colors.black : 검은색

 

이로써 textColor 변수는 검은색을 가지게 되었다

 

그러면 이게 실제로 적용되는지 한번 보자

 

우리는 지금 글자를 빨간색으로 설정했는데

 

text의 속성중 color에 빨간색 대신 textColor 변수를 지정한다

 

 

Invalid constant value 오류가 생겼다

 

해당 오류는 부모에 생긴 const 때문이라고 전에 말한적 있다

 

현재 color의 부모는 TextStyle이므로 앞에 적힌 const를 삭제해준다

 

또 까먹었을 수 있는 사람을 위해 간단하게 const를 설명해주면

 

변하지 않는 데이터들은 const를 사용해 감싸주도록 되어있다

 

하지만 현재 color는 계속 변화할것이므로 const를 사용할 수 없다

 

 

이제 화면을 보자

 

글자색이 검은색으로 변한것을 확인할 수 있다

 

 

자 이제 모든 준비는 끝났다

 

이제 해야할 작업은 크게 두가지로 나눌 수 있다

 

1. 색상을 랜덤으로 바꿔줄 함수 생성

2. 버튼에 함수 연결

 

앞서 import 시킨 dart:math 라이브러리를 사용할 때가 되었다

 

근데 최 상단으로 올라가보면

 

패키지 import가 삭제되었을 수 있다

 

없으면 다시 작성해주도록 하자

 

그 다음 함수를 만든다

 

 

랜덤한 색상을 가져오는 함수를 하나 만들었다

 

해당 함수를 설명해보자면

 

해당 함수는 랜덤한 색상을 만들어내는 함수로

 

반환 형태는 Color로 색상을 반환한다

 

getRandomColor() 는 함수의 이름이다

 

return Color() 는 괄호 안에 작성된 내용을 처리하고 반환한다는 뜻이다

 

Random().nextDouble() dart:math 에 포함된 메서드로

0.0 ~ 1.0 사이의 랜덤한 실수를 반환한다

 

여기서 처음보는 Double이 나오는데

 

플러터에서 숫자를 처리할때는

 

정수와 실수가 대표적이다

 

정수 (Int)  실수 (Double) 
음수를 포함한 소숫점 없는 숫자 음수를 포함한 소숫점 있는 숫자

 

이렇게만 알고 가자

 

어차피 개발하면서 정말 많이 마주할것이기 때문에

 

자세한건 쓰는법을 익히고 이론을 배워가는 형태로 알아가기를 바란다

 

 

따라서 

Random().nextDouble(): 는

 

0.1 ~ 1.0 사이의 랜덤한 실수를 반환하는 코드라고 생각하면 된다

 

0xFFFFFF

 

16진수로 표현된 흰색을 뜻한다

 

보통 RGB 라고 많이 부르는데

 

R : Red

G : Green 

B : Blue

 

세가지로 나뉜다

 

이 값들은 255까지 가질 수 있는데

 

너무 복잡한 얘기니 생략하고

 

앞서 0.1 ~ 1.0 사이 실수값을 얻은 다음 흰색에 곱해 새로운 색을 만들어낸다

 

.toInt(): 는 실수값을 정수로 변환하는 일을 한다

 

쉽게 얘기해 1.01로 변환하는것이다

 

결과적으로

 

0부터 0xFFFFFF 사이의 랜덤한 정수 값이 생성되게 된다

 

withOpacity(1.0): 이건 투명도 설정인데

1.0 은 완전 불투명을 뜻한다

 

사실 생략해도 상관없다

 

 

요약하자면

 

 0부터 0xFFFFFF 사이의 랜덤한 정수를 이용해 랜덤한 색상을 뽑아낸다

 

 

랜덤한 색상을 만들었으면 뭐 할 수 있겠나

 

실제 적용을 해봐야지

 

적용하는 함수도 만들어준다

 

이때 화면이 갱신되어야 색이 변하니까

setState를 사용해준다

 

함수를 간단하게 설명하자면

 

changeTextColor는 아무것도 반환하지 않는 함수로

textColorgetRandomColor 함수에서 얻은 랜덤한 색상을 집어넣는다

 

그리고 setState로 화면을 갱신한다

 

우리는 앞서

 

 

text의 색상을 동적으로 바꿀 수 있게 변수를 연결해놨다

 

이제 저 함수를 버튼에 연결해 실행하면 변수의 값이 달라질것이다

 

 

이제 버튼에 연결했다

 

작동하는 로직을 잠깐 설명하자면

 

버튼을 눌렀을때  onPressed가 작동해

changeTextColor 함수가 실행된다

 

해당 함수는

 

getRandomColor 함수를 실행하고

 

getRandomColor 함수는 랜덤한 색상을 반환한다

 

여기서 반환된 랜덤한 색상은 textColor 변수에 대입되게 되며

 

최종적으로

 

text Style 속성에 지정된 Color 옵션에 textColor 값이 변하게 되어 글자색이 변한다

 

마지막으로 setState를 통해 화면을 갱신해준다

 

 

 

이제 아까 만들어둔 아이콘 버튼을 클릭하면 색상이 랜덤으로 변하는것을 볼 수 있다

 

물론 나랑 색은 다를거다

 

 

끝내며

 

오늘은 짧지만 복잡한 과정이 좀 있었다

 

차근차근 읽어보며 복습하기를 바란다

 

다음 포스팅에서 보도록 하자

 

벌써 기능을 4개나 만들었다

 

어마어마하지 않은가

 


시리즈 목록

 

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 1 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 2 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 3 현재포스트

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 4 바로가기

2023-10-06 17:04:59

 

시리즈 목록

 

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 1 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 2 현재 포스트

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 3 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 4 바로가기


 

오랜만이다

추석에 너무 많이 먹어 나태해져있었다

 

바로 본론으로 들어가보자

저번에 우리는

 

 

여기까지 만든것으로 기억하고 있다

 

오늘은

 

버튼을 만들고

버튼을 누르면 텍스트를 바꿔보는 시간을 가지도록 하겠다

 

그러면 일단 버튼부터 만들어야겠지?

 

 

저번에 만들었던 main.dart 에서 진행한다

body에 코드를 추가한다

 

 

 

잘 봐두자

Row 바깥에 작성했다

 

이렇게 작성하면

Column의 자식이 되어 Column의 영향을 받는다

 

다시말해

 

세로로 작성된다는 얘기다

 

그리고

Invalid Constant value 오류가 있는데

 

이건 해결하기 쉽다

 

 

Column 을 보면 앞에 const가 작성되어 있다

 

저걸 지우면 오류가 해결된다

 

 

 

Column 앞에 있는 const를 지우면

이렇게 여러줄에 경고가 뜨는것처럼 보이는데

 

상관없다

 

그럼 여기서 const에 대해 잠깐 공부하고 가자

 

/ 알 필요 없으면 다음으로 넘어가라 /

더보기

 

==START==

 

플러터에서 Const란 변하지 않는 데이터 같은거에 사용된다

 

예를 들어

 

변하지 않는 텍스트라던지

텍스트의 색상 , 사이즈 라던지

 

반대로 Const가 있으면 데이터는 변화할 수 없다

 

버튼은 누르면 무언가가 변화하거나 하는 액션이 취해지므로

 

Const가 있으면 데이터가 변화될 수 없어

 

앞에서 본

 

Invalid Constant value.

 

오류가 생기는것이다

 

==END==

 

 

이제 저장해주면

 

 

오류는 없어질 것이고

 

화면에는

 

 

이렇게 버튼이 하나 생길것이다

 

해당 버튼은

 

아무런 기능이 없으며

 

그냥 누를수만 있다

 

 

그러면 Row에 버튼을 옮겨볼까?

 

 · 안따라해도 된다 그냥 보기만해라

나중에 바꾸기 귀찮아진다 ·

 

 

 

코드는 이렇게 작성될 것이다.

 

이러면 화면은

 

 

위에 있는 Row의 자식이 되어

Row의 영향을 받은 바람에 두개가 가로로 세팅되어버렸다

 

기억해둬라

어떤 부모의 영향을 받냐에 따라 결과는 달라진다

 

그러면 원래대로 돌려두고

 

버튼을 좀 여러개 넣을 생각이니까

 

Row를 사용해 버튼을 안에 넣는다

 

 

Row를 하나 만들고

 

밑에 있는 ElevatedButton을 옮긴다

 

 

 

Row안에 정상적으로 넣었고

 

이때 화면은

 

 

다음과 같을 것이다

 

이제 버튼 몇개를 추가해주자

 

코드 복붙해도 상관없으니

 

미리 만들어둔 버튼을 사용한다

 

 

 

화면은

 

 

이렇게 될 것이다

 

근데 왼쪽에 몰려있어서 좀 불편하다

 

전에 

 

mainAxisAlignment 에 대해 공부한 적이 있다.

 

기억 안난다면

비 전공자도 텍스트컨트롤 할 수 있다 - 1

 

포스팅을 참고하길 바란다

 

무슨 옵션을 사용하던 상관은 없지만

 

필자는

 

 

 

MainAxisAlignment.spaceEvenly 옵션을 적용했다

 

 

기능 구현에는 아~무런 영향이 없으니

 

원하는 옵션을 적용하면 된다

 

그런데 텍스트랑 너무 붙어 있어서 맛이 안산다

좀 떨어지게 만들어보자

 

 

어디에 배치했는지 잘 보길 바란다

RowRow사이에 SizedBox를 배치했다

 

그리고 옵션으로 height100 줬는데

 

이러면 Row Row 사이에 높이 100만큼의 빈 공간이 생긴다

 

 

다만 주의하길 바란다

 

sizedbox를 너무 많이 남용해 UI를 배치하면

 

이빨 사이를 이쑤시개로 너무 쑤셔

 

사이가 벌어지고 다른 이빨에도 영향을 주는것처럼

 

모든 UI에 영향을 주게 되고

 

사용하는 핸드폰마다 화면 크기가 달라

 

원하는대로 구현이 안 될 가능성이 높다

 

 

지금은 간단하게 구현하는거니까

사용하도록 하지만

 

가급적이면 UI의 배치는

MarginPadding을 사용하기 바란다

 

 

버튼을 조금 더 디자인 해보자

 

 

버튼에 속성을 넣어봤다

텍스트는 속성을 지정할때

style 옵션과 TextStyle() 위젯을 사용했지만

 

버튼은 ButtonStyle() 위젯을 사용한다

 

코드를 설명해보자면

 

배경색을 변경하는 코드인데

버튼이 눌렸을때는 빨간색 기본 색은 파란색

 

이렇게 작성되어 있다

 

나머지 버튼도 비슷하게 만들어보길 바란다

 

해당 스타일 옵션은 텍스트파일로 첨부해두겠다

 

굳이 따라칠 이유가 없어 파일로 첨부하니

 

따라치고 싶으면 따라치고

 

아니면 복붙해서 써도 된다

 

버튼스타일링.txt
0.00MB

 

 

글자 디자인이 끝났으면

 

이제 텍스트를 바꿀 준비를 해보자

 

여기까지 오는데 참 오래걸렸다

 

오늘은 내용이 좀 길어도 끝까지 따라오길 바란다

 

여기서 끊으면 비빔면 한봉지 같은 느낌이 날게 뻔하다

 

 

상단에 텍스트 변수를 하나 만들자

 

예전에도 설명했지만 다시한 번 설명한다

 

String text = '가지고 놀 텍스트임';

 

여기서 String은 변수의 형태다

 

사람으로 치면

김 이 박 최 같은거라고 이해하면 편하다

 

text는 이름 같은 거다

길동이라던지 영희라던지

 

= 는 대입을 의미한다

 

비 전공자가 볼때 = 는 결과를 나타낸다고 생각할 수 있다

 

예를 들어 1 + 1 = 2 이런것처럼 말이다

 

근데 프로그래밍에서

 

= 는 대입을 뜻한다

 

1 + 1 = 2 이걸 프로그래밍으로 해석하면

 

말도 안되지만 1+1 에 2를 넣으란 얘기랑 같다

 

그럼 프로그래밍에서 같다는 어떻게 쓰냐고?

 

=를 두개 쓴다

 

==

 

정리

대입 같다
1 + 1 = 2 1 + 1 == 2

 

변수를 만들었으니까

 

이제 직접 사용해보자

 

 

 

이렇게 기존에 만들어둔

가지고 놀 텍스트임 을 변수 이름으로 바꿔주면 된다

 

기억하자

 

constant 오류가 발생하면 부모위젯에 있는 const를 지우면 해결된다

 

거슬러 올라가보니

Text 위젯의 부모는 Row 위젯으로 앞에 Const가 붙어있다

 

저걸 지우면 오류가 해결된다

 

 

이제 저장해보자

 

 

화면에 변화가 없다

오류가 생긴건가?

 

아니다 text 변수의 내용을 바꿔보자

 

 

그러나 변한게 없다

 

이제 

 

 

리 스타트 혹은 핫 리로드를 눌러보자

 

 

잘 변하는걸 확인할 수 있었다

 

왜 바꾸자마자 변하지 않느냐 라고 물어본다면

 

플러터는 기본적으로

 

데이터가 변화했다고 화면을 새로 만들어주지 않는다

 

이때는 Provider 라는 패키지 혹은 Rapid 혹은 SetState 등을 사용해

 

화면을 갱신하라고 알려줘야만 한다

 

왜 이런 구조를 가지게 됐느냐 라는 의문이 생기면

 

구글에 찾아보거나 플러터 개발자한테 물어보도록 하자

 

필자가 그냥 추측하건데

 

너무 많은 데이터가 계속 갱신되면

 

리소스를 너무 많이 잡아먹어서 그런게 아닐까? 한다

 

이제 텍스트도 변화시켰겠다

 

버튼을 누르면 바뀌게만 하면 끝인거다

 

일단 원래 형태로 텍스트를 바꿔놓도록 하자

 

 

지우고 할 필요 없다

CTRL + Z를 이용하자

 

막간상식

 

뭘 하던 뒤로가기 앞으로가기는 알아두길 바란다

 

뒤로가기 앞으로가기
CTRL + Z CTRL + Y

 

이제 텍스틀 바꿔줄 함수를 하나 만든다

 

함수에 대해 전에도 설명했지만

 

다시한번 설명하자면

 

 

특정 기능을 반복적으로 사용하거나

 

특정한 상황 혹은 다양한 상황에 사용하기 위해

 

코드를 뭉쳐놓고 작성해둔 모음집 같은거라 보면 된다

 

 

함수를 하나 만들었다

changeText1()

 

함수를 다시 설명하자면

 

void는 반환하는게 없을때 사용한다

 

여기서 반환이란

 

예를 들어 함수가 어떤 계산을 하고 값을 다른데 줘야할때 반환한다 라고 한다

 

예를 들어

 

1+1의 결과를 반환해야한다면 void를 적지 않는다

 

지금처럼 뭔가 계산하거나 다른 함수에 돌려줘야할게 없는 함수는

 

void를 사용해 반환할게 없다고 명시해주는게 좋다

 

 

changeText1 이건 함수 이름이다

 

함수 이름을

a , b , c , d 이런식으로 만들 수도 있는데

 

변수도 그렇고 함수도 그렇고 그렇게 만들지 마라

 

나중에 유지보수할때도 힘들고

 

오류를 수정할때도 힘들다

 

함수나 변수를 만들땐

 

알아볼 수 있게 만들자

 

혼자 연습할거니까 a , b , c , i ,. j  이런거 쓰겠다고?

 

써라 상관없다

 

다만 현업에서 저렇게 쓰면

 

내일은 침대로 출근할지도 모른다

 

앞서 내가 화면의 갱신을 요구하려면 setState 같은걸 써야한다고 했었다

 

다른 패키지 설치하는건 나중에 어차피 알려줄테니

 

지금은 플러터 기본 탑재기능인 SetState를 사용해준다

 

이때 명심할게 있다

 

전에도 설명했지만

 

플러터에는 Stateless 위젯과 Stateful 위젯이 있다

 

화면을 갱신하거나 해야한다면 Stateful 위젯을 사용하자

 

Stateless 위젯은 SetState를 사용할 수 없다

 

함수를 요악하면 이렇다

 

changeText1() 함수가 실행되면

 

text 변수의 내용을 '텍스트 바뀜?' 으로 대입해라

 

text 변수의 내용을 바꾸고 화면을 갱신하라고 플러터한테 명령하는거다

 

자 이제 함수를 만들었으니

 

버튼에 연결해보자

 

 

버튼에 보면 onPressed 가 있는데

 

이건 버튼이 눌렸을때 

: 뒤에 있는걸 실행하라는 얘기다

 

지금은 () {} 가 있는데

 

이걸 바꿔준다

 

 

아까 만들어둔

 

changeText1 을 

onPressed 에 작성한다

 

이러면 버튼이 눌렸을때 함수가 작동할것이다

 

 

텍스트가 바뀌는 것을 볼 수 있다

 

이제 함수를 복사하고 이름을 바꾼다음

 

다른 버튼 두개에도 연결해보자

 

코드 첨부는 안한다

 

그정도는 알아서 하자

 

 

끝내며

 

여기까지 따라왔다면 박수를 쳐주고 싶다

 

간단하게 생각해도 여간 어려운게 아니다

 

그리고 지금 만들어보는 기능들이 결국 어디에 쓰이냐고?

 

나중에 당신이 앱 만들때 하나의 기능으로 사용될 수도 있다

 

아님말고

 

다음 포스팅에서 보자

 


 

시리즈 목록

 

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 1 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 2 현재 포스트

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 3 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 4 바로가기

2023-09-24 00:16:20

시리즈 목록

 

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 1 현재포스트

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 2 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 3 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 4 바로가기


 

반갑다 나다

 

또 무슨 기깔난걸 만들어볼까 하다가 한통의 메일을 받았다

 

노 베이스 비전공자인데 변수나 함수같은게 이해가 안된다는 메일이었다

 

기초 지식을 익히고 싶다고 용기내서 메일을 보내신거같은데

 

학원을 가라 내 포스팅 기다리다가 환갑된다

 

하지만 조금은 응원하고 싶으니

 

이번엔 텍스트를 이용해서 변수를 이해하고 함수도 작성해보고 하는 시간을 가지도록 하겠다.

 

똑같이

 

 

메인 하나 만들어놓고 애뮬레이터 시작해서

 

이 화면까지는 띄워놓고 시작하자

 

 

오늘 해볼건 크게 3가지정도 만들어왔다

 

1. 버튼을 눌러서 텍스트 변경해보기

2. 버튼을 눌러서 텍스트 색상 랜덤으로 변경해보기

3. 버튼을 눌러서 계산 결과 화면에 표시해보기

 

1번부터 하자

 

샘플코드를 지우고

 

 

 

이렇게 만들어놓고 시작하자

 

앞서 다크모드 만들기에서 했던것처럼

 

MatrialApp을 설정하고

버튼을 이용해 화면을 갱신하기 때문에

 

Stateful 위젯으로 만들어보자

 

기억 안나면 가서 보고오자

 

 

기초 구조는 이렇게 작성해두고 시작한다.

 

이때 화면은

 

 

이런 상태여야 한다

 

이제 버튼을 만들어보자

 

저번에 했던것처럼 비슷하게 만들어준다

 

만드는 방법은

 

Scaffold → Container → Column → Row 이 순서대로 작성부터 해주면된다.

 

이렇게 보면 와닿지 않을 수 있는데

 

증조 - 현조 - 부모 - 자식

 

이 순서라고 기억해두자

 

 

다시 말하지만

 

부모가 없는데 자식이 있을 수 없다

 

 

순서대로 하나씩 만들자

한번에 다 만든거 보여주면 손을 놔버릴 것 같으니

 

Scaffold 안에 Container를 만들었다

 

이로써

 

현조 와 부모가 탄생했다

 

이때 화면은

 

 

코드를 보고 있는 우리의 뇌처럼

아주 새 하얗다

 

걱정하지말아라

순백의 도화지만큼 채우기 쉬운것도 없다

 

 

 

자식으로 Column을 추가해준다

 

이때 뜨는 파란색 경고는 일단 무시하자

 

저 경고가 왜 뜨는지 궁금하다면

 

다크모드 만들기 1을 참고하면 된다.

 

짧게 얘기해주자면

 

Container에는 여러가지 옵션이 존재하는데

옵션을 포함하지 않으면 Container를 사용하지 말라고 경고해준다

 

그러면 저 경고를 무시해도 되느냐?

 

ㅇㅇ 된다

 

저 경고가 거슬린다면 sizedbox를 사용해서 없앨 수 있다

 

sizedbox Container 의 차이는 아래 가볍게 기술해둔다

전문적인건 따로 찾아보도록 하자

근데 몰라도 서비스 잘 운영한다

 

Container SizedBox
다양한 옵션 가능 옵션이 몇개 없음

 

그리고 바로 버튼을 넣지 않고 Column을 배치한 이유는

 

정렬을 위함이다

 

여기서 첫번째 뉴비 분쇄기가 나온다

 

내가 원하는 위치에 글자 하나를 가져다 놓고 싶어도

고려해야할 사안들이 많아진다

 

바탕화면에서 아이콘 끌어다가 마음대로 두는것처럼 할 수가 없다

 

그렇게 할 수 있었으면

플러터 개발자 사는 방향으로 매일 3번씩 절할 수 있다 진심으로

 

근데 못하니까 위치를 조절할때

Container , SizedBox , Column , Row , ··· 등 뭐 많은 위젯을 이용해서

위치를 조절해야한다

 

다행이도 플러터에는

내가 화면을 어떻게 만들고 있는지 보여주는 고마운 툴이 있다

 

가끔 UI 배치하다가 개박살나면 하나씩 찾으면서 고치면된다

 

 

VSCODE를 사용하고 있다면

화면 우측이라던지 어딘가에 이렇게 생긴게 하나 떠있는걸 볼 수 있다

 

여기서 좌측 상단의 커서를 누르고 애뮬레이터의 화면을 누르면

 

 

이렇게 내가 선택한 위젯의 정보가 나온다

 

참고해서 UI 배치 잘 하길 바란다

 

본론으로 돌아와서

 

이제 Column 의 자식으로

Row를 넣어주도록 하자

 

특이하게 Column이나 Row

 

child가 아닌 

 

children 을 사용하는데

 

둘의 차이를 밑에서 설명한다

 

중요한 내용이니 그냥 보고 가라

 

이미 알아도 두번 봐라

 

child children
단 한개의 위젯만 배치 가능 복수의 위젯 배치 가능

 

여기서 말하는 위젯은

Column , Row , Container , SizedBox, Text , Img , Audio , Button

화면 위에 올라가는 모든것을 지칭한다

 

 

children을 사용하는 경우

1개도 배치가 가능하고 2개도 배치가 가능하고 3개도 배치가 가능하다

 

고속버스를 생각해보자

 

버스에 있는 수많은 좌석에

혼자 앉을 수도 있고 , 둘이 앉을 수 도 있고 , 다섯이 앉을 수 도 있다

 

child

 

좌석 한개 한개를 생각해보면된다

 

좌석 하나에 한명이 앉는게 원칙이다

 

이렇게 이해하면 편하다

 

그렇다고 child좌석이고 children고속버스

 

이렇게 이해하면 대참사난다

 

그러면 꼭 좌석에 혼자 앉으란 법이 있냐고 반문하는 사람이 있는데

 

개발 말고 다른 길을 찾는게 빠르지 않을까 진심으로 조언한다

 

이제 Column의 자식으로 Row을 넣고 텍스트를 넣는다.

 

Row도 마찬가지로 children을 사용한다

 

여기서 팁을 하나 제공하도록 하겠다

이게 뭐하는 위젯인지 모르겠다면 위젯 위에 마우스를 가져가보자

 

 

뭐가 많은데

MainAxisAlignment도 보이고

children도 보인다

 

간략하게 설명하자면

 

이 위젯이 뭐 하는건지 간단하게 정보를 주는거다

 

근데도 모르겠다?

 

윈도우 기준

컨트롤 + 스페이스바를 동시에 눌러보자

 

 

사용할 수 있는 옵션이라던지 속성이라던지 다 뜬다

 

이랬는데도 모르겠다?

 

인터넷에 검색하던지 ChatGPT나 BingAI나 물어보자

 

그런데도 모르겠다?

 

명심해두자 개발뿐만 아니라 많은 일자리가 있다

 

본론으로 돌아와서

 

Row를 추가하고 Text를 추가한다

 

Text 내용은 아무거나 상관없다

 

 

필자는 이렇게 만들어놨다

 

그러면 화면에

 

 

이렇게 뜨는걸 확인할 수 있다

근데 글자 위치가 정말 마음에 안든다

 

여기서 막간 상식으로 텍스트가 왼쪽 상단부터

출력되는 이유를 아래 첨부해둔다

궁금하면 열어보자

 

더보기

 

텍스트가 왼쪽 상단부터 출력되는 이유는

 

플러터는 왼쪽 상단부터 위젯이 생성되기 때문이다

 

원래 프로그래밍 언어는

 

Top - Down 방식을 채택하고 있는데

 

이는 위에서 아래로 읽어가면서 프로그램을 실행한다는 얘기다

 

쉽게 얘기하면

 

먼저 실행되어야 할건 상단에 배치하란 말이랑 같다

 

 

우선 글자위치를 옮기고

글자 크기를 변경해보도록 하자

 

글자 위치부터 변경할것이다.

 

이때는 Row의 속성과 Column의 속성을 모두 이용한다

 

속성에 대한 설명이 필요하다면

 

다크모드 만들기 1을 참고하자

 

찾아보는게 귀찮은 사람들을 위해

다음에 다시 한 번 설명할 수 있는 시간을 마련해보겠다

 

1. Column에 속성넣기

 

 

mainAxisAlignment: MainAxisAlignment.center, 속성을 넣어보자

 

간단히 말해주자면

Column에서 mainAxisAlignment 옵션은 세로 정렬을 얘기한다

 

코드를 풀어보면

Column에 배치된 위젯들을 세로 정렬을 하는데 위치를 가운데로 지정해라

 

이런뜻이다

 

 

 

텍스트가 아래로 내려왔다

하지만 아직도 가운데가 아니다

 

2. Row의 정렬을 이용한다

 

 

마찬가지로 mainAxisAlignment: MainAxisAlignment.center 옵션을 넣어준다

 

Row에서 mainAxisAlignment 는 가로 정렬을 의미한다

 

 

이제 텍스트가 정 중앙에 온것을 볼 수 있다

 

이 외에도 정렬하는 방법은 있는데

나는 선호하진 않는다

 

예를 들어 Center 위젯을 쓴다던지 하면

위치 옮기고 싶어서 RowColumn으로 속성넣고 지정했는데 꿈쩍 안할때도 많다

 

이런 일은 부모 위젯이 강제되어서 그렇지만

자유롭게 변경하지 못하는 문제가 있으므로 가급적이면 직접 지정하거나 하도록 하자

 

이제 텍스트 크기를 좀 키워보자

 

Text 위젯의 속성을 변경하면 된다

 

옵션은 textStyle 옵션을 사용하면 된다

 

 

styleText 위젯의 속성이고 속성을 지정하기 위해선 위와 같이 작성해야한다

 

왜 이렇게 해야하냐고 묻는다면

 

플러터 개발자한테 따지도록 하자

 

 

글자가 커졌다

만족스럽다

 

이제 버튼을 추가해야하는데

 

글이 너무 길어졌다

 

다음 포스팅에서 보도록 하자

 

 

끝내며

끝까지 읽었다면

또 끝까지 따라왔다면

당신이 도달한 끝에 행운이 깃들기를 바란다

이해 못했다고 주늑들지 말기를 바란다

그냥 무작정 따라 치다보면 눈에 익게 되고

그 다음에는 읽힌다

 


시리즈 목록

 

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 1 현재포스트

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 2 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 3 바로가기

[플러터] 비 전공자도 텍스트 컨트롤 할 수 있다 - 4 바로가기

2023-09-21 03:54:07

이 포스트는 시리즈편이다 3편까지 있으며

이게 3편이다.

 

그리고 나는 플러터의 플자도 모른다 싶으면 1부터 따라해보는것을 추천한다.

 

초보자도 다크모드 만들 수 있다 - 1 바로가기
초보자도 다크모드 만들 수 있다 - 2 바로가기
초보자도 다크모드 만들 수 있다 - 3 현재 포스트

 

 

 

저번에 여기까지 만들었다.

이제 버튼을 누르면 화면이 검게 또 한번 누르면 다시 하얗게 만들어지도록 만들자

 

 

변수를 하나 만들어준다

여기서 변수에 대한 설명을 첨부한다

필요하면 열어보길 바란다

 

더보기

=================================

  bool isDarkMode = false; // 다크모드가 활성화 되었는지 체크
  
  bool : 변수의 형태다. int, String 등 여러개가 있지만 여기선 bool만 설명한다
  bool은 true와 false 두 가지 값만 가질 수 있다
  다시 말해 진실 혹은 거짓 이 두가지를 이용해 앱의 상태를 관찰하거나 할때 주로 사용한다
  
  isDarkMode : 변수 이름이다. 변수 이름을 i , a , z  이런식으로 설정할 수 도 있는데
  나중에 유지보수할때 못알아본다. 주석 안달아두면 솔직히 컴퓨터 부모님이 와도 잘 못알아본다.
  주석이 있어도 화난다.
  변수는 항상 이름 파익이 쉽도록 만들자
  
   = : 대입할때 쓴다
   비 전공자 입장에서 볼때 = 을 설명하면
   a = 1 는 a 는 1 이다 라고 설명할 수 있겠지만
   
   전공자 입장에서 보면
   a = 1  는 a 에 1을 대입한다 라고 할 수 있다
   즉
   
   isDarkMode에 값을 대입하란 얘기다
   
   false : 앞서 bool 이 가질 수 있는 값중 하나다
   거짓을 담당하고 있으며
   
   이 변수에서는
   
   isDarkMode에 false를 대입하라고 하는 내용과 같다.
   
   // 는 주석이다 변수같은거나 함수같은거엔 주석을 필히 달아두자
   나중에 후회한다

=================================

 

그 다음 함수를 하나 만든다

함수라는건 특정한 기능을 편하게 사용하거나 반복적으로 사용하기 위해

만들어둔 코드집합이라고 볼 수 있다.

 

함수를 다음과 같은 위치에 작성한다

 

함수를 잠깐 분해해서 설명하자면

아래와 같다

 

void : 반환 형태를 얘기한다 void라면 반환하는게 없을때 작성한다

toggleTheme : 함수의 이름이며 , 호출할때 사용한다 

setState((){}) : 플러터에서 Stateful 위젯과 함께 사용된다.
상태를 변경되면 위젯을 재 빌드 한다.
따라서 화면이 갱신된다.

 isDarkMode = !isDarkMode : isDarkMode 변수값을 뒤집는 역할을 한다
현재 isDarkMode는 false 값을 가지고 있는데
변수 앞에 ! 가 붙으면 해당 내용을 NOT 하는 역할을 한다
쉽게 얘기하면 false를 가지고 있는 isDarkMode는 !isDarkMode가 되어 true가 되는것이다.

이에 대해서는 추후에 변수다루기 할때 집중적으로 설명하도록 하겠다

 

이제 함수를 만들었으니

해당 함수를 버튼에 적용시켜 버튼을 눌렀을때 함수가 실행되도록 만들면 된다.

 

버튼의 onPressed에 작성하면된다.

 

 

적용했다면

버튼을 눌러보자

 

 

아무 변화가 없다

저거 사기치는거 아니야?

할 수 있는데

 

우리가 만든 함수를 보자

 

isDarkMode의 값이

True가 되도록 만든게 고작이다

 

이 함수로 뭘 할 수 있냐고 묻는다면

그냥 false를 true로 바꿀 수 있도록 만든거다

 

그게 전부다

 

실제로 화면의 설정을 바꾸는건 작성하지 않아서 그렇다.

해당 내용을 작성해야한다.

 

테마를 바꿔야하는데

테마를 변경하는건

theme 키워드로 바꿀 수 있다.

다만 해당 키워드는 MaterialApp 에서 사용할 수 있는데

우리는 최 상단에

 

 

이렇게 MaterialApp을 만들어놨다

 

조상님의 머리가 곱슬이냐 아니냐에 따라 후손도 곱슬이냐 아니냐가 결정되듯

우리는 조상님의 설정값을 바꿔주어야 한다.

 

다만 문제가 있는데

runApp에 사용된 MaterialApp은 시조의 격인데

이곳에 지정하려면 복잡한 과정을 거치기에 간단하게 사용하려고 한다.

 

이곳에 있는 ScaffoldMaterialApp을 씌워주는 작업을 진행하고

그곳에 테마를 지정할것이다.

 

굳이 따지면 증조 격 되는 조상을 하나 만든다고 보면 된다.

 

이 전과 같이

Scaffold 앞에 커서를 두고 전구를 누른다

 

그 다음 Wrap with widget... 을 선택하고

 

다음과 같이 만들어주면 된다

 

변경할 부분은

childhome으로 바꾸는 작업 그리고 widget이라 작성된 부분을 MaterialApp으로 바꿔주면 된다

 

이 다음 테마를 지정해줄건데

테마는

아래랑 같이 작성하면 된다.

 

 

조금 설명을 해보자면

isDarkModetrueThemeData.dark()를 실행하고

isDarkModefalseThemeData.light()를 실행하라는 명령어다

 

보통 이걸 풀어쓰면

if (isDarkMode == true) {

ThemeData.dark();

} else {

ThemeData.light();

}

 

뭐 이런식으로 작성되겠지만

? 키워드를 통해 간결하게 작성할 수 있다

 

풀어 쓰는 건 학습할때 익히고

쓰는법을 익혔다면 키워드를 통해 함축해서 쓰는법을 익혀라

 

그냥 쉽게보면 된다

선언된 변수값이 (isDarkMode)

trueThemeData.dark() 를 실행하고

falseThemeData.light()를 실행하라는 명령어다

 

그러면 isDarkMode는 어떻게 값이 변화될까

 

앞서 만들어둔 함수가 여기서 빛을 본다

 

구조를 살짝 살펴보면

 

버튼을 눌렀을때 함수가 실행되고

함수가 실행되어 값이 변경되고

값이 변경되었으니 setState가 작동해 화면을 재 빌드한다.

 

그리고 마지막으로 일치하는 값에 있는 다른 명령어를 실행한다.

 

우리는 Theme.Data의 dark() 와 light()를 만든적이 없다.

 

이건 플러터에서 제공하는 기본 테마로

다크모드 / 라이트모드를 지원하도록 되어있다.

 

물론 커스터마이즈도 가능하긴하지만

그건 나중에 시간나면 해보길 추천한다.

 

이제 저장하고 핫리로드 혹은 리스타트를 진행한 다음 버튼을 눌러보면

 

 

화면이 변하는걸 볼 수 있다.

 

멋지다

이제 모드 변경을 지원하는 토글키를 만들었다.

 

다만 뭔가 좀 아쉽다.

버튼을 눌렀을때 아이콘도 바뀐다면 더 멋있지 않을까?

 

그러니까 추가해본다.

 

기존에 만들어둔 아이콘을 수정하도록 한다

이번에는 icon: 을 수정할건데

 

방법은 위에서 테마를 지정한 방식과 같다.

 

isDarkMode 변수가 True면 앞에 있는 값

Icon(Icons.brightness_2)을 실행

 

False면 뒤에 있는 값

Icon(Icons.wb_sunny)를 실행 하도록 한다

 

이렇게 하면 

 

모드가 바뀔때 아이콘도 바뀌는걸 볼 수 있다.

 

좀 더 해볼까,

아이콘 색상도 바꿀 수 있다.

그 전에 크기부터 바꿔보자

 

이제 좀 커졌다

 

색상 지정하는건 

icon 옵션중 color를 지정하면 된다.

그 다음 아래랑 같이 지정해주면 모드에 따라 색상도 변화한다.

 

 

설명하자면

isDarkModeTrue면 아이콘을 흰색으로

isDarkModeFalse아이콘을 노란색으로 지정하라는 얘기다

 

 color 옵션에 Colors.white 이렇게 작성되는 이유는

 

나도 모른다. 플러터 개발자한테 따지도록

 

최종적으로 결과물은

 

 

이렇게 나올것이다

잘 만들었다.

 

다음엔 또 다른 기능을 구현해보도록 하자

 

끝내며

 

앞서 얘기했지만

나는 뭐 변수 형태가 어쨌네, 값의 형태가 어쩌네, 바이트가 어쩌고 메가가 어쩌고

이론만 죽어라 공부하면 지루함에 못이겨 떠나게 된다고 생각한다

뭐가 됐던 구현이라도 해봐야 맛이라도 볼것 아닌가

찍먹하는 사람들에게 당부하고 싶다

포기하지 말아라

결국 프로그래머란 직업은

버그를 사랑하는 변태같은 직업이다

 

 

2023-09-21 00:38:27

이 포스트는 시리즈편이다 3편까지 있으며

다 필요없고 구현하는것만 보고 싶으면 3편을 보는것을 추천한다

 

그리고 나는 플러터의 플자도 모른다 싶으면 1부터 따라해보는것을 추천한다.

 

초보자도 다크모드 만들 수 있다 - 1 바로가기
초보자도 다크모드 만들 수 있다 - 2 현재 포스트
초보자도 다크모드 만들 수 있다 - 3 바로가기

 

 

 

저번에 여기까지 한걸로 기억한다

원래는 이것저것 추가해볼 예정이었으나, 바로 버튼부터 만들어보자

 

코드를 수정해 버튼을 만든다.

 

이 코드를 아래와 같이 바꾼다

설명은 나중에 할테니 일단 바꾸자

 

 

코드를 이렇게 바꾸고 나면

 

 

화면이 이렇게 바뀐걸 볼 수 있다

data 보다는 나은 화면이지만 뭔가 부족하다

버튼을 가운데로 가져오도록 하자

 

기존 코드를 수정한다.

 

이때 노가다로 추가하는 방법도 있겠지만

조금 더 개발의 질을 올려주는 방법을 사용하도록 한다

 

알아두면 유용하다 일단 봐두자

 

 

위젯의 첫 부분에 커서를 찍으면 좌측으로 전구모양이 보이는데

해당 전구를 누르면

 

이렇게 여러가지 메뉴를 볼 수 있다.

여기서 바로 Center를 추가할 수도 있겠지만

다양한 방식을 사용할 수 있으니

첫번째

Wrap with widget...을 선택해준다

 

이제 선택된 widget을 바꾸면 된다.

 

cent 만 입력해도 뜬다.

센터로 설정하고 나면 버튼은

 

이렇게 가운데로 오게 된다.

하지만 우리가 원하는건 화면 정 중앙이므로

다른 정렬도 함께 사용해준다.

 

여기서 Column을 이용해 정렬한다.

 

mai 라고 입력하면

mainAxisAlignment 를 입력할 수 있도록 출력되는데 엔터를 눌러주면 된다

그 다음

 

다시 똑같이 mai를 입력하면 여러 메뉴를 볼 수 있는데

각 메뉴에 대한건 사용할 때 마다 설명하는것으로 하고

이번에는 MainAxisAlignment.center 를 선택한다

 

MainAxisAlignment 이 궁금한 사람은

아래 더보기를 눌러보자

 

더보기

정렬하는 속성은 크게 두가지가 있다

crossAxisAlignment , mainAxisAlignment 

 

이 두가지는 

Column과 Row 위젯에서 사용하는데

 

Column 위젯에서

· crossAxisAlignment 는 가로 정렬을 의미하고

· mainAxisAlignment 는 세로 정렬을 의미한다

 

반대로 Row 위젯에서

· mainAxisAlignment 는 가로 정렬을 의미하고

· crossAxisAlignment 는 세로 정렬을 의미한다

 

사용은 앞서 작성한것처럼

        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,

이런식으로 사용하게 되며

center에 알맞은 속성이 들어온다.

 

다양한 속성을 설명하기엔 길어지므로 사용할때마다 설명하거나

아니면 직접 학습하는 방식으로 익히길 바란다

백날 이론봐서는 의미없다 직접 써보고

몸으로 익혀 머슬메모리에 기억하는게

제일이다.

 

Column에 옵션을 추가하고 나면

 

아이콘이 가운데로 오는것을 볼 수 있다.

 

이제 다음에는

변수도 추가해보고 테마도 건들여보고

실제로 화면을 변화시켜보자

 

 

끝내며

 

글을 나눠쓰는게 나도 썩 내키진 않지만

글이 길어지면 그만큼 집중력이 떨어진다

이해가 안된다면 반복적으로 학습해보길 바란다

2023-08-23 01:51:19

이 포스트는 시리즈편이다 3편까지 있으며

다 필요없고 구현하는것만 보고 싶으면 3편을 보는것을 추천한다

 

초보자도 다크모드 만들 수 있다 - 1 현재 포스트
초보자도 다크모드 만들 수 있다 - 2 바로가기
초보자도 다크모드 만들 수 있다 - 3 바로가기

 

 

앱을 개발하다보면 다크모드 / 라이트모드 전환에 대한 기능이 필요해지기 마련이다

특히 유틸리티의 경우 다크모드를 지원하지 않으면 부족한 앱 처럼 보이기도 한다

 

그래서 다크모드 토글 키를 만들어보려고 한다.

 

나는 프로그래밍에 있어서 변수가 어쩌고 , 연산식이 저쩌고 이런 식으로 서술하는걸 좋아하지 않는다

 

이유는 간단하다

 

지루하다

 

백날 천날 이론만 배워봐라

 

만들 수 있는게 없다

 

그러니까 잘 몰라도 실전으로 들어가서 헤딩 해보는 것도 방법이라 생각한다.

 

각설하고 본론으로 돌아와서

 

이제 설정 해둔 IDE랑 애뮬레이터를 이용해서 뭐라도 만들어보자

 

 

저번에 만들어둔 애뮬레이터를 키고

IDE에서 main.dart의 코드를 실행한다.

 

 

앱이 기기에 설치되고 샘플 코드가 작동하는것을 볼 수 있다.

각 요소나 기능들은 필요할때마다 설명하거나 배워가는식으로 하고

일단 버튼도 눌러보고 하면서 신기함을 즐겼으면 한다

 

필연적인 에러와 각종 버그랑 싸우고 승리하려면

결국 즐겨야한다

 

이게 샘플 코드인데

지금은 몰라도 된다

그냥 뭐가 많구나 하는것만 알면된다.

 

우리는 샘플코드가지고 뭐 할게 아니므로

 

import 'package:flutter/material.dart';

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

 

이 코드만 빼고 다 지워준다

 

 

지웠다면 우리만의 화면을 만들어야하는데

플러터는

두 가지 화면을 지원한다

StatefulWidget / StatelessWidget

 

간단하게 두 위젯의 차이를 보자면

 

StatefulWidget  StatelessWidget
동적 정적
리소스 소모 많음 리소스 소모 적음

 

이런 차이가 있다

StatefulWidget 의 경우 데이터가 갱신되거나 , 화면이 갱신되면 새롭게 화면을 만들어

변화를 반영한다.

StatelessWidget 는 데이터가 갱신되거나 , 화면이 갱신되어도 변화를 반영하진 않는다.

따라서 어떤 라이브러리들을 함께 사용하는데 그건 나중에 알아보도록 하겠다.

 

오늘은 토글키를 이용해 화면을 즉각적으로 변화시키려고 하기 때문에 StatefulWidget을 이용한다.

 

 

길게 칠 것도 없다 stf만 입력하면 자동으로 완성해준다

 

 

추가를 하면 기본적으로 이름을 변경할 수 있다

F2를 눌러 변경하도록 한다

이름은 아무거나 상관없지만 최소한 이게 뭐하는건지는 알 수 있도록 작성한다

 

 

필자는 그냥 다크모드토글로 정했다

이제

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

 

여기 빨간 오류가 거슬린다.

이 오류는 시작점을 찾지못해 오류가 발생한다

앞서 StatefulWidget의 이름을 변경했으므로 변경한 이름과 일치하게 바꿔준다.

 

 

에러가 없어졌으니 이제 테스트를 해본다.

 

 

* 아는 사람은  넘어가자 초심자를 위한 설명이다 *

 

우리가 주목해야 할 버튼은

크게 4가지가 있다

 





일시중지 버튼
[ 나는 많이 안씀 ]




핫 리로드
[ 앱을 종료하지 않아도 업데이트 내역이 반영됨 ]




리스타트
[ 앱을 재 시작함 ]




스탑
[ 앱 종료 ]

 

이 정도만 알아도 된다.

우리는 리스타트 버튼을 눌러 코드 업데이트를 반영한다

 

 

화면이 시꺼매지는걸 볼 수 있다

Placeholder를 지정하면 화면이 이렇게 생성된다.

 

이렇게 두면 다크모드고 라이트모드고

아무것도 아니니까 코드를 업데이트 하도록 한다

 

그리고 글자를 추가해본다.

 

 

하지만 애뮬레이터 화면은 변경된게 없다.

파란색 경고에 대해서는 따로 설명하지 않겠다.

 

어차피 쓰다보면 알게된다.

그래도 궁금하면 아래를 참고하자

 

더보기
더보기

컨테이너에는 margin , padding , width , height , decoration 등 옵션이 많은데

옵션을 사용하지 않고 컨테이너를 사용하는 것을 플러터는 싫어한다

그래서 경고를 날려주는건데 딱히 실행하는데 문제 없다

보통 저렇게 지정하면 sizebox라는걸로 알아서 바꿔준다.

 

왜 옵션없이 컨테이너를 쓰지 말라고 하는지는

플러터 개발자한테 물어보도록 하자

 

 

그리고 컨트롤패널을 보면 

 

못보던 친구들이 활성화가 되어있는게 보인다.

보통 이렇게 표시되면 에러가 발생한거다.

 

그래서 업데이트가 반영되지 않은 상태고

디버그모드라서 하나씩 실행해보고 어디서 문제인지 찾을 수 도 있다.

 

이건 나중에 디버그 해보면서 천천히 하나씩 써보고

지금은 원인부터 찾도록 하자

 

대게 에러생기면 여기 표시해준다

근데 표시가 없다면 리스타트를 눌러보도록 하자

 

이제 뭐가 문젠지 정상적으로 출력된다

단순한 에러메세지를 보자면

No Directionality widget found.

이게 문제라고 한다.

 

왜 이런 문제가 발생하냐면

플러터는 MaterialApp 이라고 하는 조상님을 항상 먼저 불러와야 한다.

 

사람도 마찬가지로

조상이 없는데 내가 있을 수는 없는 노릇이다

 

따라서 조상님을 추가해주도록 한다.

 

추가하는 위치는 StatefulWidget 위에 있는 main() 함수에서 진행한다.

 

void main() {
  runApp(const DarkModeToggle());
}

 

기존에 있는 코드를 아래와 같이 변경해준다

 

void main() {
  runApp(
    MaterialApp(
      home: DarkModeToggle(),
    ),
  );
}

 

 

이제 조상님도 추가해줬으니 후손이 존재할 수 있게 되었다.

리스타트로 확인하자

 

 

부담스럽게 data 라는 글씨가 정상적으로 화면에 표시되는걸 확인할 수 있다.

 

여기까지 하면 토글키를 만들 기본 세팅이 끝났다.

 

원래는 쭉 길게 작성하려고 했으나

스크롤이 길어지면 노잼이므로 다음 글로 이어서 작성한다.

 

 

글을 마치며

 

많은 사람들이 개발자에 도전하고 좌절하며 꿈을 이어나간다.

 

개중에는 포기한사람도 있고, 개중에는 성공한 사람도 있다

 

하나 확실한건 끈기를 가지고 덤비면 뭐라도 만들어진다는 것이다.

 

개발자 지망생 혹은 주니어 개발자들이 힘냈으면 하는 바램이다.

 

또 하나

 

이론만 죽어라 공부하면 결국 구구단이나 만들고 있다.

 

실제 서비스 기능을 구현해보자는 마음으로 덤비길 바란다.

 

다음 글에서 보도록 하자



Developer port. Designed by bskyvision.