반응형

Flutter 레이아웃의 기본, Container 위젯을 이해하자

 

Flutter에서 Container 위젯은 레이아웃을 구성하는 데 가장 기본적이면서도 강력한 도구입니다. 이를 비유하자면, 빈 상자(Box) 또는 캔버스처럼 생각할 수 있습니다. 이 빈 캔버스 위에 원하는 스타일, 정렬, 크기 등을 적용해 다양한 레이아웃을 구성할 수 있습니다.


1. Container란 무엇인가?

 

Container 위젯은 Flutter에서 레이아웃을 꾸미고 배치하는 데 사용되는 다목적 위젯입니다. 주요 기능은 다음과 같습니다:

크기 조절: width, height를 통해 크기를 조정할 수 있습니다.

스타일링: color, decoration을 사용해 배경색, 테두리, 그림자 등을 추가할 수 있습니다.

배치: 내부 여백(padding), 외부 여백(margin), 정렬(alignment) 등을 설정할 수 있습니다.

 

2. Container의 주요 속성

 

Container는 다양한 속성을 제공하며, 이를 통해 위젯을 쉽게 커스터마이징할 수 있습니다.

속성 설명
width / height 컨테이너의 너비와 높이를 설정합니다.
color 컨테이너의 배경색을 지정합니다.
padding 내부 여백을 설정하여 컨테이너 내부의 자식 위젯이 테두리로부터 얼마나 떨어져야 하는지 결정합니다.
margin 외부 여백을 설정하여 컨테이너와 주변 위젯 간의 간격을 조정합니다.
decoration 배경, 테두리, 그림자, 둥근 모서리 등의 복잡한 스타일을 설정할 수 있습니다. color와 함께 사용하지 못하며, 둘 중 하나만 사용 가능합니다.
alignment 자식 위젯의 배치를 컨테이너 내부에서 조정합니다.
constraints 컨테이너의 최소 및 최대 크기를 설정합니다.
child Container 내부에 들어갈 다른 위젯 설정(모든 위젯에 자식 위젯을 지정할 수 있음)

 


3. 실제 예제 코드로 이해하기

 

기본적인 Container

Container(
  width: 100,
  height: 100,
  color: Colors.blue, // 단순 배경색 설정
)

여백과 정렬 추가

Container(
  margin: EdgeInsets.all(20), // 외부 여백
  padding: EdgeInsets.all(10), // 내부 여백
  color: Colors.orange,
  child: Text('Hello Flutter!'), // 자식 위젯
)

스타일링과 둥근 테두리

Container(
  width: 150,
  height: 150,
  decoration: BoxDecoration(
    color: Colors.green,
    borderRadius: BorderRadius.circular(15), // 둥근 모서리
    boxShadow: [
      BoxShadow(
        color: Colors.black.withOpacity(0.2),
        spreadRadius: 2,
        blurRadius: 5,
      ),
    ],
  ),
  child: Center(
    child: Text(
      'Styled Box',
      style: TextStyle(color: Colors.white),
    ),
  ),
)

 

 

4. Container의 한계

 

Container를 지나치게 남용하면 성능에 영향을 미칠 수 있습니다. Flutter는 레이아웃을 효율적으로 구성하기 위해 더 간단한 위젯(예: Padding, SizedBox, Align)을 사용할 수 있습니다. 따라서 Container를 사용할 때 꼭 필요한 경우에만 활용하는 것이 좋습니다.

반응형
반응형

Flutter의 didChangeDependencies 함수란?

Flutter에서 didChangeDependencies 함수StatefulWidget의 상태가 변경되었거나, 위젯이 의존하고 있는 어떤 값이 변경되었을 때 호출되는 함수입니다.
쉽게 말해, "위젯이 외부에서 제공받는 데이터가 변경되었을 때 실행되는 함수"입니다.

 


didChangeDependencies의 주요 특징

  1. 특정 상황에서 호출:
    • 위젯의 의존성이 변경되었을 때 호출됩니다.
    • 예: InheritedWidget의 값이 변경되었을 때.
  2. initState 다음에 호출:
    • 위젯이 처음 생성될 때, initState 이후에 한 번 호출됩니다.
    • 그 이후에는 의존성이 변경될 때마다 호출됩니다.
  3. 데이터 의존성이 있을 때 사용:
    • 위젯이 상위 위젯에서 제공하는 데이터를 사용할 때, 이 데이터를 다시 불러오거나 처리하는 데 유용합니다.

didChangeDependencies 함수의 기본 구조

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  // 의존성 변경 시 수행할 작업
}
  • super.didChangeDependencies(): Flutter의 기본 동작을 유지하려면 항상 호출해야 합니다.

간단한 예제: InheritedWidget과 함께 사용

아래는 InheritedWidget을 사용해 데이터를 전달하고, didChangeDependencies에서 이 데이터를 처리하는 예제입니다.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

// InheritedWidget 정의
class CounterProvider extends InheritedWidget {
  final int counter;

  CounterProvider({
    required this.counter,
    required Widget child,
  }) : super(child: child);

  @override
  bool updateShouldNotify(CounterProvider oldWidget) {
    return oldWidget.counter != counter;
  }

  static CounterProvider? of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<CounterProvider>();
  }
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int counter = 0;

  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return CounterProvider(
      counter: counter,
      child: MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: Text('didChangeDependencies 예제')),
          body: CounterDisplay(),
          floatingActionButton: FloatingActionButton(
            onPressed: _incrementCounter,
            child: Icon(Icons.add),
          ),
        ),
      ),
    );
  }
}

class CounterDisplay extends StatefulWidget {
  @override
  _CounterDisplayState createState() => _CounterDisplayState();
}

class _CounterDisplayState extends State<CounterDisplay> {
  int? counter;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // InheritedWidget에서 데이터를 가져옴
    counter = CounterProvider.of(context)?.counter;
    print('didChangeDependencies 호출됨: counter = $counter');
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        'Counter: $counter',
        style: TextStyle(fontSize: 24),
      ),
    );
  }
}

실행 결과:

  1. 처음 실행하면 Counter: 0이 표시됩니다.
  2. 플러스 버튼을 누르면:
    • counter 값이 증가하고, didChangeDependencies가 호출되어 화면이 업데이트됩니다.
    • 콘솔에 didChangeDependencies 호출됨이 출력됩니다.

언제 didChangeDependencies를 사용해야 할까?

  • InheritedWidget 데이터 의존:
    • 위젯이 상위 위젯에서 데이터를 받을 때, 데이터 변경을 감지하고 싶을 때.
  • 외부 의존성 감지:
    • 예: 테마 변경, 지역화(Localization) 데이터 변경.

didChangeDependencies와 initState의 차이

initState didChangeDependencies
위젯이 처음 생성될 때 한 번 호출됨. 처음 생성될 때 한 번 호출되고, 이후 의존성이 변경될 때마다 호출됨.
내부 상태를 초기화하는 데 사용됨. 외부 데이터(의존성) 변경을 감지하고 처리함.
context를 사용할 수 없음 context를 사용할 수 있음.
반응형
반응형

Flutter의 initState 함수란?

Flutter에서 initState 함수StatefulWidget의 상태를 초기화할 때 사용하는 메서드입니다.
쉽게 말해, "앱이 처음 실행될 때 한 번만 호출되는 준비 작업 함수"라고 생각하면 됩니다.
예를 들어, 데이터를 불러오거나 타이머를 설정하는 등 초기화가 필요한 작업을 initState에서 수행합니다.


initState의 주요 특징

  1. 딱 한 번 호출됨
    • initState는 State 객체가 처음 생성될 때 한 번만 호출됩니다.
    • 이후 상태가 변경되어도 initState는 다시 호출되지 않습니다.
  2. 초기화 작업에 적합
    • 데이터를 불러오거나 리스너를 추가하는 등 초기 설정 작업에 사용됩니다.
  3. super.initState() 호출 필요
    • initState를 오버라이드할 때 super.initState() 를 반드시 호출해야 Flutter의 내부 초기화가 제대로 동작합니다.

initState 함수의 기본 구조

@override
void initState() {
  super.initState(); // 부모 클래스의 초기화 메서드 호출
  // 초기화 작업
}

간단한 예제: 앱 시작 시 타이머 설정

아래는 앱이 실행되면 3초 후에 텍스트를 업데이트하는 예제입니다.

import 'package:flutter/material.dart';
import 'dart:async'; // 타이머를 사용하기 위해 필요

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String message = "안녕하세요!";

  @override
  void initState() {
    super.initState();
    // 3초 후에 메시지 변경
    Timer(Duration(seconds: 3), () {
      setState(() {
        message = "Flutter를 배우고 있어요!";
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('initState 함수 예제')),
        body: Center(
          child: Text(
            message,
            style: TextStyle(fontSize: 24),
          ),
        ),
      ),
    );
  }
}

 


언제 initState를 사용해야 할까?

  • 초기 데이터 로드:
    • 예: API 호출, 데이터베이스에서 데이터 가져오기.
  • 애니메이션 시작:
    • 애니메이션 컨트롤러 초기화.
  • 리스너 추가:
    • 텍스트 입력이나 네트워크 이벤트를 감지하는 리스너 설정.
  • 타이머 설정:
    • 특정 시간 후에 동작을 실행.

 

주의할 점

  1. UI 관련 작업 금지:
    • initState에서 직접 UI를 업데이트하거나 context를 사용해 위젯 트리에 접근하면 오류가 발생할 수 있습니다.
    • 이유: 위젯이 아직 완전히 렌더링되지 않았기 때문입니다.
  2. 반드시 super.initState() 호출:
    • initState를 오버라이드할 때 Flutter의 기본 초기화 작업을 위해 super.initState()를 호출해야 합니다.
  3. dispose와 함께 사용:
    • 리스너나 애니메이션 컨트롤러를 initState에서 추가했다면, dispose 함수에서 반드시 정리(cleanup)해야 메모리 누수를 방지할 수 있습니다.
반응형
반응형

Flutter의 createState 함수란?

Flutter에서 createState 함수StatefulWidget과 함께 사용되며, 화면의 변경 가능한 상태(state)를 관리하는 중요한 역할을 합니다. 쉽게 말해, StatefulWidget을 위한 "상태 관리자"를 만들어주는 함수입니다.


왜 createState가 필요한가?

StatefulWidget은 두 가지 주요 구성 요소로 이루어져 있습니다:

  1. StatefulWidget: 화면에 정적인 부분을 정의합니다.
  2. State: 화면의 변경 가능한 부분(예: 버튼 클릭, 입력 값)을 관리합니다.

createState 함수는 StatefulWidget이 화면의 상태를 관리할 수 있도록 State 객체를 연결합니다.

 

createState 함수의 기본 구조

createState 함수는 StatefulWidget 클래스에서 필수로 구현해야 하며, State 클래스를 반환합니다.

@override
State<MyWidget> createState() => _MyWidgetState();

 

  • MyWidget: StatefulWidget 클래스 이름입니다.
  • _MyWidgetState: State 클래스 이름입니다. 일반적으로 밑줄(_)을 붙여 해당 클래스를 비공개로 만듭니다.

간단한 예제: 버튼을 누르면 숫자가 증가하는 앱

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int counter = 0;

  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('createState 함수 예제'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                '버튼을 누른 횟수:',
                style: TextStyle(fontSize: 20),
              ),
              Text(
                '$counter',
                style: TextStyle(fontSize: 40, fontWeight: FontWeight.bold),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _incrementCounter,
                child: Text('숫자 증가'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

 

 


createState 함수의 동작 과정

  1. State 객체 생성:
    • createState 함수는 State 객체를 생성하고 StatefulWidget과 연결합니다.
  2. State 객체 관리:
    • Flutter는 State 객체를 사용해 StatefulWidget의 상태를 관리합니다.
  3. 상태 변경:
    • 상태가 변경되면 setState 메서드를 호출하여 build 함수를 다시 실행하고 UI를 업데이트합니다.

StatefulWidget에서 createState와 State의 관계

StatefulWidget은 변경 가능한 UI를 처리할 때 항상 State 객체와 함께 작동합니다. 아래 그림으로 쉽게 이해할 수 있습니다:

StatefulWidget -------> createState() -------> State 클래스
       ↑                                          ↓
      UI 정의                              상태 변경 및 UI 업데이트

1. createState 함수는 언제 호출되나요?

  • StatefulWidget이 처음 생성될 때 딱 한 번 호출됩니다.

2. 왜 State 객체를 분리하나요?

  • State 객체를 분리하면 동일한 StatefulWidget을 다른 상태에서 재사용할 수 있어 UI와 상태를 독립적으로 관리할 수 있습니다.

3. State 클래스의 생명주기는 어떻게 되나요?

State 클래스는 아래와 같은 순서로 작동합니다:

  1. createState: State 객체 생성.
  2. initState: State 객체 초기화.
  3. build: UI 렌더링.
  4. setState: 상태 변경 후 UI 업데이트.
반응형
반응형

Flutter의 build 함수란?

Flutter에서 UI를 만드는 핵심 메서드 중 하나가 바로 build 함수입니다. 앱 화면에 표시되는 모든 것은 이 build 함수에서 정의됩니다. 쉽게 말해, build 함수는 화면에 어떤 위젯을 보여줄지 "그리는 설계도"라고 할 수 있습니다.

 


build 함수의 역할

  1. 위젯 트리를 구성:
    • build 함수는 Flutter에게 어떤 위젯을 화면에 보여줄지 알려줍니다.
    • 이 함수 안에서 다양한 위젯을 조합해 "위젯 트리(widget tree)"를 만듭니다.
  2. UI 업데이트 처리:
    • 앱의 상태(state)가 바뀌면, Flutter는 build 함수를 다시 호출해 변경된 UI를 업데이트합니다.

build 함수의 기본 구조

build 함수는 반드시 구현해야 하는 함수로, 모든 Flutter 위젯에서 사용됩니다. 아래는 build 함수의 기본 구조입니다.

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

 

  • context: 현재 위젯의 위치와 관련된 정보를 담고 있습니다.
  • 반환 값: 다른 위젯(또는 위젯 트리)을 반환합니다.

간단한 예제: build 함수에서 텍스트 표시

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Build 함수 예제')),
        body: Center(
          child: Text('안녕하세요! Flutter를 배우고 있어요!'),
        ),
      ),
    );
  }
}

 


StatefulWidget과 build 함수

StatefulWidget에서는 상태가 변경될 때마다 build 함수가 호출되어 UI를 다시 그립니다.

상태에 따라 버튼을 누르면 카운터가 증가하는 예제

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int counter = 0;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('카운터 앱')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text('버튼을 누른 횟수: $counter', style: TextStyle(fontSize: 24)),
              ElevatedButton(
                onPressed: () {
                  setState(() {
                    counter++;
                  });
                },
                child: Text('숫자 증가'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}


build 함수의 중요한 특징

  1. 반복 호출:
    • build 함수는 앱 상태가 변경될 때마다 반복적으로 호출됩니다.
    • 하지만 Flutter는 효율적으로 변경된 부분만 업데이트하므로 걱정하지 않아도 됩니다.
  2. 항상 위젯 반환:
    • build 함수는 항상 위젯 또는 위젯 트리를 반환해야 합니다.
  3. UI 선언:
    • build 함수는 "어떤 UI를 보여줄지"만 선언하며, 렌더링이나 UI 업데이트는 Flutter가 자동으로 처리합니다.
반응형
반응형


Flutter의 createElement 함수란?

Flutter에서 UI는 위젯(Widget)을 기반으로 구성됩니다. 위젯은 화면의 시각적 요소를 정의하지만, 자체적으로 렌더링되거나 상태를 유지하지는 않습니다. 이 역할은 Element라는 객체가 담당합니다. createElement 함수는 위젯이 Element를 생성하는 데 사용되는 중요한 메서드입니다. 이 글에서는 createElement의 역할과 사용 방법을 초보자도 쉽게 이해할 수 있도록 설명하겠습니다.


Element와 Widget의 차이

Flutter에서 WidgetElement는 밀접하게 연결되어 있지만 역할이 다릅니다.

  • Widget: UI의 정적인 설명서(blueprint)로, 화면에 표시할 구조와 스타일을 정의합니다.
  • Element: Widget의 구체적인 구현체로, 렌더링 트리에서 위젯을 관리하고 상태를 유지합니다.

createElement 함수는 Widget에서 Element를 생성하는 데 사용됩니다.


createElement의 역할

Flutter의 모든 위젯은 createElement 메서드를 가지고 있습니다. 이 메서드는 위젯을 기반으로 올바른 타입의 Element를 생성합니다.

  • StatelessWidget: StatelessElement를 생성합니다.
  • StatefulWidget: StatefulElement를 생성합니다.
  • RenderObjectWidget: RenderObjectElement를 생성합니다.

이렇게 생성된 Element는 위젯 트리와 렌더링 트리에서 중요한 역할을 합니다.


createElement 함수의 기본 구조

Flutter에서는 createElement가 위젯 클래스 내에서 오버라이드(Override)될 수 있습니다. 아래는 기본적인 사용 예입니다.

기본 예제:

@override
Element createElement() {
  return MyCustomElement(this);
}

이 코드는 현재 위젯에서 새로운 Element를 생성하며, 이 Element는 UI 트리에서 위젯을 관리하는 역할을 합니다.

 


실제 예제: 커스텀 위젯과 createElement

아래는 createElement를 사용하여 커스텀 위젯과 Element를 정의하는 간단한 예제입니다.

1. 커스텀 위젯 정의

import 'package:flutter/widgets.dart';

// 커스텀 위젯
class MyCustomWidget extends Widget {
  final String message;

  MyCustomWidget(this.message);

  @override
  Element createElement() {
    return MyCustomElement(this);
  }
}

 

2. 커스텀 Element 정의

class MyCustomElement extends Element {
  MyCustomElement(MyCustomWidget widget) : super(widget);

  @override
  void mount(Element? parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    print('Element Mounted: ${(widget as MyCustomWidget).message}');
  }

  @override
  void update(Widget newWidget) {
    super.update(newWidget);
    print('Element Updated: ${(widget as MyCustomWidget).message}');
  }
}

 

3. 사용 예제

void main() {
  final widget = MyCustomWidget('Hello, Flutter!');
  final element = widget.createElement();

  element.mount(null, null); // Element가 트리에 추가됨
}

 


createElement가 중요한 이유

  1. 위젯 트리와 렌더링 트리 연결:
    • createElement는 위젯 트리와 렌더링 트리 간의 연결을 담당합니다. 이를 통해 Flutter는 효율적으로 UI를 업데이트하고 다시 그립니다.
  2. 커스텀 위젯 개발:
    • 특별한 요구 사항이 있을 때, createElement를 오버라이드하여 커스텀 위젯과 Element를 정의할 수 있습니다.
  3. 성능 최적화:
    • Element는 상태를 유지하므로 Flutter는 위젯 트리를 완전히 다시 그리지 않고도 UI를 효율적으로 업데이트할 수 있습니다.

 

createElement와 Flutter 생명주기

createElement는 Flutter 위젯의 생명주기에서 초기 단계에 호출됩니다. 아래는 주요 생명주기 단계를 요약한 것입니다:

  1. Widget 생성: 위젯 트리에서 새 위젯이 생성됩니다.
  2. Element 생성: 위젯의 createElement 메서드가 호출되어 Element가 생성됩니다.
  3. mount: Element가 부모 트리에 연결되고 초기화됩니다.
  4. build: Element가 위젯의 UI를 렌더링합니다.

 

반응형
반응형

Dart의 Constructor(생성자)

생성자(Constructor)는 클래스의 인스턴스를 생성하고 초기화하는 데 사용되는 특별한 메서드입니다. Dart에서 생성자는 클래스와 동일한 이름을 가지며, 객체를 생성할 때 호출됩니다. 생성자는 객체의 초기 상태를 설정하거나, 특정 작업을 수행하면서 객체를 초기화할 때 주로 사용됩니다.


생성자의 주요 특징

  1. 클래스와 동일한 이름을 가집니다.
  2. 객체가 생성될 때 자동으로 호출됩니다.
  3. 반환 타입이 없습니다.
  4. 기본 생성자가 없을 경우, Dart는 자동으로 기본 생성자(매개변수 없는 생성자)를 제공합니다.

생성자의 종류

1. 기본 생성자

Dart에서 생성자는 클래스와 동일한 이름을 가지며, 매개변수를 통해 필드 값을 초기화할 수 있습니다.

예시:

class Person {
  String name;
  int age;

  // 기본 생성자
  Person(String name, int age) {
    this.name = name; // this를 사용하여 클래스 필드를 초기화
    this.age = age;
  }

  void introduce() {
    print('안녕하세요! 저는 $name이고, 나이는 $age입니다.');
  }
}

void main() {
  Person person = Person('홍길동', 25);
  person.introduce();
}

출력:

안녕하세요! 저는 홍길동이고, 나이는 25입니다.

2. 간략화된 생성자 (축약 생성자)

Dart에서는 축약 문법을 사용하여 필드를 간단하게 초기화할 수 있습니다. this 키워드를 사용하여 클래스의 필드를 직접 초기화합니다.

예시:

class Person {
  String name;
  int age;

  // 축약 생성자
  Person(this.name, this.age);

  void introduce() {
    print('안녕하세요! 저는 $name이고, 나이는 $age입니다.');
  }
}

void main() {
  Person person = Person('홍길동', 25);
  person.introduce();
}

출력:

안녕하세요! 저는 홍길동이고, 나이는 25입니다.

3. 이름이 지정된 생성자 (Named Constructor)

여러 생성자를 사용할 경우, 이름을 지정하여 다양한 방식으로 객체를 초기화할 수 있습니다.

예시:

class Person {
  String name;
  int age;

  // 기본 생성자
  Person(this.name, this.age);

  // 이름이 지정된 생성자
  Person.namedConstructor(String name) {
    this.name = name;
    this.age = 0; // 나이는 기본값으로 설정
  }

  void introduce() {
    print('안녕하세요! 저는 $name이고, 나이는 $age입니다.');
  }
}

void main() {
  Person person1 = Person('홍길동', 25);
  person1.introduce();

  Person person2 = Person.namedConstructor('이순신');
  person2.introduce();
}

출력:

안녕하세요! 저는 홍길동이고, 나이는 25입니다.
안녕하세요! 저는 이순신이고, 나이는 0입니다.

4. 초기화 리스트 (Initializer List)

초기화 리스트는 생성자가 본문을 실행하기 전에 필드 값을 초기화하는 데 사용됩니다. 주로 final 필드와 같이 한 번만 초기화 가능한 필드를 설정할 때 유용합니다.

예시:

class Circle {
  final double radius;
  final double area;

  // 초기화 리스트를 사용한 생성자
  Circle(this.radius) : area = 3.14 * radius * radius;

  void showArea() {
    print('반지름: $radius, 면적: $area');
  }
}

void main() {
  Circle circle = Circle(5);
  circle.showArea();
}

출력:

반지름: 5.0, 면적: 78.5

5. 팩토리 생성자 (Factory Constructor)

팩토리 생성자는 새로운 인스턴스를 생성하는 대신 기존의 인스턴스를 반환하거나 특정 조건에 따라 객체를 생성해야 할 때 사용됩니다.

예시:

class Singleton {
  static final Singleton _instance = Singleton._internal();

  // private 생성자
  Singleton._internal();

  // 팩토리 생성자
  factory Singleton() {
    return _instance;
  }
}

void main() {
  var obj1 = Singleton();
  var obj2 = Singleton();

  print(obj1 == obj2); // true (같은 객체를 반환)
}

출력:

true

생성자를 사용할 때 주의할 점

  1. 매개변수 순서와 이름에 주의: 필드 이름과 매개변수 이름이 같을 때는 this를 사용하여 혼동을 피합니다.
  2. final 또는 const 필드 초기화: final 필드는 반드시 생성자를 통해 초기화해야 하며, const 필드는 컴파일 시점에 값이 결정되어야 합니다.
  3. 생성자와 메서드 구분: 생성자는 반환 타입이 없으며, 클래스와 동일한 이름을 가집니다.
반응형
반응형


Flutter에서 위젯(Widget)은 UI 구성 요소의 기본 단위입니다. Flutter는 모든 것을 위젯으로 구성하며, 화면에 표시되는 텍스트, 이미지, 버튼, 레이아웃까지 모두 위젯으로 처리됩니다. Flutter에서 위젯을 잘 이해하는 것은 효과적인 UI 설계와 앱 개발에 중요한 요소입니다. 이 글에서는 Flutter 위젯의 개념과 종류를 쉽게 설명하겠습니다.



Flutter 위젯이란?

위젯(Widget)은 Flutter에서 화면을 구성하는 기본적인 요소입니다. 위젯은 UI를 표현하는 데 필요한 모든 것들을 정의합니다. 예를 들어, 텍스트를 표시하거나 버튼을 만들거나, 레이아웃을 설정하는 것 모두 위젯을 통해 이루어집니다.

위젯의 특성

구성 요소: Flutter 앱에서 모든 것은 위젯입니다. 화면에 보이는 텍스트, 버튼, 이미지, 리스트 등 모든 것이 위젯으로 구현됩니다.

구성 가능성: 위젯은 다른 위젯을 포함할 수 있으며, 이를 통해 복잡한 UI를 구성할 수 있습니다.

불변성: 위젯은 불변(immutable) 객체입니다. 한 번 생성된 위젯은 상태를 변경할 수 없고, 상태 변경은 StatefulWidget을 사용하여 처리합니다.

 


위젯의 종류

Flutter에서 위젯은 크게 StatelessWidgetStatefulWidget으로 나뉩니다.

1. StatelessWidget (상태 없는 위젯)

StatelessWidget상태를 변경하지 않는 위젯입니다. UI가 한 번 설정되면 변경되지 않으며, 생성 시 주어진 데이터만을 사용하여 화면을 구성합니다. 예를 들어, 텍스트를 표시하거나 단순한 아이콘을 화면에 표시할 때 사용됩니다.

import 'package:flutter/material.dart';

class MyTextWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Hello, Flutter!', style: TextStyle(fontSize: 24)),
    );
  }
}

특징:

  • 상태를 갖지 않음: 위젯 자체는 상태를 가지지 않으며, 생성 시 주어진 데이터를 기반으로 화면을 그립니다.
  • 빠르고 효율적: 상태 변경이 없으므로 성능이 뛰어납니다.
  • UI가 변경되지 않는 부분에 사용합니다.

2. StatefulWidget (상태 있는 위젯)

StatefulWidget상태를 변경할 수 있는 위젯입니다. 예를 들어, 버튼 클릭, 텍스트 입력, 슬라이더 조정 등 사용자의 입력에 따라 UI가 변경되는 경우에 사용됩니다. StatefulWidget은 두 부분으로 나뉩니다: 위젯 자체와 상태를 관리하는 State 클래스입니다.

예시:

import 'package:flutter/material.dart';

class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text('Counter: $_counter', style: TextStyle(fontSize: 24)),
          ElevatedButton(
            onPressed: _incrementCounter,
            child: Text('Increment'),
          ),
        ],
      ),
    );
  }
}

특징:

  • 상태를 유지: StatefulWidget은 상태를 유지하며, UI가 변경될 때마다 setState() 메서드를 호출하여 상태를 업데이트합니다.
  • 상태 관리: 상태를 관리하는 State 클래스를 사용하여 UI 변경을 처리합니다.
  • 사용자 인터랙션: 버튼 클릭, 입력 필드 등 사용자의 입력에 따라 UI가 동적으로 변경되어야 할 때 사용됩니다.

Flutter에서 자주 사용되는 기본 위젯

Flutter에서 제공하는 많은 기본 위젯들은 UI를 빠르게 구성하는 데 유용합니다. 여기에는 레이아웃을 구성하는 위젯, 텍스트를 표시하는 위젯, 상호작용하는 위젯들이 포함됩니다.

1. Text 위젯

텍스트를 화면에 표시하는 위젯입니다.

Text('Hello, Flutter!', style: TextStyle(fontSize: 20))

2. Container 위젯

모든 종류의 UI 요소를 배치하고 스타일을 적용할 수 있는 가장 기본적인 레이아웃 위젯입니다. 크기, 색상, 마진 등을 설정할 수 있습니다.

예시:

Container(
  width: 200,
  height: 100,
  color: Colors.blue,
  child: Center(child: Text('Hello, World!')),
)

3. ColumnRow 위젯

Column은 세로로, Row는 가로로 위젯을 배치하는 레이아웃 위젯입니다.

예시 (Column):

Column(
  children: <Widget>[
    Text('Item 1'),
    Text('Item 2'),
    Text('Item 3'),
  ],
)

4. ElevatedButton 위젯

버튼을 만들 때 사용하는 위젯입니다. 클릭 이벤트를 처리할 수 있습니다.

예시:

ElevatedButton(
  onPressed: () {
    print('Button clicked!');
  },
  child: Text('Click Me'),
)

5. Image 위젯

이미지를 화면에 표시하는 위젯입니다.

예시:

Image.asset('assets/image.png')  // 로컬 이미지

 

 

반응형
반응형


Dart는 Flutter 앱 개발에 사용되는 언어로, 다양한 변수 타입을 제공합니다. 프로그래밍을 배우는 데 있어, 변수 타입을 이해하는 것은 매우 중요합니다. 변수는 데이터를 저장하고 조작하는 기본적인 단위이기 때문입니다. 이번 글에서는 Dart에서 제공하는 주요 내장 변수 타입에 대해 초보자들도 쉽게 이해할 수 있도록 설명하겠습니다.


1. 숫자 타입 (int, double)

Dart에서 숫자는 두 가지 주요 타입으로 나눠집니다: 정수실수입니다.

  • int: 정수형 변수로, 소수점이 없는 숫자를 저장합니다.
  • double: 실수형 변수로, 소수점을 포함하는 숫자를 저장합니다.

예시:

void main() {
  int age = 25;        // 정수형 변수
  double price = 10.99; // 실수형 변수
  
  print(age);   // 출력: 25
  print(price); // 출력: 10.99
}

주요 특징:

  • int는 소수점 없이 정수만 저장할 수 있습니다.
  • double은 소수점이 포함된 숫자, 예를 들어 10.99 같은 값을 저장할 수 있습니다.

2. 문자열 타입 (String)

**String**은 문자나 단어, 문장 등을 저장하는 변수 타입입니다. 즉, 텍스트 데이터를 다룰 때 사용됩니다.

예시:

void main() {
  String greeting = "Hello, Flutter!";
  
  print(greeting); // 출력: Hello, Flutter!
}

주요 특징:

  • 문자열은 큰따옴표(")나 작은따옴표(')로 감쌀 수 있습니다.
  • 여러 줄에 걸친 문자열을 사용할 때는 ''' 또는 **"""**를 사용할 수 있습니다.

3. 불리언 타입 (bool)

**bool**은 참(true) 또는 거짓(false) 값을 저장하는 변수 타입입니다. 주로 조건문(if, else)이나 논리 연산에서 사용됩니다.

예시:

void main() {
  bool isFlutterFun = true;
  bool isCold = false;
  
  print(isFlutterFun); // 출력: true
  print(isCold);       // 출력: false
}

주요 특징:

  • bool 타입은 true 또는 false 두 값만 가질 수 있습니다.
  • 주로 조건문에서 사용되어 프로그램 흐름을 제어합니다.

4. 리스트 타입 (List)

**List**는 여러 개의 값을 순서대로 저장하는 배열 같은 역할을 합니다. 리스트는 다양한 데이터 타입의 값을 하나의 변수에 저장할 수 있는 유용한 타입입니다.

예시:

void main() {
  List<String> fruits = ["Apple", "Banana", "Orange"];
  
  print(fruits); // 출력: [Apple, Banana, Orange]
  print(fruits[0]); // 출력: Apple
}

주요 특징:

  • 리스트는 **대괄호([])**로 묶어서 여러 값을 저장합니다.
  • 인덱스를 사용해 리스트의 특정 항목에 접근할 수 있습니다. 인덱스는 0부터 시작합니다.

5. 맵 타입 (Map)

**Map**은 **키(key)**와 **값(value)**을 쌍으로 저장하는 데이터 타입입니다. 리스트가 순서대로 저장되는 반면, 맵은 키를 통해 값을 검색하는 방식입니다.

예시:

void main() {
  Map<String, String> capitals = {
    'Korea': 'Seoul',
    'Japan': 'Tokyo',
    'USA': 'Washington, D.C.'
  };
  
  print(capitals); // 출력: {Korea: Seoul, Japan: Tokyo, USA: Washington, D.C.}
  print(capitals['Korea']); // 출력: Seoul
}

주요 특징:

  • 맵은 **중괄호({})**로 묶어서 키-값 쌍을 저장합니다.
  • 를 사용해 에 접근할 수 있습니다. 예를 들어, capitals['Korea']는 Seoul을 반환합니다.

6. 동적 타입 (dynamic)

**dynamic**은 어떤 타입이든 저장할 수 있는 타입입니다. 변수의 타입을 고정하지 않고, 실행 중에 변경할 수 있기 때문에 유연하게 사용할 수 있지만, 타입 안전성이 떨어질 수 있어 주의해서 사용해야 합니다.

예시:

void main() {
  dynamic something = 42;  // 정수 저장
  print(something);        // 출력: 42
  
  something = "Flutter";   // 문자열로 변경
  print(something);        // 출력: Flutter
}

주요 특징:

  • dynamic은 타입을 동적으로 결정하기 때문에 변수에 어떤 값이든 저장할 수 있습니다.
  • 타입을 명확히 정의하지 않기 때문에 타입 오류를 쉽게 발견할 수 없습니다. 이를 신중하게 사용해야 합니다.

7. Set 타입

**Set**은 중복되지 않는 값을 저장하는 집합을 나타내는 자료형입니다. 리스트와 유사하지만, 값의 순서는 보장하지 않으며, 중복된 값을 허용하지 않습니다. 주로 유일한 값들을 다뤄야 할 때 유용합니다.

void main() {
  Set<String> fruits = {"Apple", "Banana", "Orange", "Apple"};
  
  print(fruits); // 출력: {Apple, Banana, Orange}
  
  fruits.add("Grapes");  // 새로운 요소 추가
  print(fruits); // 출력: {Apple, Banana, Orange, Grapes}
}

주요 특징:

  • 중복되지 않는 값을 저장합니다. 예를 들어 "Apple"을 두 번 추가해도 한 번만 저장됩니다.
  • 순서가 보장되지 않습니다. 즉, 값이 저장되는 순서와 출력되는 순서는 다를 수 있습니다.
  • Set은 **add()**나 remove() 메서드를 사용하여 값을 추가하거나 삭제할 수 있습니다.
  • 검색 및 포함 여부 체크가 빠른 편입니다.

Set의 사용 예:

  • 고유한 값 목록을 관리해야 할 때 유용합니다.
  • 예를 들어, 사용자가 방문한 페이지 목록, 중복된 이메일을 처리하는 시스템 등에서 활용됩니다.

8. Enum 타입

Enum(열거형)은 여러 개의 관련 상수 값을 그룹화하여 하나의 타입으로 묶을 때 사용됩니다. Enum을 사용하면 값의 집합을 명확하게 정의하고, 코드에서 의미 있는 이름을 사용할 수 있어 가독성과 유지보수성이 높아집니다.

예시:

void main() {
  var status = Status.pending;
  
  switch (status) {
    case Status.pending:
      print("Processing...");
      break;
    case Status.completed:
      print("Completed!");
      break;
    case Status.failed:
      print("Failed!");
      break;
  }
}

enum Status {
  pending,   // 대기 중
  completed, // 완료됨
  failed     // 실패
}
반응형

'Flutter' 카테고리의 다른 글

다트 이해하기 - (4) Constructor(생성자)  (0) 2024.12.01
다트 이해하기 - (3) 위젯이란?  (0) 2024.12.01
다트 이해하기 - (1) 변수  (0) 2024.12.01
플러터 기본위젯  (0) 2024.03.30
typedef와 함수  (0) 2024.03.30
반응형

1. 플러터에서 변수란?

플러터(Flutter)는 Dart 언어를 기반으로 동작하며, Dart에서도 변수는 데이터를 저장하고 관리하기 위한 기본 요소입니다. Dart의 변수는 프로그램 내에서 값들을 저장하고 이를 조작하는 데 사용됩니다. Flutter를 사용한 UI 구성이나 상태 관리에서도 변수는 필수적입니다.


2. 변수 선언과 초기화

Dart에서 변수를 선언하려면 var, final, 또는 const 키워드를 주로 사용합니다. 또한, 변수의 자료형을 명시적으로 선언할 수도 있습니다.

1. var 키워드

  • Dart는 변수에 저장된 값에 따라 자료형을 자동으로 추론합니다.
  • 한 번 값이 할당되면 같은 자료형의 값만 저장 가능합니다.
void main() {
  var name = "가디사는 개발자 주녘"; // Dart가 자료형을 String으로 추론
  print(name); // 출력: 가디사는 개발자 주녘
}

 

2. 자료형 명시

  • 변수의 자료형을 명확히 정의할 수도 있습니다.
void main() {
  String name = "Dart"; // 명시적으로 자료형 선언
  int age = 25;         // 정수 자료형
  double height = 5.9;  // 실수 자료형
  bool isFlutterDev = true; // 불리언 자료형
  print("$name, $age, $height, $isFlutterDev");
}

 

3. final과 const

  • final: 런타임에 값이 결정되며, 이후 변경 불가능.
  • const: 컴파일 타임에 값이 결정되며, 상수로 사용.
void main() {
  final String appName = "MyApp"; // 실행 중 할당된 값은 변경 불가능
  const String framework = "Flutter"; // 컴파일 시점에 값이 고정
  print("$appName uses $framework.");
}

 


3.  변수 사용 시 주의점

  1. 변수의 범위(Scope) 이해하기
    • 변수가 선언된 위치에 따라 접근 가능한 범위가 달라집니다.
    • 예를 들어, 함수 내에서 선언된 변수는 함수 외부에서 접근할 수 없습니다.
  2. 변수 이름은 명확하게
    • 변수 이름은 역할을 명확히 나타내야 가독성이 높아집니다.
    • 예: counter는 "카운트" 용도로 사용되는 변수임을 바로 알 수 있습니다.
  3. 불필요한 변수 선언 피하기
    • 너무 많은 변수를 선언하면 코드가 복잡해질 수 있으니 꼭 필요한 변수만 선언해야합니다.

4. 플러터에서 변수의 중요성

플러터에서 변수는 다음과 같은 다양한 곳에서 사용됩니다:

  1. UI 상태 관리 (Stateful Widget과 State 클래스)
  2. 사용자 입력값 저장
  3. API 호출 결과 데이터 저장
  4. 애니메이션 상태 추적

5. Dart의 Null Safety란?

Null Safety는 Dart 언어의 중요한 기능으로, 개발자가 **null 값으로 인해 발생할 수 있는 오류(null reference errors)**를 방지할 수 있도록 돕는 메커니즘입니다. Null Safety는 Dart 2.12 버전부터 기본적으로 활성화되었으며, 플러터 앱 개발에서도 핵심적인 역할을 합니다.


6. 왜 Null Safety가 필요한가?

null 값은 변수에 아무 값도 저장되지 않은 상태를 나타냅니다. 하지만 null 값에 접근하거나 조작하려 하면 프로그램이 오류를 일으킵니다. 이를 Null Pointer Exception이라고 부르며, 많은 프로그래밍 언어에서 흔히 발생하는 문제입니다.

예를 들어:

String? name; // name은 null일 수 있음
print(name.length); // NullPointerException 발생

Dart의 Null Safety는 null이 될 수 있는 변수와 null이 될 수 없는 변수를 명확히 구분함으로써 이런 문제를 방지합니다.

 


7. Null Safety의 주요 개념

1. null이 될 수 없는 변수

기본적으로 Dart에서 선언된 변수는 null 값을 가질 수 없습니다. 이를 non-nullable 변수라고 합니다.

void main() {
  String name = "Flutter"; // null이 될 수 없음
  print(name); // 정상 출력: Flutter

  name = null; // 컴파일 오류 발생
}

 

2. null이 될 수 있는 변수

변수 뒤에 ?를 붙이면 해당 변수는 nullable이 되어 null 값을 가질 수 있습니다.

void main() {
  String? name; // null이 될 수 있음
  print(name); // 출력: null

  name = "Dart";
  print(name); // 출력: Dart
}

8. Null Safety를 사용하는 방법

1. null 값 확인

null이 될 수 있는 변수에 접근할 때는 반드시 null 여부를 확인해야 합니다.

예: null 체크

void main() {
  String? name;
  if (name != null) {
    print(name.length); // name이 null이 아닐 때만 length 접근
  }
}

 

예: null 병합 연산자 ??

?? 연산자는 null일 경우 대체 값을 반환합니다.

void main() {
  String? name;
  print(name ?? "No Name"); // 출력: No Name
}

2. null 값 사용 강제

! 연산자를 사용하면 null 값을 사용할 수 있다고 Dart에 강제로 알릴 수 있습니다. 이는 개발자가 null이 아님을 확신할 때만 사용해야 합니다.

⚠️ 잘못 사용하면 런타임 오류를 발생시킬 수 있으니 주의가 필요합니다.
void main() {
  String? name;
  name = "Flutter";
  print(name!.length); // name이 null이 아님을 보장
}

3. late 키워드

late 키워드는 변수를 나중에 초기화하겠다는 것을 Dart에 명시적으로 알립니다. null이 아닌 값을 보장해야 할 때 유용합니다.

void main() {
  late String name; // 초기값 없이 선언
  name = "Dart"; // 나중에 초기화
  print(name); // 출력: Dart
}

 


4. nullable 리스트

리스트에도 null safety가 적용됩니다. 예를 들어:

  • List<String>: null 값을 포함하지 않는 문자열 리스트
  • List<String?>: null 값을 포함할 수 있는 문자열 리스트
void main() {
  List<String> names = ["Alice", "Bob"];
  List<String?> nullableNames = ["Alice", null, "Bob"];

  print(names); // 출력: [Alice, Bob]
  print(nullableNames); // 출력: [Alice, null, Bob]
}

Null Safety가 Flutter에서 중요한 이유

플러터 앱 개발에서는 상태 관리, 사용자 입력 처리, 비동기 작업 등에서 null이 자주 발생할 수 있습니다. Null Safety는 다음과 같은 문제를 예방합니다:

  1. Widget 초기화 오류 방지
    위젯이나 상태(State)를 초기화할 때 null 값이 의도치 않게 사용되는 경우를 방지합니다.
  2. 비동기 작업에서 null 값 처리
    API 호출이나 데이터베이스에서 데이터를 가져올 때 null 값이 반환될 가능성을 처리할 수 있습니다.
  3. 안정성과 유지보수성 향상
    null로 인해 발생하는 오류를 컴파일 시점에서 잡아주므로 앱의 안정성이 향상됩니다.

 

요약: Null Safety의 장점

  • 컴파일 시점에서 null 관련 오류 탐지
    앱 실행 전에 null로 인해 발생할 수 있는 문제를 예방합니다.
  • 코드 안정성과 신뢰성 향상
    명확한 nullable 및 non-nullable 구분으로 오류를 줄입니다.
  • 가독성과 유지보수성 향상
    변수의 null 가능성을 코드에서 쉽게 확인할 수 있습니다.
반응형

'Flutter' 카테고리의 다른 글

다트 이해하기 - (3) 위젯이란?  (0) 2024.12.01
다트 이해하기 - (2) 내장 변수타입  (0) 2024.12.01
플러터 기본위젯  (0) 2024.03.30
typedef와 함수  (0) 2024.03.30
dart 이론  (0) 2024.03.30
반응형

위젯은 자식을 하나만 갖는 위젯과 자식을 여러개를 갖는 위젯으로 나뉩니다.
 
자식을 하나만 갖는 대표적인 위젯들은 아래와 같고, 대체로 child 매개변수를 입력받습니다.
 

  • Container 위젯 : 자식을 담는 컨테이너 역할을 합니다. 다만 단순하게 자식을 담는 역할을 하는게 아니라 배경색, 너비와 높이, 테두리 등의 디자인을 지정할 수 있습니다.
  • GestureDetector 위젯 : 플러터에서 제공하는 제스처 기능을 자식 위젯에서 인식하는 위젯, 탭이나 드래그 그리고 더블 클릭 같은 제스처 기능이 자식 위젯에 인식됐을 때 함수를 실행할 수 있습니다.
  • SizedBox 위젯 : 높이와 너비를 지정하는 위젯, Container 위젯과 다르게 디자인적 요소는 적용할 수 없고, const 생성자로 선언할 수 있어서 퍼포먼스 측면에서 더 효율적

 
다수의 자식을 입력할 수 있는 위젯은 children 매개변수를 입력받으며 리스트로 여러 위젯을 입력할 수 있습니다.
 

  • Column 위젯 : children 매개변수에 입력된 모든 위젯들을 세로로 배치
  • Row 위젯 : children 매개변수에 입력된 모두 위젯들을 가로로 배치
  • ListView 위젯 : 리스트를 구현할 때 사용, children 매개변수에 다수의 위젯을 입력할 수 있으며 입력된 위젯이 화면을 벗어나게 되면 스크롤이 가능

 

Children 와 Child의 차이점

child는 위젯을 하나만 추가할 수 있고, children은 여럿을 추가할 수 있습니다.
대부분의 위젯은 child 또는 children 매개변수를 하나만 제공합니다. child와 children 매개변수를 동시에 입력받는 위젯은 존재하지 않습니다.
 
 

제스처 관련 위젯

사용자가 키보드로 글자를 입력하는 행위 이외 모든 입력을 플러터에서는 제스처라고 부릅니다.
화면을 한 번 탭하거나, 두 번 탭하거나, 길게 누르는 행동 모두가 제스처 입니다.
GestureDetector 위젯은 모든 제스처를 매개변수로 제공해줍니다. 제스처 관련 위젯은 하위 위젯에 탭이나 드래그처럼 특정 제스처가 입력됬을 때 인지하고 콜백 함수를 실행합니다.
 

Button 위젯

머터리얼 패키지에서 기본 제공하는 버튼으로 TextButton, OutlinedButton, ElevatedButton이 있습니다. 이 세 개의 버튼은 모두 버튼을 누르면 색깔이 변경되는 리플 효과를 지원합니다.
 
🔷 TextButton

import 'package:flutter/material.dart';

void main(){
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: TextButton(
            // 클릭시 실행
            onPressed: (){
              print('버튼 눌림');
            },

            // 스타일 지정하기
            style: TextButton.styleFrom(
              // 주 색상 지정
              foregroundColor: Colors.red,
            ),
            child: Text('텍스트 버벝'),
          ),
        ),
      ),
    );
  }
}

 

 
 
🔷 OutlinedButton

import 'package:flutter/material.dart';

void main(){
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: OutlinedButton(
            // 클릭시 실행
            onPressed: (){
              print('버튼 눌림');
            },

            // 스타일 지정하기
            style: OutlinedButton.styleFrom(
              // 주 색상 지정
              foregroundColor: Colors.red,
            ),
            child: Text('아웃라인 버튼'),
          ),
        ),
      ),
    );
  }
}

 

 
 
🔷 ElevatedButton

import 'package:flutter/material.dart';

void main(){
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: ElevatedButton(
            // 클릭시 실행
            onPressed: (){
              print('버튼 눌림');
            },

            // 스타일 지정하기
            style: ElevatedButton.styleFrom(
              // 주 색상 지정
              backgroundColor: Colors.red,

            ),
            child: Text('엘리베이티드 버튼', style: TextStyle(color: Colors.white,),),
          ),
        ),
      ),
    );
  }
}

 

 

반응형

'Flutter' 카테고리의 다른 글

다트 이해하기 - (2) 내장 변수타입  (0) 2024.12.01
다트 이해하기 - (1) 변수  (0) 2024.12.01
typedef와 함수  (0) 2024.03.30
dart 이론  (0) 2024.03.30
TodoList App 만들기  (0) 2024.03.21
반응형

typedef 키워드는 함수의 시그니처를 정의하는 값으로 보면 됩니다.

여기서 시그니처란 반환값 타입, 매개변수 개수와 타입 등을 말합니다. 즉 함수 선언부를 정의하는 키워드입니다.

함수가 무슨 동작을 하는지에 대한 정의는 없습니다.

 

typedef Operation = void Function(int x, int y);

void add(int x, int y) {
  print('결과값 : ${x + y}');
}

void subtract(int x, int y) {
  print('결과값 : ${x - y}');
}


void main () {
  // typedef는 일반적인 변수의 타입처럼 사용가능
  Operation oper = add;
  oper(1, 2);

  // subract() 함수도 Operation에 해당되는 시그니처이므로 oper 변수에 저장 가능
  oper = subtract;
  oper(1, 2);
}
결과값 : 3
결과값 : -1
반응형

'Flutter' 카테고리의 다른 글

다트 이해하기 - (1) 변수  (0) 2024.12.01
플러터 기본위젯  (0) 2024.03.30
dart 이론  (0) 2024.03.30
TodoList App 만들기  (0) 2024.03.21
Flutter MVVM 패턴 - 1  (0) 2024.03.19

+ Recent posts