Skip to content

Instantly share code, notes, and snippets.

@BoltUIX
Last active February 23, 2024 05:53
Show Gist options
  • Save BoltUIX/1f397fab579c68d0a2bc331a806da4dc to your computer and use it in GitHub Desktop.
Save BoltUIX/1f397fab579c68d0a2bc331a806da4dc to your computer and use it in GitHub Desktop.
Building adaptive apps
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Adaptive Screen',
home: const AdaptiveScreen(),
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueAccent),
useMaterial3: true,
),
);
}
}
class AdaptiveScreen extends StatefulWidget {
const AdaptiveScreen({Key? key}) : super(key: key);
@override
AdaptiveScreenState createState() => AdaptiveScreenState();
}
class AdaptiveScreenState extends State<AdaptiveScreen> {
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Responsive and Adaptive"),
),
bottomNavigationBar: MediaQuery.of(context).size.width < 640?
BottomNavigationBar(
currentIndex: _selectedIndex,
unselectedItemColor: Colors.grey,
selectedItemColor: Colors.indigoAccent,
// called when one tab is selected
onTap: (int index) {
setState(() {
_selectedIndex = index;
});
},
// bottom tab items
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home), label: 'Home'),
BottomNavigationBarItem(
icon: Icon(Icons.feed), label: 'Feed'),
BottomNavigationBarItem(
icon: Icon(Icons.favorite), label: 'Favorites'),
BottomNavigationBarItem(
icon: Icon(Icons.settings), label: 'Settings')
]):null,
body: Row(
children: [
if (MediaQuery.of(context).size.width >= 640)
NavigationRail(
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
selectedIndex: _selectedIndex,
destinations: const [
NavigationRailDestination(
icon: Icon(Icons.home), label: Text('Home')),
NavigationRailDestination(
icon: Icon(Icons.feed), label: Text('Feed')),
NavigationRailDestination(
icon: Icon(Icons.favorite), label: Text('Favorites')),
NavigationRailDestination(
icon: Icon(Icons.settings), label: Text('Settings')),
],
labelType: NavigationRailLabelType.all,
selectedLabelTextStyle: const TextStyle(
color: Colors.teal,
),
unselectedLabelTextStyle: const TextStyle(),
// Called when one tab is selected
leading: const Column(
children: [
SizedBox(
height: 8,
),
CircleAvatar(
radius: 20,
child: Icon(Icons.person),
),
],
),
),
const Expanded(child: MyResponsiveGridImage())
],
),
);
}
}
//..................................................................................
class MyResponsiveGridImage extends StatelessWidget {
const MyResponsiveGridImage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context)
.textTheme
.apply(displayColor: Theme.of(context).colorScheme.onSurface);
// Set the default number of columns to 3.
int columnsCount = 3;
// Use the ResponsiveUtils class to determine the device's screen size.
if (ResponsiveUtils.isMobile(context)) {
columnsCount = 2;
} else if (ResponsiveUtils.isDesktop(context)) {
columnsCount = 5;
}
// Build the grid view using the number of columns.
return Scaffold(
/*appBar: AppBar(
title: const Text('Responsive Grid View'),
),*/
body:
GridView.builder(
// Set padding and spacing between cards.
padding: const EdgeInsets.all(10),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// Set the number of columns based on the device's screen size.
crossAxisCount: columnsCount,
// Set the aspect ratio of each card.
childAspectRatio: 3 / 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
// Set the number of items in the grid view.
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
// Build each card in the grid view.
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Expanded(
// Add an image to each card.
child:
Icon(Icons.category),
/* Image.asset('assets/images/test.webp',
fit: BoxFit.cover,
),*/
/* Image.network(
'https://picsum.photos/id/$index/400/300',
fit: BoxFit.cover,
),*/
),
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Add a title to each card.
Text(
'Item $index', style: textTheme.titleMedium!.copyWith(fontWeight: FontWeight.bold), ),
const SizedBox(height: 5),
// Add a description to each card.
Text(
'Description of item $index', style: textTheme.bodyMedium!),
],
),
),
const SizedBox(height: 10),
],
),
);
},
// Set the grid view to shrink wrap its contents.
shrinkWrap: true,
// Disable scrolling in the grid view.
//physics: const NeverScrollableScrollPhysics(),
),
);
}
}
//..................................................................................
class ResponsiveUtils {
// Check if the device is considered as mobile based on screen width.
static bool isMobile(BuildContext context) =>
MediaQuery.of(context).size.width <= 600;
// Check if the device is considered as tablet based on screen width.
static bool isTablet(BuildContext context) =>
MediaQuery.of(context).size.width > 600 &&
MediaQuery.of(context).size.width <= 1200;
// Check if the device is considered as desktop based on screen width.
static bool isDesktop(BuildContext context) =>
MediaQuery.of(context).size.width > 1200;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment