[FLUS 스터디 9주차] Flutter 기초 - Useful Widgets

sucream·2022년 10월 27일
0

flutter-study

목록 보기
17/17
post-custom-banner

지난주에는 위젯 자체와 관련된 유용한 유틸 위젯을 다뤘다면, 오늘은 전반적으로 유용한 위젯들을 다뤄보고자 한다.

PageView

여러 페이지를 하나의 페이지에서 슬라이드하여 이용할 수 있도록 하는 위젯이다. 기본적으로 수평 방향으로 슬라이드되며, scrollDirection 옵션을 통해 스크롤 방향을 변경할 수 있다. 또한 PageController를 통해 해당 뷰페이지와 관련된 설정을 진행할 수 있다.

// PageView 테스트
class PageViewTest extends StatelessWidget {
  const PageViewTest({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    // PageView와 관련된 설정을 할 수 있는 컨트롤러
    // 시작 페이지를 2번째 페이지로 설정
    // 각 페이지가 차지하는 영역을 1.5배로 설정
    final pageController =
        PageController(initialPage: 2, viewportFraction: 1.5);
    return Scaffold(
      body: PageView(
        controller: pageController,  // 컨트롤러 지정
        scrollDirection: Axis.vertical, // 수직 스크롤
        children: [
          Container(
            color: Colors.red,
            child: Center(
                child: Image.asset(
              'images/pic6.jpeg',
            )),
          ),
          Container(
            color: Colors.green,
            child: Center(
                child: Image.asset(
              'images/pic7.jpeg',
            )),
          ),
          Container(
            color: Colors.blue,
            child: Center(
                child: Image.asset(
              'images/pic8.jpeg',
            )),
          ),
        ],
      ),
    );
  }
}

Draggable

위젯이 드래그 가능하도록 해주는 위젯으로, 위젯을 드래그할 때, 드래그 중일때 배경, 데이터, 타겟 등을 지정할 수 있다.

class DragableTest extends StatefulWidget {
  const DragableTest({Key? key}) : super(key: key);

  
  State<DragableTest> createState() => _DragableTestState();
}

class _DragableTestState extends State<DragableTest> {
  int acceptedData = 0;

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Draggable(  // 드래그 가능한 위젯
              data: 10,  // 드래그할 때 전달할 데이터
              // 드래그 중인 위젯
              feedback: Container(
                width: 100,
                height: 100,
                color: Colors.green,
              ),
              // 드래그 중일때 백그라운드에 표시되는 위젯
              childWhenDragging: Container(
                width: 100,
                height: 100,
                color: Colors.blue,
              ),
              // 드래그 가능한 위젯
              child: Container(
                width: 100,
                height: 100,
                color: Colors.red,
              ),
            ),
            // 드래그 가능한 위젯이 놓여질 수 있는 곳
            // 해당 타겟은 int 타입의 데이터만 받을 수 있음
            DragTarget<int>(
              builder: (
                BuildContext context,
                List<dynamic> accepted,
                List<dynamic> rejected,
              ) {
                return Container(
                  height: 100.0,
                  width: 100.0,
                  color: Colors.cyan,
                  child: Center(
                    child: Text('Value is updated to: $acceptedData'),
                  ),
                );
              },
              onAccept: (int data) {  // 드래그 가능한 위젯이 놓여졌을 때 호출
                setState(() {
                  acceptedData += data;
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

FutureBuilder

비동기를 위해 사용하는 위젯으로, 나중에 완료될 것으로 가정하고 미리 빌드 후 향후 비동기 함수의 결과가 왔을 때 결과값을 보여줄 수 있도록 한다. 네트워크 통신 등에 자주 사용한다.
아래 예시는 의도적으로 3초를 대기하게 한 뒤 결과를 반환하는 것이다.

class FutureBuilderTest extends StatelessWidget {
  const FutureBuilderTest({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FutureBuilder(
          future: _getData(), // 비동기 처리를 수행할 함수
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            if (snapshot.hasData) {
              // 데이터가 수신되었을 때
              return Image.asset(snapshot.data);
            } else if (snapshot.hasError) {
              // 에러가 발생했을 때
              return Text('Error: ${snapshot.error}');
            } else {
              // 데이터가 수신되기 전
              return const CircularProgressIndicator();
            }
          },
        ),
      ),
    );
  }

  // 데이터를 가져오는 비동기 함수
  // 반환형이 Future이고 함수명 뒤에 async가 붙는다.
  Future<String> _getData() async {
    await Future.delayed(const Duration(seconds: 3));
    return 'images/pic12.jpeg';
  }
}

StreamBuilder

위에서 사용한 FutureBuilder와 거의 동일하지만 약간 다르다. FutureBuilder는 일회성으로 발생하는 비동기 처리에 사용하고, StreamBuilder는 다회성 데이터 획득에 사용된다. 여기서 스트림이라고 하는것은 데이터가 들어오고 나가는 통로를 의미한다.

아래 예시는 여러 이미지가 순서대로 전달되는 것이다.

// StreamBuilder 테스트
class StreamBuilderTest extends StatelessWidget {
  const StreamBuilderTest({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: StreamBuilder(
          stream: _getStream(), // 비동기 처리를 수행할 함수
          builder: (BuildContext context, AsyncSnapshot snapshot) {
            if (snapshot.hasData) {
              // 데이터가 수신되었을 때
              return Image.asset(snapshot.data);
            } else if (snapshot.hasError) {
              // 에러가 발생했을 때
              return Text('Error: ${snapshot.error}');
            } else {
              // 데이터가 수신되기 전
              return const CircularProgressIndicator();
            }
          },
        ),
      ),
    );
  }

  Stream<String> _getStream() async* {
    await Future.delayed(const Duration(seconds: 3));

    for (int i = 1; i < 10; i++) {
      await Future.delayed(const Duration(seconds: 1));
      yield "images/pic$i.jpeg";
    }
  }
}

Refference

profile
작은 오븐의 작은 빵
post-custom-banner

0개의 댓글