개요
ConstraintsTransformBox는 부모로부터 받은 제약 조건을 변환하여 자식에게 전달하는 위젯입니다. 이를 통해 자식 위젯이 받는 제약 조건을 동적으로 수정할 수 있습니다.
참조: https://api.flutter.dev/flutter/widgets/ConstraintsTransformBox-class.html
언제 사용하나요?
- 자식 위젯이 받는 제약 조건을 커스터마이즈해야 할 때
- 스크롤 가능한 영역에서 자식이 무한 높이를 가지도록 할 때
- 특정 차원의 제약을 일시적으로 해제해야 할 때
- 복잡한 레이아웃에서 제약 조건을 디버깅할 때
- UnconstrainedBox보다 더 세밀한 제어가 필요할 때
기본 사용법
// 모든 제약 제거
ConstraintsTransformBox({
constraintsTransform: ConstraintsTransformBox.unconstrained,
child: Container({
width: 300,
height: 300,
color: 'blue'
})
})
// 높이 제약만 제거
ConstraintsTransformBox({
constraintsTransform: ConstraintsTransformBox.heightUnconstrained,
child: Column({
children: [
Text('자유로운 높이'),
// ... 많은 자식들
]
})
})
// 커스텀 변환
ConstraintsTransformBox({
constraintsTransform: (constraints) => {
return new Constraints({
minWidth: Math.max(constraints.minWidth, 100),
maxWidth: constraints.maxWidth,
minHeight: 0,
maxHeight: Infinity
});
},
child: child
})
Props
constraintsTransform (필수)
값: (constraints: Constraints) => Constraints
부모로부터 받은 제약 조건을 변환하는 함수입니다. 이 함수는 원본 제약 조건을 받아 새로운 제약 조건을 반환해야 합니다.
ConstraintsTransformBox({
constraintsTransform: (constraints) => {
// 최소 너비를 200으로 설정
return constraints.copyWith({
minWidth: 200
});
},
child: child
})
child (선택)
값: Widget | undefined
변환된 제약 조건이 적용될 자식 위젯입니다.
alignment (선택)
값: Alignment (기본값: Alignment.center)
자식의 크기가 부모와 다를 때 자식을 정렬하는 방법입니다.
ConstraintsTransformBox({
constraintsTransform: ConstraintsTransformBox.unconstrained,
alignment: Alignment.topLeft,
child: Container({
width: 100,
height: 100,
color: 'red'
})
})
clipped (선택)
값: boolean (기본값: false)
자식이 부모의 경계를 벗어날 때 클리핑할지 여부입니다.
ConstraintsTransformBox({
constraintsTransform: ConstraintsTransformBox.unconstrained,
clipped: true, // 오버플로우 클리핑
child: Container({
width: 500,
height: 500,
color: 'green'
})
})
textDirection (선택)
값: TextDirection (기본값: TextDirection.ltr)
정렬을 해석하는 데 사용되는 텍스트 방향입니다.
정적 헬퍼 메서드
ConstraintsTransformBox는 일반적인 변환을 위한 여러 정적 메서드를 제공합니다:
// 제약 조건을 변경하지 않음
ConstraintsTransformBox.unmodified
// 모든 제약 제거 (무한 크기)
ConstraintsTransformBox.unconstrained
// 너비 제약만 제거
ConstraintsTransformBox.widthUnconstrained
// 높이 제약만 제거
ConstraintsTransformBox.heightUnconstrained
// 최대 높이 제약 제거
ConstraintsTransformBox.maxHeightUnconstrained
// 최대 너비 제약 제거
ConstraintsTransformBox.maxWidthUnconstrained
// 최대 너비와 높이 제약 제거
ConstraintsTransformBox.maxUnconstrained
실제 사용 예제
예제 1: 스크롤 가능한 리스트에서 높이 제약 제거
const ScrollableList = ({ items }) => {
return SingleChildScrollView({
child: ConstraintsTransformBox({
constraintsTransform: ConstraintsTransformBox.heightUnconstrained,
child: Column({
children: items.map(item =>
ListTile({
title: Text(item.title),
subtitle: Text(item.description)
})
)
})
})
});
};
예제 2: 최소 크기 보장하면서 제약 변환
const MinSizeTransform = ({ minSize = 150, child }) => {
return ConstraintsTransformBox({
constraintsTransform: (constraints) => {
return new Constraints({
minWidth: Math.max(constraints.minWidth, minSize),
maxWidth: constraints.maxWidth,
minHeight: Math.max(constraints.minHeight, minSize),
maxHeight: constraints.maxHeight
});
},
child: child
});
};
// 사용
MinSizeTransform({
minSize: 200,
child: Container({
color: 'blue',
child: Text('최소 200x200 크기 보장')
})
})
예제 3: 종횡비를 유지하면서 제약 변환
const AspectRatioTransform = ({ aspectRatio = 1, child }) => {
return ConstraintsTransformBox({
constraintsTransform: (constraints) => {
const width = constraints.maxWidth;
const height = width / aspectRatio;
return new Constraints({
minWidth: 0,
maxWidth: width,
minHeight: 0,
maxHeight: height
});
},
alignment: Alignment.center,
child: child
});
};
예제 4: 디버깅용 제약 로깅
const DebugConstraints = ({ label, child }) => {
return ConstraintsTransformBox({
constraintsTransform: (constraints) => {
console.log(`${label} 제약:`, {
minWidth: constraints.minWidth,
maxWidth: constraints.maxWidth,
minHeight: constraints.minHeight,
maxHeight: constraints.maxHeight
});
return constraints; // 변경 없이 반환
},
child: child
});
};
// 사용
DebugConstraints({
label: 'Container',
child: Container({
width: 200,
height: 200,
color: 'red'
})
})
예제 5: 조건부 제약 변환
const ConditionalConstraints = ({
isExpanded,
maxWidth = 300,
child
}) => {
return ConstraintsTransformBox({
constraintsTransform: (constraints) => {
if (isExpanded) {
return constraints; // 확장 모드에서는 원본 제약 사용
}
// 축소 모드에서는 최대 너비 제한
return constraints.copyWith({
maxWidth: Math.min(constraints.maxWidth, maxWidth)
});
},
clipped: !isExpanded,
child: AnimatedContainer({
duration: Duration({ milliseconds: 300 }),
child: child
})
});
};
제약 변환 패턴
일반적인 변환 패턴
// 1. 최소 크기 강제
(constraints) => constraints.copyWith({
minWidth: 100,
minHeight: 100
})
// 2. 최대 크기 제한
(constraints) => constraints.copyWith({
maxWidth: Math.min(constraints.maxWidth, 500),
maxHeight: Math.min(constraints.maxHeight, 500)
})
// 3. 정사각형 강제
(constraints) => {
const size = Math.min(constraints.maxWidth, constraints.maxHeight);
return Constraints.tight({ width: size, height: size });
}
// 4. 비율 유지
(constraints) => {
const ratio = 0.5; // 높이가 너비의 절반
return constraints.copyWith({
maxHeight: constraints.maxWidth * ratio
});
}
주의사항
- 변환된 제약이 유효하지 않으면 레이아웃 오류가 발생할 수 있습니다
- 무한 제약을 사용할 때는 자식이 고유 크기를 가져야 합니다
- clipped가 false일 때 자식이 부모를 오버플로우할 수 있습니다
- 너무 복잡한 변환은 레이아웃 성능에 영향을 줄 수 있습니다
- 변환 함수는 순수 함수여야 하며, 부작용이 없어야 합니다
관련 위젯
- UnconstrainedBox: 모든 제약을 제거하는 간단한 방법
- ConstrainedBox: 추가 제약을 적용
- OverflowBox: 부모 제약을 벗어날 수 있게 허용
- SizedBox: 고정 크기 지정
- FractionallySizedBox: 부모 크기의 비율로 크기 지정