FractionallySizedBox in Flutter: A Practical Guide

Introduction

FractionallySizedBox is a Flutter widget that sizes its child to a fraction of its parent’s total available space. It’s particularly useful when you need to create responsive layouts or components that need to maintain proportional dimensions.

Understanding FractionallySizedBox

Key Properties

  1. widthFactor: A multiplier for the parent’s width (0.0 to 1.0)
  2. heightFactor: A multiplier for the parent’s height (0.0 to 1.0)
  3. alignment: Determines how to position the child within the box
  4. child: The widget to be sized

When to Use FractionallySizedBox

  • Creating responsive progress indicators
  • Building dynamic loading bars
  • Implementing proportional layouts
  • Making adaptive UI components

Practical Example: Custom Progress Bar

Here’s a real-world example of a progress bar component that you might use for file uploads, data processing, or loading states:

class ProgressBar extends StatelessWidget {
  final double progress; // Value from 0.0 to 1.0
  final String label;
  final Color color;
  final Color backgroundColor;
  final double height;

  const ProgressBar({
    Key? key,
    required this.progress,
    required this.label,
    this.color = Colors.blue,
    this.backgroundColor = Colors.grey,
    this.height = 20,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: [
        // Progress Label
        Text(
          label,
          style: Theme.of(context).textTheme.bodyMedium,
        ),
        SizedBox(height: 8),

        // Progress Bar Container
        Container(
          height: height,
          width: double.infinity,
          decoration: BoxDecoration(
            color: backgroundColor.withOpacity(0.2),
            borderRadius: BorderRadius.circular(height / 2),
          ),
          clipBehavior: Clip.hardEdge,
          child: FractionallySizedBox(
            widthFactor: progress.clamp(0.0, 1.0),
            alignment: Alignment.centerLeft,
            child: Container(
              decoration: BoxDecoration(
                color: color,
                borderRadius: BorderRadius.circular(height / 2),
              ),
              child: Center(
                child: Text(
                  '${(progress * 100).toInt()}%',
                  style: TextStyle(
                    color: Colors.white,
                    fontWeight: FontWeight.bold,
                    fontSize: height * 0.6,
                  ),
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }
}

Usage Example

Here’s how to implement the progress bar in a real application:

class UploadScreen extends StatefulWidget {
  @override
  _UploadScreenState createState() => _UploadScreenState();
}

class _UploadScreenState extends State<UploadScreen> {
  double _uploadProgress = 0.0;

  // Simulate a file upload process
  void _simulateUpload() {
    setState(() => _uploadProgress = 0.0);

    Timer.periodic(Duration(milliseconds: 100), (timer) {
      setState(() {
        _uploadProgress += 0.01;
        if (_uploadProgress >= 1.0) {
          timer.cancel();
          _showCompleteDialog();
        }
      });
    });
  }

  void _showCompleteDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Upload Complete'),
        content: Text('Your file has been successfully uploaded.'),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text('OK'),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('File Upload Example'),
      ),
      body: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Single file upload progress
            ProgressBar(
              progress: _uploadProgress,
              label: 'Uploading file...',
              color: Theme.of(context).primaryColor,
            ),

            SizedBox(height: 24),

            // Multiple progress bars example
            ProgressBar(
              progress: _uploadProgress * 0.7, // Different progress rates
              label: 'Processing data...',
              color: Colors.green,
              height: 15,
            ),

            SizedBox(height: 24),

            // Action buttons
            Center(
              child: ElevatedButton(
                onPressed: _uploadProgress < 1.0 ? _simulateUpload : null,
                child: Text('Start Upload'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Best Practices

  1. Input Validation
    • Always clamp progress values between 0.0 and 1.0
    • Handle edge cases (null values, negative numbers)
    • Provide meaningful default values
  2. Performance
    // DO: Use const constructor when possible
    const ProgressBar(
     progress: 0.5,
     label: 'Loading...',
    )
    
    // DON'T: Rebuild unnecessarily
    ProgressBar(
     progress: 0.5,
     label: 'Loading...',
    )
  3. Accessibility
    • Use appropriate colors with good contrast
    • Consider adding semantic labels
    • Support different text scales

Common Pitfalls to Avoid

  1. Unbounded Width
    // DON'T: May cause layout errors
    Row(
     children: [
       FractionallySizedBox(
         widthFactor: 0.5,
         child: ProgressBar(...),
       ),
     ],
    )
    
    // DO: Provide constraints
    Row(
     children: [
       Expanded(
         child: FractionallySizedBox(
           widthFactor: 0.5,
           child: ProgressBar(...),
         ),
       ),
     ],
    )
  2. Animation Smoothness
    // DON'T: Jerky updates
    setState(() {
     progress += 0.1;
    });
    
    // DO: Smooth transitions
    setState(() {
     progress = (progress + 0.1).clamp(0.0, 1.0);
    });

Conclusion

FractionallySizedBox is an essential widget for creating responsive components in Flutter. The progress bar example demonstrates how it can be used effectively to create a reusable, professional-looking component. By following the best practices and avoiding common pitfalls, you can create robust and maintainable UI components that work well across different screen sizes and orientations.

Summary
FractionallySizedBox in Flutter: A Practical Guide
Article Name
FractionallySizedBox in Flutter: A Practical Guide
Description
FractionallySizedBox is a Flutter widget that sizes its child to a fraction of its parent's total available space
Author
Publisher Name
raheemdev.com
Publisher Logo

Leave a Comment

Ads Blocker Image Powered by Code Help Pro

Ads Blocker Detected!!!

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

Powered By
100% Free SEO Tools - Tool Kits PRO