Overview
ConstraintsTransformBox is a widget that transforms the constraints received from its parent before passing them to its child. This allows you to dynamically modify the constraints that a child widget receives.
Reference: https://api.flutter.dev/flutter/widgets/ConstraintsTransformBox-class.html
When to Use
- When you need to customize the constraints a child widget receives
- When allowing a child to have infinite height in a scrollable area
- When temporarily removing constraints in specific dimensions
- When debugging constraints in complex layouts
- When you need more fine-grained control than UnconstrainedBox provides
Basic Usage
// Remove all constraints
ConstraintsTransformBox({
constraintsTransform: ConstraintsTransformBox.unconstrained,
child: Container({
width: 300,
height: 300,
color: 'blue'
})
})
// Remove only height constraints
ConstraintsTransformBox({
constraintsTransform: ConstraintsTransformBox.heightUnconstrained,
child: Column({
children: [
Text('Free height'),
// ... many children
]
})
})
// Custom transformation
ConstraintsTransformBox({
constraintsTransform: (constraints) => {
return new Constraints({
minWidth: Math.max(constraints.minWidth, 100),
maxWidth: constraints.maxWidth,
minHeight: 0,
maxHeight: Infinity
});
},
child: child
})
Props
constraintsTransform (required)
Type: (constraints: Constraints) => Constraints
A function that transforms the constraints received from the parent. This function takes the original constraints and should return new constraints.
ConstraintsTransformBox({
constraintsTransform: (constraints) => {
// Set minimum width to 200
return constraints.copyWith({
minWidth: 200
});
},
child: child
})
child (optional)
Type: Widget | undefined
The child widget to which the transformed constraints will be applied.
alignment (optional)
Type: Alignment (default: Alignment.center)
How to align the child when its size differs from the parent.
ConstraintsTransformBox({
constraintsTransform: ConstraintsTransformBox.unconstrained,
alignment: Alignment.topLeft,
child: Container({
width: 100,
height: 100,
color: 'red'
})
})
clipped (optional)
Type: boolean (default: false)
Whether to clip the child when it exceeds the parent’s boundaries.
ConstraintsTransformBox({
constraintsTransform: ConstraintsTransformBox.unconstrained,
clipped: true, // Clip overflow
child: Container({
width: 500,
height: 500,
color: 'green'
})
})
textDirection (optional)
Type: TextDirection (default: TextDirection.ltr)
The text direction used to resolve the alignment.
Static Helper Methods
ConstraintsTransformBox provides several static methods for common transformations:
// Leave constraints unchanged
ConstraintsTransformBox.unmodified
// Remove all constraints (infinite size)
ConstraintsTransformBox.unconstrained
// Remove only width constraints
ConstraintsTransformBox.widthUnconstrained
// Remove only height constraints
ConstraintsTransformBox.heightUnconstrained
// Remove max height constraint
ConstraintsTransformBox.maxHeightUnconstrained
// Remove max width constraint
ConstraintsTransformBox.maxWidthUnconstrained
// Remove both max width and height constraints
ConstraintsTransformBox.maxUnconstrained
Practical Examples
Example 1: Removing Height Constraints in Scrollable List
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)
})
)
})
})
});
};
Example 2: Ensuring Minimum Size While Transforming
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
});
};
// Usage
MinSizeTransform({
minSize: 200,
child: Container({
color: 'blue',
child: Text('Minimum 200x200 size guaranteed')
})
})
Example 3: Aspect Ratio Constraint Transform
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
});
};
Example 4: Debug Constraint Logging
const DebugConstraints = ({ label, child }) => {
return ConstraintsTransformBox({
constraintsTransform: (constraints) => {
console.log(`${label} constraints:`, {
minWidth: constraints.minWidth,
maxWidth: constraints.maxWidth,
minHeight: constraints.minHeight,
maxHeight: constraints.maxHeight
});
return constraints; // Return unchanged
},
child: child
});
};
// Usage
DebugConstraints({
label: 'Container',
child: Container({
width: 200,
height: 200,
color: 'red'
})
})
Example 5: Conditional Constraint Transform
const ConditionalConstraints = ({
isExpanded,
maxWidth = 300,
child
}) => {
return ConstraintsTransformBox({
constraintsTransform: (constraints) => {
if (isExpanded) {
return constraints; // Use original constraints in expanded mode
}
// Limit max width in collapsed mode
return constraints.copyWith({
maxWidth: Math.min(constraints.maxWidth, maxWidth)
});
},
clipped: !isExpanded,
child: AnimatedContainer({
duration: Duration({ milliseconds: 300 }),
child: child
})
});
};
Constraint Transform Patterns
Common Transform Patterns
// 1. Force minimum size
(constraints) => constraints.copyWith({
minWidth: 100,
minHeight: 100
})
// 2. Limit maximum size
(constraints) => constraints.copyWith({
maxWidth: Math.min(constraints.maxWidth, 500),
maxHeight: Math.min(constraints.maxHeight, 500)
})
// 3. Force square
(constraints) => {
const size = Math.min(constraints.maxWidth, constraints.maxHeight);
return Constraints.tight({ width: size, height: size });
}
// 4. Maintain ratio
(constraints) => {
const ratio = 0.5; // Height is half of width
return constraints.copyWith({
maxHeight: constraints.maxWidth * ratio
});
}
Important Notes
- Invalid transformed constraints can cause layout errors
- When using infinite constraints, the child must have an intrinsic size
- When clipped is false, the child can overflow its parent
- Complex transformations can impact layout performance
- Transform functions should be pure functions without side effects
Related Widgets
- UnconstrainedBox: Simple way to remove all constraints
- ConstrainedBox: Apply additional constraints
- OverflowBox: Allow child to exceed parent constraints
- SizedBox: Specify fixed size
- FractionallySizedBox: Size based on parent’s dimensions