Permissions Onboarding
Loading preview
Starting the Flutter app
A Flutter onboarding UI demo for notification, location, camera, and contacts permissions with rationale.
import 'package:flutter/material.dart';
class _Perm {
final IconData icon;
final String title;
final String why;
const _Perm(this.icon, this.title, this.why);
}
class PermissionsOnboarding extends StatefulWidget {
const PermissionsOnboarding({super.key});
@override
State<PermissionsOnboarding> createState() => _PermissionsOnboardingState();
}
class _PermissionsOnboardingState extends State<PermissionsOnboarding> {
static const _perms = [
_Perm(Icons.notifications_outlined, 'Notifications',
'Get reminders and important updates.'),
_Perm(Icons.location_on_outlined, 'Location',
'Show places and offers near you.'),
_Perm(Icons.camera_alt_outlined, 'Camera',
'Scan documents and add photos.'),
_Perm(Icons.contacts_outlined, 'Contacts',
'Find friends who already use the app.'),
];
final _granted = <int>{};
/// UI demo: no system prompt appears. This is where to call a permission
/// plugin, for example with `permission_handler`:
///
/// ```dart
/// final status = await Permission.camera.request();
/// if (status.isGranted) setState(() => _granted.add(index));
/// ```
void _request(int index) {
setState(() => _granted.add(index));
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final scheme = theme.colorScheme;
return Scaffold(
body: SafeArea(
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(24, 32, 24, 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('A few permissions',
style: theme.textTheme.headlineSmall
?.copyWith(fontWeight: FontWeight.bold)),
const SizedBox(height: 8),
Text('You can change these anytime in Settings.',
style: theme.textTheme.bodyMedium
?.copyWith(color: scheme.onSurfaceVariant)),
const SizedBox(height: 4),
Text('UI demo: no system permissions are requested.',
style: theme.textTheme.bodySmall
?.copyWith(color: scheme.onSurfaceVariant)),
],
),
),
Expanded(
child: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: _perms.length,
itemBuilder: (context, i) {
final p = _perms[i];
final granted = _granted.contains(i);
return Card(
margin: const EdgeInsets.symmetric(vertical: 6),
child: Padding(
padding: const EdgeInsets.all(12),
child: Row(
children: [
CircleAvatar(
backgroundColor: scheme.primaryContainer,
child: Icon(p.icon,
color: scheme.onPrimaryContainer),
),
const SizedBox(width: 14),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(p.title,
style: const TextStyle(
fontWeight: FontWeight.w600)),
Text(p.why,
style: theme.textTheme.bodySmall?.copyWith(
color: scheme.onSurfaceVariant)),
],
),
),
granted
? const FilledButton.tonal(
onPressed: null,
child: Text('Allowed'),
)
: OutlinedButton(
onPressed: () => _request(i),
child: const Text('Allow'),
),
],
),
),
);
},
),
),
Padding(
padding: const EdgeInsets.all(24),
child: SizedBox(
width: double.infinity,
height: 52,
child: FilledButton(
onPressed: () => _showDemo(context, 'Continue (demo)'), child: const Text('Continue')),
),
),
],
),
),
);
}
}
void _showDemo(BuildContext context, String message) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(content: Text(message)));
}
Add it to your project
Copies the Dart source into your app, so you own it. Flutter SDK only, no extra packages.
First time? Run dart pub global activate fluttertemplates_dev, or read the CLI guide.
How it works
A UI demo, and the screen says so: the app never asks the OS for anything. _granted is a set of indexes that starts empty, and tapping Allow calls _request, which only adds to the set. Its doc comment shows where to call a permission plugin. Allowed is disabled, because apps generally can’t revoke a grant. _perms pairs each permission with a one-line reason, and Continue shows a demo SnackBar.
Adapting it
- Call
permission_handlerin_request, updating_grantedfrom the returned status. - Fill
_grantedfrom current statuses ininitState. - Remove the demo line, and link denied permissions to system settings.