flutter -8

김상윤·2023년 3월 7일
0

flutter

목록 보기
8/10

네비게이션

많은 페이지 이동
페이지? 스캐폴드를 최상위로 가지고 있는 애가 페이지
다른페이지로 이동을 라우팅이라 한다.
라우팅 하려면 최상단 위젯이 스캐폴드여야만 해

네비게이션 -> 스택구조(늦게 들어온게 가장 많이 빠짐) Last in First Out
새로 페이지를 불러온다(push)
현재 페이지를 뺀다(pop)

push 예제

Navigator.push(
	context,	//현재 위젯의 상태정보, 거의 고정
	MaterialPageRoute(builder.(context) => 이동할페이지(),)   //중요
	);
),

pop 예제

Navigator.pop(context); // 라우트 해줄 필요없음, 현재 위젯 상황을 context로 보여줌, 이전페이지로 이동

비교 연산

if문! 원하는 조건에 맞을 때만 실행
if(statement) -> statement엔 boolean 형만(true or false)

if(statement조건){
	참일 때 실행할 문장;
} else {
	거짓일 때 실행할 문장;
}

예시

bool login(String id, String pw){
	if(pw.length <= 8 ) return false;    //pw가 8글자 안넘으면 바로 fal
	if(!isEmail(id)) return false;		//없으면 false인데 !만나서 true로 실행문 실행 
	if(!exists(id)) return false;		//상동
	return true;
}

Parse

int.parse(myController.text) -> myController에 숫자 형식 String이 있다 가정하면 string을 숫자로

3항연산자

조건 ? 참일 때(위젯가능) : 거짓일때 뭐 할건지
if문과 비슷, 자주쓰임 중요!

Checkbox

setState, stf랑 같이 사용
왜? stf는 화면이 전환될 때 사용함. checkbox의 값이 바뀌면서 화면도 같이 바뀌어야 되기 때문에

예시

var isChecked = false;
CheckBox(
	value : isChecked,
	onChanged: (value){
		isChecked = value!;
		setState((){});
	)

Visibility 위젯

visible속성 false(bool변수 가능)로 바꾸면 child가 안보이게 설정 가능

과제

  • 프로젝트 생성시 main.dart의 기본 소스코드 분석
  • Stateful 위젯의 라이프사이클을 공부하고, initState함수가 무엇인지, 언제 작동되는지 소스코드로 직접 테스트해보세요. 그리고 버튼의 이벤트를 통해 setState((){}); 실행했을 때, 왜 initState 함수는 실행이 안되는지 정리하세요.
  • UI 코드 작성(사칙연산 앱)

1번

import 'package:flutter/material.dart';
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({super.key});
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.
  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".
  final String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }
  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

기본적인 코드를 살펴보면 한 번 빌드를 한 후 ui를 바꿀 필요가 없는 타이틀과 테마에는
stl위젯으로 감싸져있다. 하지만 fab를 눌렀을 때 숫자가 증가하는 ui를 만들기 위해서
그 부분은 stf 위젯으로 만들어져 있는 점을 볼 수 있다. _incrementCounter 함수를 이용하여
fab를 눌렀을 때 center에 있는 _counter변수를 증가시키고 ui를 계속해서 바꿔주는 역할을
하고 있다. 만약 stl위젯으로 되어있다면 적용이 안되고 숫자가 증가하지 않고 0으로 화면 ui의 변경은 없을 것이다.

2번

createState() method는 statefulWidget을 구축하자마자 호출되며 state object를
생성한다. initState() : object가 트리에 주입되면(mounted 속성은 true로 설정),
initState()가 class constructor 다음으로 자동으로 실행된다. initState()는
state obejct가 처음 생성될 때, 한 번만 호출된다. build() : 위젯을 반환(return)한다.
반환된 위젯이 렌더링되어 화면에 표시된다. build method는 필수
setState() : 상태가 변경되었을 때 프레임워크에 상태가 변경됨을 알린다.
dispose() : state object가 영구적으로 삭제될때 호출된다.
이 함수는 주로 Stream이나 애니메이션 해제 시 사용된다.

class _CounterContainerState extends State<CounterContainer> {
  late int count;
  @override
  void initState() {
    super.initState();
    count = 0;
  }
  ...
}

initstate()는 state를 초기화하는 함수이다. initState는 statefulWidget이 실행하면
단 한 번만 작동을 한다. 그 이후 작동시키기 위해서는 해당 statefulWidget을 종료한 후에 가능하다. 이 함수 안을 수정하고 hot reload 또는 rebuild를 아무리 하더라도 바뀌지 않으니 반드시
수정한 statefulWidget을 종료(dispose) 후 다시 실행시켜야 한다

3번


import 'package:flutter/material.dart';
void main() {
  runApp(const MyApp());
}
class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyCustomWidget(),
    );
  }
}
class MyCustomWidget extends StatefulWidget {
  const MyCustomWidget({super.key});
  @override
  State<MyCustomWidget> createState() => _MyCustomWidgetState();
}
showResultDialog(BuildContext context, var result) {
  showDialog(
    context: context,
    builder: (context) {
      return Dialog(
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
        child: SizedBox(
          width: MediaQuery.of(context).size.width / 2,
          height: 150,
          child: Center(
              child: Text(
            "$result",
            style: const TextStyle(fontWeight: FontWeight.bold),
          )),
        ),
      );
    },
  );
}
class _MyCustomWidgetState extends State<MyCustomWidget> {
  int x = 0;
  int y = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text("사칙연산"),
      ),
      body: Center(
          child: Padding(
        padding: const EdgeInsets.all(32.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Row(
              children: [
                Text("x의 값은?"),
                SizedBox(
                  width: 80,
                ),
                SizedBox(
                  width: 200,
                  child: TextField(
                    onChanged: (value) {
                      x = int.parse(value);
                    },
                    decoration: InputDecoration(
                        hintText: "x의 값을 입력하세요.", border: OutlineInputBorder()),
                  ),
                ),
              ],
            ),
            Row(
              children: [
                Text("Y의 값은?"),
                SizedBox(
                  width: 80,
                ),
                SizedBox(
                  width: 200,
                  child: TextField(
                    onChanged: (value) {
                      y = int.parse(value);
                    },
                    decoration: InputDecoration(
                      hintText: "y의 값을 입력하세요",
                      border: OutlineInputBorder(),
                    ),
                  ),
                )
              ],
            ),
            ElevatedButton(
              onPressed: () {
                showResultDialog(context, x + y);
              },
              child: Text("더하기 결과"),
            ),
            ElevatedButton(
              onPressed: () {
                showResultDialog(context, x - y);
              },
              child: Text("빼기 결과"),
            ),
            ElevatedButton(
              onPressed: () {
                showResultDialog(context, x * y);
              },
              child: Text("곱하기 결과"),
            ),
            ElevatedButton(
              onPressed: () {
                showResultDialog(context, x / y);
              },
              child: Text("나누기 결과"),
            )
          ],
        ),
      )),
    );
  }
}
profile
교육 중!

0개의 댓글