flutter_spotlight_tour 1.0.6
flutter_spotlight_tour: ^1.0.6 copied to clipboard
A modern, lightweight onboarding spotlight tour package for Flutter apps.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_spotlight_tour/flutter_spotlight_tour.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(debugShowCheckedModeBanner: false, home: Home());
}
}
class Home extends StatefulWidget {
const Home({super.key});
@override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
final controller = SpotlightTourController();
final keyBalance = GlobalKey();
final keyStats = GlobalKey();
final keyCards = GlobalKey();
final keySend = GlobalKey();
final keyReceive = GlobalKey();
final keyPay = GlobalKey();
final keyGoals = GlobalKey();
final keyHistory = GlobalKey();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
controller.start(context, [
SpotlightTourItem(
key: keyBalance,
title: "Wallet Balance",
description: "Your total available balance",
),
SpotlightTourItem(
key: keyStats,
title: "Income & Expense",
description: "Track your monthly flow",
),
SpotlightTourItem(
key: keyCards,
title: "Your Cards",
description: "Manage your cards easily",
),
SpotlightTourItem(
key: keySend,
title: "Send Money",
description: "Transfer money instantly",
),
SpotlightTourItem(
key: keyReceive,
title: "Receive Money",
description: "Get payments securely",
),
SpotlightTourItem(
key: keyPay,
title: "Pay QR",
description: "Scan & pay instantly",
),
SpotlightTourItem(
key: keyGoals,
title: "Savings Goal",
description: "Track your financial goals",
),
SpotlightTourItem(
key: keyHistory,
title: "Transactions",
description: "Your recent activity",
),
]);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF6F7FB),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Good Morning 👋",
style: TextStyle(
fontSize: 26,
fontWeight: FontWeight.bold,
color: Color(0xFF111827),
),
),
const SizedBox(height: 20),
/// BALANCE (key moved directly here)
Container(
key: keyBalance,
padding: const EdgeInsets.all(22),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(22),
gradient: const LinearGradient(
colors: [Color(0xFF4F46E5), Color(0xFF6366F1)],
),
),
child: const Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Total Balance",
style: TextStyle(color: Colors.white70),
),
SizedBox(height: 10),
Text(
"\$12,450.80",
style: TextStyle(
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
],
),
),
const SizedBox(height: 20),
Row(
children: [
_stat("Income", "+\$3,200", Colors.green),
const SizedBox(width: 10),
_stat("Expense", "-\$1,450", Colors.red),
],
),
const SizedBox(height: 20),
SizedBox(
height: 140,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
_card("Visa", "•••• 4582", keyCards),
_card("Master", "•••• 8891", null),
_card("Virtual", "•••• 1122", null),
],
),
),
const SizedBox(height: 20),
Row(
children: [
Expanded(
child: _action(
"Send",
Icons.send_rounded,
Colors.green,
key: keySend,
),
),
const SizedBox(width: 10),
Expanded(
child: _action(
"Receive",
Icons.call_received_rounded,
Colors.orange,
key: keyReceive,
),
),
const SizedBox(width: 10),
Expanded(
child: _action(
"Pay",
Icons.qr_code_rounded,
Colors.blue,
key: keyPay,
),
),
],
),
const SizedBox(height: 20),
Container(
key: keyGoals,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Savings Goal",
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
LinearProgressIndicator(
value: 0.65,
backgroundColor: Colors.grey.shade200,
color: Colors.green,
),
const SizedBox(height: 6),
const Text("\$6,500 / \$10,000"),
],
),
),
const SizedBox(height: 20),
Column(
key: keyHistory,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"Transactions",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
_txn("Netflix", "-\$15.99", Colors.red),
_txn("Salary", "+\$2,500", Colors.green),
_txn("Uber", "-\$18.20", Colors.red),
],
),
],
),
),
),
);
}
/// ---------- WIDGETS ----------
Widget _stat(String t, String v, Color c) {
return Expanded(
child: Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
children: [
Text(t),
const SizedBox(height: 6),
Text(
v,
style: TextStyle(color: c, fontWeight: FontWeight.bold),
),
],
),
),
);
}
Widget _card(String name, String num, Key? key) {
return Container(
key: key,
width: 180,
margin: const EdgeInsets.only(right: 12),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(18),
gradient: const LinearGradient(
colors: [Color(0xFF111827), Color(0xFF374151)],
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(name, style: const TextStyle(color: Colors.white70)),
const Spacer(),
Text(
num,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
],
),
);
}
Widget _action(String label, IconData icon, Color color, {required Key key}) {
return Container(
key: key,
padding: const EdgeInsets.symmetric(vertical: 14),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(18),
),
child: Column(
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: color.withValues(alpha: 0.12),
),
child: Icon(icon, color: color),
),
const SizedBox(height: 8),
Text(label),
],
),
);
}
Widget _txn(String t, String a, Color c) {
return ListTile(
leading: CircleAvatar(
backgroundColor: c.withValues(alpha: 0.1),
child: Icon(Icons.monetization_on, color: c),
),
title: Text(t),
trailing: Text(
a,
style: TextStyle(color: c, fontWeight: FontWeight.bold),
),
);
}
}