Posts flutter (rn 개발자를 위한 정리 3)
Post
Cancel

flutter (rn 개발자를 위한 정리 3)

Flutter 위젯

Views

View 컨테이너

  • React Native 에서는 View 가 컨테이너이고 Flexbox를 이용한 레이아웃, 스타일, 터치 핸들링, 접근성제어를 지원

  • Flutter에서는 Container나, Column, Row, Center같은 위젯 라이브러리의 핵심 레이아웃 위젯을 사용할 수 있음.

FlatList, SectionList

  • ListView : 목록의 수가 적은 경우에 가장 적합함.
  • 무거운 목록이거나 무한 스크롤 목록일때는 ListView.builder 를 사용
    • 자식들을 필요할 때만 빌드하고, 화면에 나타나야할 자식들만 빌드함
1
2
3
4
5
6
7
8
9
10
// Flutter
var data = [ ... ];
ListView.builder(
  itemCount: data.length,
  itemBuilder: (context, int index) {
    return Text(
      data[index],
    );
  },
)

Canvas

  • ReactNative에서는 직접적으로 지원하는 컴포넌트가 없음
  • Flutter에서는 CustomPaint, CustomPainter 클래스를 사용하여 캔버스를 그릴 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Flutter
class MyCanvasPainter extends CustomPainter {

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint();
    paint.color = Colors.amber;
    canvas.drawCircle(Offset(100.0, 200.0), 40.0, paint);
    Paint paintRect = Paint();
    paintRect.color = Colors.lightBlue;
    Rect rect = Rect.fromPoints(Offset(150.0, 300.0), Offset(300.0, 400.0));
    canvas.drawRect(rect, paintRect);
  }

  bool shouldRepaint(MyCanvasPainter oldDelegate) => false;
  bool shouldRebuildSemantics(MyCanvasPainter oldDelegate) => false;
}
class _MyCanvasState extends State<MyCanvas> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomPaint(
        painter: MyCanvasPainter(),
      ),
    );
  }
}

Canvas on iOS

레이아웃

레이아웃 속성 정의

  • React native에서는 style props를 이용해 flexbox 속성을정의함.

    1
    2
    3
    4
    
    // React Native
    <View
      style=
    >
    
  • flutter에서는 컨트롤 위젯 및 스타일 속성을 결합하여 설계된 위젯을 통해 레이아웃을 정의한다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    // Flutter
    Center(
      child: Column(
        children: <Widget>[
          Container(
            color: Colors.red,
            width: 100.0,
            height: 100.0,
          ),
          Container(
            color: Colors.blue,
            width: 100.0,
            height: 100.0,
          ),
          Container(
            color: Colors.green,
            width: 100.0,
            height: 100.0,
          ),
        ],
      ),
    )
    

위젯을 겹쳐 쌓아올리는 방법

  • React Native에서는 absolute 을 사용
  • flutter에서는 Stack을 사용함.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Flutter
Stack(
  alignment: const Alignment(0.6, 0.6),
  children: <Widget>[
    CircleAvatar(
      backgroundImage: NetworkImage(
        'https://avatars3.githubusercontent.com/u/14101776?v=4'),
    ),
    Container(
      decoration: BoxDecoration(
          color: Colors.black45,
      ),
      child: Text('Flutter'),
    ),
  ],
)

Stack on iOS

스타일링

컴포넌트 꾸미기

  • react native 에서는 인라인 스타일링과 stylesheets.create를 이용한 스타일링 가능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<View style={styles.container}>
  <Text style=>
    This is a sample text
  </Text>
</View>

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center'
  }
});
  • flutter에서는 Text 위젯은 style 속성에 TextStyle클래스를 사용할 수 있음.
    • 여러 곳에서 같은 스타일을 사용하고 싶으면 따로 빼서 적용가능
    • 다른 위젯에서도 비슷한 방식인가?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var textStyle = TextStyle(fontSize: 32.0, color: Colors.cyan, fontWeight:
   FontWeight.w600);
	...
Center(
  child: Column(
    children: <Widget>[
      Text(
        'Sample text',
        style: textStyle,
      ),
      Padding(
        padding: EdgeInsets.all(20.0),
        child: Icon(Icons.lightbulb_outline,
          size: 48.0, color: Colors.redAccent)
      ),
    ],
  ),
)

Icons와 Colors를 사용하는 방법은?

  • flutter에서는 material 라이브러리를 import하면 다양한 material icon컬러를 가져옴
1
Icon(Icons.lightbulb_outline, color: Colors.redAccent)
  • Icons 클래스를 사용할떄는 pubspec.yaml 파일에 uses-material-design : true 를 꼭 설정해줘야함
1
2
name: my_awesome_application
flutter: uses-material-design: true
  • 쿠퍼티노 아이콘 사용
1
2
3
name: my_awesome_application
dependencies:
  cupertino_icons: ^0.1.0
  • 컴포넌트 전체적인 색과 스타일을 지정하고 싶으면 ThemeData 클래스를 사용
    • MaterialApp 에서 theme 속성에 ThemeData 객체를 설정한다.
    • Colors 클래스는 material 디자인의 color paletter에 해당하는 색상을 제공
1
2
3
4
5
6
7
8
9
10
11
12
13
class SampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Sample App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        textSelectionColor: Colors.red
      ),
      home: SampleAppPage(),
    );
  }
}

스타일 테마 추가

  • React Native에서는 컴포넌트 공통 테마는 stylesheets에 정의한 후 컴포넌트에 사용함
  • Flutter에서는 ThemeData 클래스에 스타일을 정의하고, MaterialApp 위젯의 테마 속성에 전달함으로써 거의 모든 곳에 균일한 스타일을 적용할 수 있음.
1
2
3
4
5
6
7
8
9
10
 @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primaryColor: Colors.cyan,
        brightness: Brightness.dark,
      ),
      home: StylingPage(),
    );
  }
  • Theme는 MaterialApp 위젯을 사용하지 않아도 적용가능.
    • data 매개변수에서 ThemeData를 가져와 모든 자식 위젯에 ThemeData를 적용함.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 @override
  Widget build(BuildContext context) {
    return Theme(
      data: ThemeData(
        primaryColor: Colors.cyan,
        brightness: brightness,
      ),
      child: Scaffold(
         backgroundColor: Theme.of(context).primaryColor,
              ...
              ...
      ),
    );
  }

상태관리

StatelessWidget

  • 상태 변화가 필요없는 위젯.
  • 객체의 자체적인 구성정보나 위젯의 BuildContext 이외의 것에 의존하지 않을때 유용함

  • 상태가 없는 위젯의 build 메서드는 보통 3가지 상황에서만 호출됨
    • 위젯이 트리에 추가될 때
    • 위젯의 부모가 설정이 변경됐을때
    • 사용하고 있는 InheritedWidget이 변경될 때

StatefulWidget

  • setState를 호출하여 Flutter 프레임워크에게 상태가 변경됐음을 알려줌.

    • 이후 앱이 build 메서드를 다시 실행하여 변경사항을 반영함
  • 아래는 createState() 메서드를 필요로하는 StatefulWidget을 선언하는 예시

    • 위젯의 상태를 관리하는 상태객체 _MyStatefulWidgetState를 생성함
    1
    2
    3
    4
    5
    6
    7
    
    class MyStatefulWidget extends StatefulWidget {
      MyStatefulWidget({Key key, this.title}) : super(key: key);
      final String title;
    
      @override
      _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
    }
    
  • 아래는 _MyStatefulWidgetState 라는 상태 클래스.

    • 상태가 바뀌면 setState가 새로운 toggle 값과 함께 호출됨.
    • 이후 프레임워크가 UI위젯을 다시 빌드함.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    
    class _MyStatefulWidgetState extends State<MyStatefulWidget> {
      bool showtext=true;
      bool toggleState=true;
      Timer t2;
    
      void toggleBlinkState(){
        setState((){
          toggleState=!toggleState;
        });
        var twenty = const Duration(milliseconds: 1000);
        if(toggleState==false) {
          t2 = Timer.periodic(twenty, (Timer t) {
            toggleShowText();
          });
        } else {
          t2.cancel();
        }
      }
    
      void toggleShowText(){
        setState((){
          showtext=!showtext;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Column(
              children: <Widget>[
                (showtext
                  ?(Text('This execution will be done before you can blink.'))
                  :(Container())
                ),
                Padding(
                  padding: EdgeInsets.only(top: 70.0),
                  child: RaisedButton(
                    onPressed: toggleBlinkState,
                    child: (toggleState
                      ?( Text('Blink'))
                      :(Text('Stop Blinking'))
                    )
                  )
                )
              ],
            ),
          ),
        );
      }
    }
    

StatefulWidget 과 StatelessWidget의 모범사례

위젯을 설계할때의 고려사항

  1. 위젯이 StatefulWidget인지 StatelessWidget인지 결정하라

    • 위젯이 변화하면 Stateful 사용
    • 위젯이 final이거나 immutable이면, Stateless를 사용
  2. 어떤 객체가 위젯의 상태를 관리하는지 결정하라

    • Flutter에서 상태를 관리하는 3가지 방법
      • 위젯이 자신의 상태를 관리
      • 부모위젯이 상태를 관리
      • 혼합하여 관리
    • 원칙
      • 해당 상태가 사용자 입력이라면, 상위위젯에서 관리하는 것이 가장 좋음
        • ex : 슬라이더 위치 혹은 체크박스의 선택과 취소
      • 해당 상태가 UI와 연관이 깊으면, 해당 위젯에서 관리
        • ex : 애니메이션
      • 잘모르겠을때는 부모 위젯이 관리하도록 함
  3. StatefulWidget의 하위 클래스 및 State

    • 아래 예시는 자신이 직접 상태를 관리하는 것
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    class MyStatefulWidget extends StatefulWidget {
      MyStatefulWidget({Key key, this.title}) : super(key: key);
      final String title;
    
      @override
      _MyStatefulWidgetState createState() => _MyStatefulWidgetState();
    }
    
    class _MyStatefulWidgetState extends State<MyStatefulWidget> {
    
      @override
      Widget build(BuildContext context) {
        ...
      }
    }
    
  4. StatefulWidget을 위젯트리에 추가하기

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    class MyStatelessWidget extends StatelessWidget {
      // This widget is the root of your application.
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MyStatefulWidget(title: 'State Change Demo'),
        );
      }
    }
    
    • 위와같이 Stateless 위젯 안에 Stateful 위젯을 추가하는 방식도 통함
This post is licensed under CC BY 4.0 by the author.

flutter (rn 개발자를 위한 정리 2)

flutter (rn 개발자를 위한 정리 4)

Comments powered by Disqus.