Stack과 Positioned

Stack과 Positioned 위젯은 함께 작동하여 자식 위젯들을 정확한 위치에 배치하는 레이어드 레이아웃을 만듭니다.

속성

Stack 속성

  • children: Widget[] - 쌓을 자식 위젯들의 목록
  • alignment: Alignment - 위치가 지정되지 않은 자식들의 정렬 방법 (기본값: “topLeft”)
    • “topLeft”, “topCenter”, “topRight” - 상단 왼쪽, 상단 중앙, 상단 오른쪽
    • “centerLeft”, “center”, “centerRight” - 중앙 왼쪽, 중앙, 중앙 오른쪽
    • “bottomLeft”, “bottomCenter”, “bottomRight” - 하단 왼쪽, 하단 중앙, 하단 오른쪽
  • fit: StackFit - 위치가 지정되지 않은 자식들의 크기 조정 방법
    • “loose” (기본값) - 자식들이 Stack보다 작을 수 있음
    • “expand” - 자식들이 Stack을 채워야 함
    • “passthrough” - Stack이 자식들의 크기에 맞춰짐
  • clipped: boolean - 자식들을 Stack의 경계로 잘라낼지 여부 (기본값: false)

Positioned 속성

  • child: Widget - 위치를 지정할 위젯
  • left: number - 왼쪽 가장자리로부터의 거리
  • top: number - 상단 가장자리로부터의 거리
  • right: number - 오른쪽 가장자리로부터의 거리
  • bottom: number - 하단 가장자리로부터의 거리
  • width: number - 위치가 지정된 위젯의 너비
  • height: number - 위치가 지정된 위젯의 높이

일반적인 사용 사례

  1. 기본 오버레이:

    Stack({
      children: [
        Container({
          width: 200,
          height: 200,
          color: "blue",
        }),
        Positioned({
          top: 20,
          left: 20,
          child: Container({
            width: 50,
            height: 50,
            color: "red",
          }),
        }),
      ],
    });
    
  2. 배지가 있는 카드:

    Stack({
      children: [
        Container({
          width: 150,
          height: 200,
          color: "white",
        }),
        Positioned({
          top: -10,
          right: -10,
          child: Container({
            width: 30,
            height: 30,
            borderRadius: BorderRadius.circular(15),
            color: "red",
          }),
        }),
      ],
    });
    
  3. 전체 화면 오버레이:

    Stack({
      fit: "expand",
      children: [
        ContentWidget(),
        Container({
          color: "rgba(0, 0, 0, 0.5)",
        }),
        Center({
          child: LoadingSpinner(),
        }),
      ],
    });
    

모범 사례

  1. 레이아웃 가이드라인:

    • 레이어가 필요한 경우에만 Stack 사용
    • 위치가 지정되지 않은 자식들의 정렬 고려
    • 적절한 StackFit 선택
    • 필요한 경우 clipped 속성 사용
  2. 성능:

    • 위치가 지정된 자식들의 수 최소화
    • 불필요한 Stack 중첩 피하기
  3. 반응형 디자인:

    • 다양한 화면 크기 처리
    • 엣지 케이스 고려
    • 적절한 경우 상대적 위치 지정 사용

일반적인 패턴

  1. 모달 다이얼로그:

    Stack({
      fit: "expand",
      children: [
        Container({
          color: "rgba(0, 0, 0, 0.5)",
        }),
        Center({
          child: Container({
            width: 300,
            height: 200,
            color: "white",
            child: DialogContent(),
          }),
        }),
      ],
    });
    
  2. 캡션이 있는 이미지:

    Stack({
      children: [
        Image({ src: "image.jpg" }),
        Positioned({
          bottom: 0,
          left: 0,
          right: 0,
          child: Container({
            color: "rgba(0, 0, 0, 0.5)",
            child: Text({
              text: "캡션",
              color: "white",
            }),
          }),
        }),
      ],
    });
    
  3. 플로팅 액션 버튼:

    Stack({
      children: [
        MainContent(),
        Positioned({
          bottom: 16,
          right: 16,
          child: FloatingActionButton({
            onPressed: () => console.log("눌림"),
          }),
        }),
      ],
    });
    

팁과 트릭

  1. 레이아웃 디버깅:

    • 임시 배경색 사용
    • Stack 경계 확인
    • 위치 지정 동작 모니터링
    • 잘라내기 동작 테스트
  2. 위치 지정 기법:

    • 가능한 경우 상대적 위치 지정 사용
    • Stack 정렬 고려
    • 오버플로우 적절히 처리
  3. 최적화:

    • 가능한 경우 Stack 위젯 캐싱
    • const 생성자 사용
    • 레이아웃 제약 조건 고려
    • 적절한 fit 속성 선택