컨테이너

[Flutter] Stack과 Positioned Class 본문

Development/Flutter

[Flutter] Stack과 Positioned Class

어항 2022. 2. 18. 17:33
반응형

대표적으로 위젯을 순서대로 배치할 수 있는 Class는 Column과 Row 입니다.

Column과 Row는 각각 세로, 가로 방향 순서대로 위젯들을 배치합니다.

 

두 Class는 쉽고 깔끔하게 위젯들을 원하는 방향으로 배치해주지만,

두 개의 도형이나 사진이 겹쳐있는 듯한 위젯을 만들어 사용하는데 한계가 있습니다. 

 

이번 글에선 위젯들의 위치를 원하는 곳에 배치할 수 있는 Stack과 Positioned Class를 알아보겠습니다.

 

 

혹시 Column와 Row Class가 궁금하신 분들은 아래 링크를 참고하시면 좋을 것 같습니다.

 

 

[Flutter] Row, Column Class

Row Class 예제코드 import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( t..

ahang.tistory.com

 

 


 

 

Stack Class

 

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: TestScreen(),
    );
  }
}

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

  @override
  _TestScreenState createState() => _TestScreenState();
}

class _TestScreenState extends State<TestScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Column'),
        centerTitle: true,
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            width: 450,
            height: 150,
            color: Colors.redAccent,
          ),
          Container(
            width: 350,
            height: 125,
            color: Colors.blueAccent,
          ),
          Container(
            width: 250,
            height: 100,
            color: Colors.cyanAccent,
          ),
          Container(
            width: 150,
            height: 75,
            color: Colors.purpleAccent,
          ),
        ],
      ),
    );
  }
}

위 코드는 오늘 실습에 사용될 베이스 코드입니다.

 

세로 방향으로 위젯을 배치하는 Column에 색과 크기가 다른 Container 4개가 들어 있습니다.

실행 화면은 아래와 같습니다.

 

 

그렇다면 Column이 아닌 Stack의 경우는 어떨까요?

 


 

class _TestScreenState extends State<TestScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Stack'),
        centerTitle: true,
      ),
      body: Container(
        width: MediaQuery.of(context).size.width * 1,
        height: MediaQuery.of(context).size.height * 1,
        child: Stack(
          children: [
            Container(
              width: 450,
              height: 150,
              color: Colors.redAccent,
            ),
            Container(
              width: 350,
              height: 125,
              color: Colors.blueAccent,
            ),
            Container(
              width: 250,
              height: 100,
              color: Colors.cyanAccent,
            ),
            Container(
              width: 150,
              height: 75,
              color: Colors.purpleAccent,
            ),
          ],
        ),
      ),
    );
  }
}

위 코드처럼 베이스 코드에서 Column을 Stack으로 바꾸면 아래와 같은 화면을 볼 수 있습니다.

 

 

 

Column은 위젯들을 순서대로 배치하므로 Container들이 겹칠 일이 없던 반면,

Stack은 단지 정해진 위치나 규칙 없이 위젯들을 배치만 하므로 Container들이 겹치는 것을 확인하실 수 있습니다.

 

따라서 Stack에선 위젯들의 위치를 사용자가 직접 정해줘야하는데,

이때 위치를 특정하기 위해 사용하는 위젯이 Positioned Class입니다.

 

 


 

Positioned Class

 

Positioned(
  top: 200,
  child: Container(
    width: 450,
    height: 150,
    color: Colors.redAccent,
  ),
)

 

방금 사용했던 코드에서 빨간색 Container의 코드를 위와 같이 변경해봅시다.

 

 

빨간색 Container의 위치가 변경된 것을 확인할 수 있습니다.

 

눈치가 빠르신 분들은 알아채셨겠지만, top: 200은 맨 위로부터 200px 떨어진 위치를 의미합니다.

만약 0이라면 맨 위로부터 0px 떨어진 곳에 위젯이 위치하게 됩니다.

즉, 위젯이 맨 위에 붙어있는 것이죠 (left, right, bottom도 동일).

 

 

Positioned는 아래와 같이 위젯의 위치를 설정할 수 있습니다.

top: ??
left: ??
right: ??
bottom: ??

그렇다면 다른 Container들도 위치를 지정해볼까요?

 

 

Top

Stack(
  children: [
    Positioned(
      top: 0,
      child: Container(
        width: 450,
        height: 150,
        color: Colors.redAccent,
      ),
    ),
    Positioned(
      top: 100,
      child: Container(
        width: 350,
        height: 125,
        color: Colors.blueAccent,
      ),
    ),
    Positioned(
      top: 200,
      child: Container(
        width: 250,
        height: 100,
        color: Colors.cyanAccent,
      ),
    ),
    Positioned(
      top: 300,
      child: Container(
        width: 150,
        height: 75,
        color: Colors.purpleAccent,
      ),
    ),
  ],
)

 

 


 

Bottom

Stack(
  children: [
    Positioned(
      bottom: 0,
      child: Container(
        width: 450,
        height: 150,
        color: Colors.redAccent,
      ),
    ),
    Positioned(
      bottom: 100,
      child: Container(
        width: 350,
        height: 125,
        color: Colors.blueAccent,
      ),
    ),
    Positioned(
      bottom: 200,
      child: Container(
        width: 250,
        height: 100,
        color: Colors.cyanAccent,
      ),
    ),
    Positioned(
      bottom: 300,
      child: Container(
        width: 150,
        height: 75,
        color: Colors.purpleAccent,
      ),
    ),
  ],
)

 

 


 

주의사항

 

Stack(
  children: [
    Positioned(
      child: Container(
        width: 450,
        height: 150,
        color: Colors.redAccent,
      ),
    ),
    Positioned(
      child: Container(
        width: 150,
        height: 75,
        color: Colors.blueAccent,
      ),
    ),
  ],
)

 

Stack은 맨 마지막에 생성된 위젯이 가장 위로 옵니다.

 

위 코드를 보시면 파란색 Container가 빨간색 Container보다 크기는 작지만,

마지막에 생성되어 빨간색 Container의 위에 생성된 것을 확인할 수 있습니다.

 

 


 

Stack(
  children: [
    Positioned(
      child: Container(
        width: 150,
        height: 75,
        color: Colors.blueAccent,
      ),
    ),
    Positioned(
      child: Container(
        width: 450,
        height: 150,
        color: Colors.redAccent,
      ),
    ),
  ],
)

 

반면 위 코드의 경우 파란색 Container가 빨간색 Container보다 크기도 작은데,

먼저 생성되므로 빨간색 Container의 뒤에 있어 보이지 않는 것을 확인할 수 있습니다.

 

 

따라서 상황을 고려하여 위젯의 생성 순서를 정하시면,

이전보다 훨씬 더 다양한 디자인의 위젯들을 생성하실 수 있습니다.

 

더 공부하고 싶으신 분들은 아래 링크를 참조하시면 좋을 것 같습니다.

 

 

Stack class - widgets library - Dart API

A widget that positions its children relative to the edges of its box. This class is useful if you want to overlap several children in a simple way, for example having some text and an image, overlaid with a gradient and a button attached to the bottom. Ea

api.flutter.dev

 

Positioned class - widgets library - Dart API

A widget that controls where a child of a Stack is positioned. A Positioned widget must be a descendant of a Stack, and the path from the Positioned widget to its enclosing Stack must contain only StatelessWidgets or StatefulWidgets (not other kinds of wid

api.flutter.dev

 

반응형
Comments