Question #54EasyFlutter Basics

Flutter difference between double.infinity vs media query

#flutter

Answer

Overview

Both

text
double.infinity
and
text
MediaQuery
are used to make widgets take maximum available width/height, but they work in fundamentally different ways and have different use cases.


double.infinity

Definition: A constant representing positive infinity (∞) as a double value.

How It Works

  • Tells the widget to take maximum available space from parent
  • Works in unbounded constraints contexts
  • Static value (doesn't change with device size)
  • Part of Dart's core library

Example

dart
Container(
  width: double.infinity,  // Take all available width
  height: 200,
  color: Colors.blue,
  child: Text('Full width container'),
)

When to Use

Use when:

  • You want a widget to fill parent width/height
  • Parent has bounded constraints (known size)
  • You don't need the exact pixel value
  • Building responsive layouts
dart
// Scenario 1: Full-width button
ElevatedButton(
  style: ElevatedButton.styleFrom(
    minimumSize: Size(double.infinity, 50), // Full width, 50px height
  ),
  onPressed: () {},
  child: Text('Full Width Button'),
)

// Scenario 2: Card that fills width
Card(
  child: Container(
    width: double.infinity,
    padding: EdgeInsets.all(16),
    child: Text('This card fills available width'),
  ),
)

Limitations

Cannot use with:

  • Unbounded constraints (ListView, Row, Column without size)
  • When you need exact device dimensions
dart
// ❌ Error: Unbounded constraints
Row(
  children: [
    Container(
      width: double.infinity, // ERROR: Row has unbounded width!
      height: 100,
    ),
  ],
)

// ✅ Fix: Use Expanded instead
Row(
  children: [
    Expanded(
      child: Container(
        height: 100,
      ),
    ),
  ],
)

MediaQuery

Definition: Provides information about the current device's screen size, orientation, padding, and more.

How It Works

  • Gets actual device screen dimensions
  • Returns real pixel values
  • Responds to device rotation and screen size changes
  • Part of Flutter's widget framework

Example

dart
Container(
  width: MediaQuery.of(context).size.width,  // Exact screen width in pixels
  height: MediaQuery.of(context).size.height * 0.5, // Half screen height
  color: Colors.blue,
  child: Text('Half screen height'),
)

When to Use

Use when:

  • You need exact device dimensions
  • Building responsive layouts with percentages
  • Calculating widget sizes based on screen
  • Handling different screen sizes/orientations
dart
class ResponsiveLayout extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    final width = size.width;
    final height = size.height;

    return Column(
      children: [
        // 30% of screen height
        Container(
          height: height * 0.3,
          color: Colors.blue,
          child: Text('30% height'),
        ),

        // 70% of screen height
        Container(
          height: height * 0.7,
          color: Colors.green,
          child: Text('70% height'),
        ),
      ],
    );
  }
}

Additional MediaQuery Properties

dart
final mediaQuery = MediaQuery.of(context);

// Screen dimensions
final screenWidth = mediaQuery.size.width;    // Full width (e.g., 375px)
final screenHeight = mediaQuery.size.height;  // Full height (e.g., 812px)

// Device pixel ratio (for high-DPI screens)
final pixelRatio = mediaQuery.devicePixelRatio; // e.g., 2.0 for Retina

// Orientation
final orientation = mediaQuery.orientation; // portrait or landscape

// Safe area padding (notches, status bar, etc.)
final topPadding = mediaQuery.padding.top;      // Status bar height
final bottomPadding = mediaQuery.padding.bottom; // Home indicator height

// Text scale factor (accessibility)
final textScale = mediaQuery.textScaleFactor; // e.g., 1.0 or 1.5

// View insets (keyboard)
final keyboardHeight = mediaQuery.viewInsets.bottom;

Key Differences

Featuredouble.infinityMediaQuery.of(context).size
TypeConstant (∞)Actual pixel value
ValueAbstract "maximum"Concrete number (e.g., 375px)
Context needed❌ No✅ Yes (requires BuildContext)
Use caseFill parent sizeGet device dimensions
ResponsiveParent-basedDevice screen-based
RotationN/A✅ Updates automatically
Works in unbounded❌ No (errors)✅ Yes
Percentage calculations❌ No✅ Yes (multiply by fraction)

Side-by-Side Examples

Example 1: Full Width Container

Using double.infinity:

dart
Container(
  width: double.infinity, // Fills parent width
  height: 200,
  color: Colors.blue,
)

Using MediaQuery:

dart
Container(
  width: MediaQuery.of(context).size.width, // Exact screen width
  height: 200,
  color: Colors.blue,
)

Result: Both give full width, but MediaQuery provides exact pixels.


Example 2: Responsive Height

Using double.infinity (not useful for percentages):

dart
Container(
  height: double.infinity, // Takes all available height
  // Can't do "50% of height" with double.infinity
)

Using MediaQuery (useful for percentages):

dart
Container(
  height: MediaQuery.of(context).size.height * 0.5, // Exactly 50% screen height
)

Example 3: Handling Constraints

Scenario: Widget inside Column

dart
// ❌ Error with double.infinity
Column(
  children: [
    Container(
      width: double.infinity, // ✅ Works - Column has bounded width
      height: double.infinity, // ❌ Error - Column has unbounded height!
    ),
  ],
)

// ✅ Fix with MediaQuery
Column(
  children: [
    Container(
      width: double.infinity,
      height: MediaQuery.of(context).size.height * 0.3, // ✅ Works
    ),
  ],
)

// ✅ Alternative fix with Expanded
Column(
  children: [
    Expanded( // Takes remaining space
      child: Container(
        width: double.infinity,
      ),
    ),
  ],
)

Practical Examples

Full-Width Form

dart
class LoginForm extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(16),
      child: Column(
        children: [
          // Full width text field
          TextField(
            decoration: InputDecoration(
              hintText: 'Email',
              constraints: BoxConstraints(
                maxWidth: double.infinity, // Fill width
              ),
            ),
          ),
          SizedBox(height: 16),

          // Full width button
          ElevatedButton(
            style: ElevatedButton.styleFrom(
              minimumSize: Size(double.infinity, 50),
            ),
            onPressed: () {},
            child: Text('Login'),
          ),
        ],
      ),
    );
  }
}

Responsive Card

dart
class ResponsiveCard extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;

    // Different widths for different screen sizes
    double cardWidth;
    if (screenWidth < 600) {
      cardWidth = double.infinity; // Mobile: full width
    } else if (screenWidth < 1200) {
      cardWidth = screenWidth * 0.6; // Tablet: 60% width
    } else {
      cardWidth = 800; // Desktop: fixed 800px
    }

    return Container(
      width: cardWidth,
      padding: EdgeInsets.all(16),
      child: Card(child: Text('Responsive card')),
    );
  }
}

Safe Area Handling

dart
class SafeAreaExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final mediaQuery = MediaQuery.of(context);
    final topPadding = mediaQuery.padding.top; // Status bar
    final bottomPadding = mediaQuery.padding.bottom; // Home indicator

    return Container(
      width: double.infinity,
      height: double.infinity,
      padding: EdgeInsets.only(
        top: topPadding,
        bottom: bottomPadding,
      ),
      child: Column(
        children: [
          Text('Safe from notches and system UI'),
        ],
      ),
    );
  }
}

Common Mistakes

❌ Mistake 1: Using double.infinity in Unbounded Context

dart
// ❌ Error
ListView(
  children: [
    Container(
      height: double.infinity, // Error: ListView has unbounded height!
    ),
  ],
)

// ✅ Fix
ListView(
  children: [
    Container(
      height: 200, // Use fixed height or MediaQuery percentage
    ),
  ],
)

❌ Mistake 2: Not Using MediaQuery for Percentages

dart
// ❌ Bad - can't calculate percentages
Container(
  height: double.infinity * 0.5, // Still infinity!
)

// ✅ Good
Container(
  height: MediaQuery.of(context).size.height * 0.5, // Exact 50%
)

When to Use Which

Use double.infinity when:

  • Making a widget fill its parent
  • Parent has bounded constraints
  • You don't need exact pixel values
  • Building simple full-width buttons/containers

Use MediaQuery when:

  • You need exact screen dimensions
  • Calculating percentages of screen size
  • Building responsive layouts
  • Handling orientation changes
  • Working with safe areas (notches, status bars)
  • Making decisions based on screen size

Combining Both

dart
class CombinedExample extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final screenHeight = MediaQuery.of(context).size.height;

    return Column(
      children: [
        // Header: Fixed 20% of screen height
        Container(
          width: double.infinity,  // Full width
          height: screenHeight * 0.2,  // 20% height
          color: Colors.blue,
        ),

        // Content: Takes remaining space
        Expanded(
          child: Container(
            width: double.infinity,  // Full width
            color: Colors.green,
          ),
        ),

        // Footer: Fixed 10% of screen height
        Container(
          width: double.infinity,  // Full width
          height: screenHeight * 0.1,  // 10% height
          color: Colors.red,
        ),
      ],
    );
  }
}

Key Takeaways

double.infinity: Says "give me maximum space" (abstract)

MediaQuery: Says "give me exactly X pixels" (concrete)

Use double.infinity for simple full-width/height containers

Use MediaQuery for responsive layouts with percentages


Resources