Use MediaQuery for Sizing
Replace all hardcoded sizes with percentages of screen width/height:
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
// Example: Button width is 80% of screen width, but min 180, max 350
double buttonWidth = screenWidth * 0.8;
if (buttonWidth < 180) buttonWidth = 180;
if (buttonWidth > 350) buttonWidth = 350;
B. Use SafeArea and SingleChildScrollView
This ensures content is always visible and scrollable, even on small screens:
body: SafeArea(
child: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// ...your widgets...
],
),
),
),
),
C. Responsive Button Example
Column(
children: countryData.keys.map((countryName) {
return GestureDetector(
onTap: () => _onCountrySelected(countryName),
child: Container(
width: buttonWidth,
padding: EdgeInsets.symmetric(
vertical: screenHeight * 0.015,
horizontal: 20,
),
margin: EdgeInsets.symmetric(
vertical: screenHeight * 0.008,
),
decoration: BoxDecoration(
color: Color(int.parse(countryData[countryName]!['color']!)),
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: _selectedCountryName == countryName ? Colors.white : Colors.grey,
),
),
child: Text(
countryName,
style: TextStyle(
fontSize: screenWidth * 0.045,
fontWeight: FontWeight.bold,
color: _selectedCountryName == countryName ? Colors.white : Colors.black,
),
textAlign: TextAlign.center,
),
),
);
}).toList(),
),
D. Responsive Logo Example
ClipOval(
child: Image.asset(
'assets/icon/logo5.jpg',
height: screenHeight * 0.12,
width: screenHeight * 0.12,
fit: BoxFit.cover,
),
),
- Advanced: Responsive Layouts with LayoutBuilder and Breakpoints For more complex screens, use LayoutBuilder to change layouts based on available width:
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 600) {
// Mobile layout
return Column(...);
} else {
// Tablet/Desktop layout
return Row(...);
}
},
)
Tip: Use breakpoints (e.g., 600px for mobile/tablet) to switch layouts.
- Best Practices Checklist Wrap main content in SafeArea.
Wrap long content in SingleChildScrollView.
Use MediaQuery for all sizes and font sizes.
Avoid hardcoded pixel values.
Test on multiple screen sizes and orientations.
Use Expanded and Flexible for dynamic layouts.
Use FractionallySizedBox or double.infinity for fluid widths.
- Example: Full Responsive Country Selection Page
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
double buttonWidth = screenWidth * 0.8;
if (buttonWidth < 180) buttonWidth = 180;
if (buttonWidth > 350) buttonWidth = 350;
return Scaffold(
appBar: AppBar(title: const Text("Select Country")),
body: SafeArea(
child: SingleChildScrollView(
child: Center(
child: Column(
children: [
SizedBox(height: screenHeight * 0.03),
ClipOval(
child: Image.asset(
'assets/icon/logo5.jpg',
height: screenHeight * 0.12,
width: screenHeight * 0.12,
fit: BoxFit.cover,
),
),
SizedBox(height: screenHeight * 0.03),
Column(
children: countryData.keys.map((countryName) {
return GestureDetector(
onTap: () => _onCountrySelected(countryName),
child: Container(
width: buttonWidth,
padding: EdgeInsets.symmetric(
vertical: screenHeight * 0.015,
horizontal: 20,
),
margin: EdgeInsets.symmetric(
vertical: screenHeight * 0.008,
),
decoration: BoxDecoration(
color: Color(int.parse(countryData[countryName]!['color']!)),
borderRadius: BorderRadius.circular(10),
border: Border.all(
color: _selectedCountryName == countryName ? Colors.white : Colors.grey,
),
),
child: Text(
countryName,
style: TextStyle(
fontSize: screenWidth * 0.045,
fontWeight: FontWeight.bold,
color: _selectedCountryName == countryName ? Colors.white : Colors.black,
),
textAlign: TextAlign.center,
),
),
);
}).toList(),
),
SizedBox(height: screenHeight * 0.03),
Padding(
padding: EdgeInsets.symmetric(horizontal: screenWidth * 0.05),
child: Text(
_selectedCountryName.isNotEmpty
? 'Selected Country: $_selectedCountryName'
: 'No country selected',
style: TextStyle(
fontSize: screenWidth * 0.04,
fontWeight: FontWeight.w500,
),
textAlign: TextAlign.center,
),
),
SizedBox(height: screenHeight * 0.02),
],
),
),
),
),
);
}
Top comments (0)