network_aware_ui 0.1.0
network_aware_ui: ^0.1.0 copied to clipboard
A lightweight, reactive Flutter package to monitor network connectivity, verify internet reachability, and render customizable offline UI states.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:network_aware_ui/network_aware_ui.dart';
void main() {
runApp(const NetworkAwareExampleApp());
}
/// Example application showcasing the network_aware_ui package features.
class NetworkAwareExampleApp extends StatelessWidget {
/// Creates the [NetworkAwareExampleApp].
const NetworkAwareExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Network Aware UI Example',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
useMaterial3: true,
),
home: const ExampleHomeScreen(),
);
}
}
/// The main dashboard screen demonstrating banners, builders, and offline widgets.
class ExampleHomeScreen extends StatefulWidget {
/// Creates the [ExampleHomeScreen].
const ExampleHomeScreen({super.key});
@override
State<ExampleHomeScreen> createState() => _ExampleHomeScreenState();
}
class _ExampleHomeScreenState extends State<ExampleHomeScreen> {
BannerPosition _bannerPosition = BannerPosition.top;
bool _useDedicatedBuilders = true;
@override
Widget build(BuildContext context) {
return NetworkAwareBanner(
bannerPosition: _bannerPosition,
showOnlineBannerDuration: const Duration(seconds: 2),
child: Scaffold(
appBar: AppBar(
title: const Text('Network-Aware UI'),
actions: [
IconButton(
icon: const Icon(Icons.refresh_rounded),
tooltip: 'Force Reachability Check',
onPressed: () async {
final messenger = ScaffoldMessenger.of(context);
final state = await NetworkAware.instance.checkReachability(
forceRefresh: true,
);
messenger.showSnackBar(
SnackBar(
content: Text(
'Refreshed: ${state.status.name} (${state.primaryConnectionType.name})',
),
duration: const Duration(seconds: 2),
),
);
},
),
],
),
body: _useDedicatedBuilders
? NetworkAwareBuilder(
animateTransitions: true,
onlineBuilder: (context, state) => _buildDashboard(context, state),
offlineBuilder: (context, state) => OfflineWidget(
onRetry: () async {
await NetworkAware.instance.checkReachability(
forceRefresh: true,
);
},
),
checkingBuilder: (context, state) => const Center(
child: CircularProgressIndicator(),
),
)
: NetworkAwareBuilder(
builder: (context, state) {
if (state.isOffline) {
return const OfflineWidget();
}
return _buildDashboard(context, state);
},
),
),
);
}
Widget _buildDashboard(BuildContext context, NetworkState state) {
final theme = Theme.of(context);
return SingleChildScrollView(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
state.isOnline
? Icons.check_circle_rounded
: Icons.cancel_rounded,
color: state.isOnline ? Colors.green : Colors.red,
size: 28,
),
const SizedBox(width: 12),
Text(
'Live Network State',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
],
),
const Divider(height: 24),
_buildStateRow('Status:', state.status.name.toUpperCase()),
_buildStateRow(
'Primary Connection:',
state.primaryConnectionType.name,
),
_buildStateRow(
'All Interfaces:',
state.connectionTypes.map((t) => t.name).join(', '),
),
_buildStateRow(
'Internet Reachable:',
state.isInternetReachable ? 'Yes' : 'No',
),
_buildStateRow(
'Last Evaluated:',
'${state.timestamp.hour.toString().padLeft(2, '0')}:${state.timestamp.minute.toString().padLeft(2, '0')}:${state.timestamp.second.toString().padLeft(2, '0')}',
),
],
),
),
),
const SizedBox(height: 20),
Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Configuration Controls',
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 12),
SwitchListTile(
title: const Text('Use Dedicated Builders'),
subtitle: const Text('Toggle between dedicated and generic builder'),
value: _useDedicatedBuilders,
onChanged: (val) {
setState(() {
_useDedicatedBuilders = val;
});
},
),
const Divider(),
ListTile(
title: const Text('Banner Position'),
subtitle: Text('Current: ${_bannerPosition.name}'),
trailing: SegmentedButton<BannerPosition>(
segments: const [
ButtonSegment(
value: BannerPosition.top,
label: Text('Top'),
),
ButtonSegment(
value: BannerPosition.bottom,
label: Text('Bottom'),
),
],
selected: {_bannerPosition},
onSelectionChanged: (selected) {
setState(() {
_bannerPosition = selected.first;
});
},
),
),
],
),
),
),
],
),
);
}
Widget _buildStateRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
label,
style: const TextStyle(fontWeight: FontWeight.w500),
),
Text(
value,
style: const TextStyle(fontWeight: FontWeight.bold),
),
],
),
);
}
}