You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
So I am trying to have a Showcase in my CupertinoNavigationBar, but when I navigate to the Detail page, I get an exception 'Please provide ShowCaseView context'. I have saved the context from the ShowCaseWidget and applied it, but I can't get it to work at all. As soon as you click on the top item to pull up the Detail page, the error happens. If you change the DEBUG_showShowcase to false so that there is no showcase in the navigationBar everything works fine. Not sure if I am doing something wrong with the CupertinoNavigationBar or ShowCaseWidget.
I took the example and tried to make it work with the CupertinoNavigationBar.
Anyone help is appreciated.
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:showcaseview/showcaseview.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: 'Flutter ShowCase',
theme: ThemeData(
primaryColor: const Color(0xffEE5366),
),
debugShowCheckedModeBanner: false,
home: const Scaffold(
body: MailPage(),
),
);
}
}
class MailPage extends StatefulWidget {
const MailPage({Key? key}) : super(key: key);
@override
_MailPageState createState() => _MailPageState();
}
class _MailPageState extends State<MailPage> {
final GlobalKey _one = GlobalKey();
final GlobalKey _two = GlobalKey();
final GlobalKey _three = GlobalKey();
final GlobalKey _four = GlobalKey();
final GlobalKey _five = GlobalKey();
final GlobalKey _nav = GlobalKey();
List<Mail> mails = [];
final scrollController = ScrollController();
BuildContext? showContext;
@override
void initState() {
super.initState();
//Start showcase view after current widget frames are drawn.
//NOTE: remove ambiguate function if you are using
//flutter version greater than 3.x and direct use WidgetsBinding.instance
WidgetsBinding.instance.addPostFrameCallback(
(_) => ShowCaseWidget.of(showContext!).startShowCase([_three, _four, _five, _one]),
);
mails = [
Mail(
sender: 'Medium',
sub: 'Showcase View',
msg: 'Check new showcase View',
date: '1 May',
isUnread: false,
),
Mail(
sender: 'Quora',
sub: 'New Question for you',
msg: 'Hi, There is new question for you',
date: '2 May',
isUnread: true,
),
Mail(
sender: 'Google',
sub: 'Flutter 1.5',
msg: 'We have launched Flutter 1.5',
date: '3 May',
isUnread: false,
),
Mail(
sender: 'Github',
sub: 'Showcase View',
msg: 'New star on your showcase view.',
date: '4 May ',
isUnread: true,
),
Mail(
sender: 'Simform',
sub: 'Credit card Plugin',
msg: 'Check out our credit card plugin',
date: '5 May',
isUnread: false,
),
Mail(
sender: 'Flutter',
sub: 'Flutter is Future',
msg: 'Flutter launched for Web',
date: '6 May',
isUnread: true,
),
Mail(
sender: 'Medium',
sub: 'Showcase View',
msg: 'Check new showcase View',
date: '7 May ',
isUnread: false,
),
Mail(
sender: 'Simform',
sub: 'Credit card Plugin',
msg: 'Check out our credit card plugin',
date: '8 May',
isUnread: true,
),
Mail(
sender: 'Flutter',
sub: 'Flutter is Future',
msg: 'Flutter launched for Web',
date: '9 May',
isUnread: false,
),
];
}
@override
void dispose() {
scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// I read that I needed to save off the context, not sure this is right
//flag to switch between using the showcase on the navigation bar.
bool DEBUG_showShowcase = true;
return ShowCaseWidget(
onStart: (index, key) {
log('onStart: $index, $key');
},
onComplete: (index, key) {
log('onComplete: $index, $key');
if (index == 4) {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle.light.copyWith(
statusBarIconBrightness: Brightness.dark,
statusBarColor: Colors.white,
),
);
}
},
blurValue: 1,
// autoPlayDelay: const Duration(seconds: 1),
builder: Builder(
builder: (context) {
showContext = context;
return Stack(children: [
CupertinoPageScaffold(
backgroundColor: Colors.white,
navigationBar: CupertinoNavigationBar(
middle: Row(
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
//uses flag to determine if we should add the showcase
if (DEBUG_showShowcase)
Showcase(
key: _one,
description: 'Tap to see menu options',
disableDefaultTargetGestures: true,
onBarrierClick: () => debugPrint('Barrier clicked'),
child: GestureDetector(
onTap: () => debugPrint('menu button clicked'),
child: Icon(
Icons.menu,
color: Theme.of(context).primaryColor,
),
),
),
// if we don't use the showcase, just display the icon
if (!DEBUG_showShowcase)
Icon(Icons.menu, color: Theme.of(context).primaryColor),
const SizedBox(
width: 10,
),
const Text(
'Search email',
style: TextStyle(
color: Colors.black45,
fontSize: 16,
letterSpacing: 0.4,
),
),
const Spacer(),
const Icon(
Icons.search,
color: Color(0xffADADAD),
),
],
),
),
],
),
),
child: Column(children: [
Container(
padding: const EdgeInsets.only(left: 16, top: 8),
child: const Text(
'PRIMARY',
style: TextStyle(
color: Colors.black,
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
),
const Padding(padding: EdgeInsets.only(top: 8)),
Expanded(
child: ListView.builder(
controller: scrollController,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
if (index == 0) {
return showcaseMailTile(_three, true, context, mails.first);
}
return MailTile(
mail: mails[index % mails.length],
);
},
),
),
]),
),
Positioned(
bottom: 16,
right: 16,
child: Showcase(
key: _five,
title: 'Compose Mail',
description: 'Click here to compose mail',
targetShapeBorder: const CircleBorder(),
child: FloatingActionButton(
backgroundColor: Theme.of(context).primaryColor,
onPressed: () {
setState(() {
/* reset ListView to ensure that the showcased widgets are
* currently rendered so the showcased keys are available in the
* render tree. */
scrollController.jumpTo(0);
ShowCaseWidget.of(showContext!)
// .startShowCase([_one, _two, _three, _four, _five]);
.startShowCase([_three, _four, _five, _one]);
});
},
child: const Icon(
Icons.add,
),
),
),
)
]);
}
),
);
}
GestureDetector showcaseMailTile(GlobalKey<State<StatefulWidget>> key,
bool showCaseDetail, BuildContext context, Mail mail) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(
CupertinoPageRoute(
builder: (context) => const Detail(),
),
);
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Showcase(
key: key,
description: 'Tap to check mail',
tooltipPosition: TooltipPosition.top,
disposeOnTap: true,
onTargetClick: () {
Navigator.push<void>(
context,
MaterialPageRoute<void>(
builder: (_) => const Detail(),
),
).then((_) {
setState(() {
ShowCaseWidget.of(context).startShowCase([_four, _five]);
});
});
},
child: MailTile(
mail: mail,
showCaseKey: _four,
showCaseDetail: showCaseDetail,
)),
),
);
}
}
class SAvatarExampleChild extends StatelessWidget {
const SAvatarExampleChild({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(10),
child: Container(
width: 45,
height: 45,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Color(0xffFCD8DC),
),
child: Center(
child: Text(
'S',
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
),
);
}
}
class Mail {
Mail({
required this.sender,
required this.sub,
required this.msg,
required this.date,
required this.isUnread,
});
String sender;
String sub;
String msg;
String date;
bool isUnread;
}
class MailTile extends StatelessWidget {
const MailTile(
{required this.mail,
this.showCaseDetail = false,
this.showCaseKey,
Key? key})
: super(key: key);
final bool showCaseDetail;
final GlobalKey<State<StatefulWidget>>? showCaseKey;
final Mail mail;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(left: 6, right: 16, top: 8, bottom: 8),
color: mail.isUnread ? const Color(0xffFFF6F7) : Colors.white,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
if (showCaseDetail)
Showcase.withWidget(
key: showCaseKey!,
height: 50,
width: 140,
targetShapeBorder: const CircleBorder(),
targetBorderRadius: const BorderRadius.all(
Radius.circular(150),
),
container: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 45,
height: 45,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Color(0xffFCD8DC),
),
child: Center(
child: Text(
'S',
style: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
),
const SizedBox(
height: 10,
),
const Text(
"Your sender's profile ",
style: TextStyle(color: Colors.white),
)
],
),
child: const SAvatarExampleChild(),
)
else
const SAvatarExampleChild(),
const Padding(padding: EdgeInsets.only(left: 8)),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
mail.sender,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: mail.isUnread
? FontWeight.bold
: FontWeight.normal,
fontSize: 17,
),
),
Text(
mail.sub,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 16,
),
),
Text(
mail.msg,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontWeight: FontWeight.normal,
color: mail.isUnread
? Theme.of(context).primaryColor
: Colors.black,
fontSize: 15,
),
),
],
),
)
],
),
),
SizedBox(
width: 50,
child: Column(
children: <Widget>[
const SizedBox(
height: 5,
),
Text(
mail.date,
style: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 12,
color: Colors.grey,
),
),
const SizedBox(
height: 10,
),
Icon(
mail.isUnread ? Icons.star : Icons.star_border,
color: mail.isUnread ? const Color(0xffFBC800) : Colors.grey,
),
],
),
),
],
),
);
}
}
class Detail extends StatefulWidget {
const Detail({Key? key}) : super(key: key);
@override
_DetailState createState() => _DetailState();
}
class _DetailState extends State<Detail> {
final GlobalKey _one = GlobalKey();
BuildContext? myContext;
@override
void initState() {
super.initState();
//NOTE: remove ambiguate function if you are using
//flutter version greater than 3.x and direct use WidgetsBinding.instance
WidgetsBinding.instance.addPostFrameCallback(
(_) => Future.delayed(const Duration(milliseconds: 200), () {
ShowCaseWidget.of(myContext!).startShowCase([_one]);
}),
);
}
@override
Widget build(BuildContext context) {
return ShowCaseWidget(
builder: Builder(
builder: (context) {
// store the ShowCaseWidget context
myContext = context;
return CupertinoPageScaffold(
backgroundColor: Theme.of(context).colorScheme.background,
navigationBar: CupertinoNavigationBar(
// leading: const Icon(CupertinoIcons.left_chevron),
middle: Text('Test Page',
style: Theme.of(context).textTheme.headlineSmall,
maxLines: 1,
softWrap: false,
overflow: TextOverflow.fade),
),
/*
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: const Icon(
Icons.arrow_back,
color: Colors.black,
),
onPressed: () {
Navigator.pop(context);
},
),
),
*/
child: Material(
child: Padding(
padding: const EdgeInsets.all(16),
child: ListView(
children: <Widget>[
Showcase(
key: _one,
title: 'Title',
description: 'Desc',
child: InkWell(
onTap: () {},
child: const Text(
'Flutter Notification',
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.w600,
),
),
),
),
const SizedBox(
height: 16,
),
const Text(
'Hi, you have new Notification from flutter group, open '
'slack and check it out',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
),
const SizedBox(
height: 16,
),
RichText(
text: const TextSpan(
style: TextStyle(
fontWeight: FontWeight.w400,
color: Colors.black,
),
children: [
TextSpan(text: 'Hi team,\n\n'),
TextSpan(
text:
'As some of you know, we’re moving to Slack for '
'our internal team communications. Slack is a '
'messaging app where we can talk, share files, '
'and work together. It also connects with tools '
'we already use, like [add your examples here], '
'plus 900+ other apps.\n\n',
),
TextSpan(
text: 'Why are we moving to Slack?\n\n',
style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
TextSpan(
text:
'We want to use the best communication tools to '
'make our lives easier and be more productive. '
'Having everything in one place will help us '
'work together better and faster, rather than '
'jumping around between emails, IMs, texts and '
'a bunch of other programs. Everything you share '
'in Slack is automatically indexed and archived, '
'creating a searchable archive of all our work.',
),
],
),
),
],
),
),
),
);
},
),
);
}
}
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
So I am trying to have a Showcase in my CupertinoNavigationBar, but when I navigate to the Detail page, I get an exception 'Please provide ShowCaseView context'. I have saved the context from the ShowCaseWidget and applied it, but I can't get it to work at all. As soon as you click on the top item to pull up the Detail page, the error happens. If you change the DEBUG_showShowcase to false so that there is no showcase in the navigationBar everything works fine. Not sure if I am doing something wrong with the CupertinoNavigationBar or ShowCaseWidget.
I took the example and tried to make it work with the CupertinoNavigationBar.
Anyone help is appreciated.
Beta Was this translation helpful? Give feedback.
All reactions