black screen with Dismissible - flutter

i am trying to call Navigator.pop(context); from Dismissible like following
#override
Widget build(BuildContext context) {
return Dismissible(
key: const Key('some key here'),
direction: DismissDirection.down,
onDismissed: (l) {
Navigator.pop(context);
},
child: const Scaffold(
backgroundColor: Colors.yellowAccent,
),
);
}
}
it is work fine but the problem is once i swipe i see black screen !
how could i make it transparent so i can see the previous page instead of black screen ..
if it is not possible with Dismissible please suggest to me any other way to make it done
import 'package:flutter/material.dart';
class myFirstPag extends StatefulWidget {
const myFirstPag({Key? key}) : super(key: key);
#override
myFirstPagState createState() => myFirstPagState();
}
class myFirstPagState extends State<myFirstPag> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: (){
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return mySecPag();
}
)
);
},
child: const Scaffold(
backgroundColor: Colors.red,
body: Center(child: Text('my First Page')
),
),
);
}
}
class mySecPag extends StatefulWidget {
const mySecPag({Key? key}) : super(key: key);
#override
mySecPagState createState() => mySecPagState();
}
class mySecPagState extends State<mySecPag> {
#override
Widget build(BuildContext context) {
return Dismissible(
key: const Key('some key here'),
direction: DismissDirection.down,
onDismissed: (l) {
Navigator.pop(context);
},
child: const Scaffold(
backgroundColor: Colors.yellowAccent,
body: Center(child: Text('my sec page'),),
),
);
}
}

I don't think you will able to achive it by Dismissible widget:
I have modified your code slightly to this:
import 'package:flutter/material.dart';
class myFirstPag extends StatefulWidget {
const myFirstPag({Key? key}) : super(key: key);
#override
myFirstPagState createState() => myFirstPagState();
}
class myFirstPagState extends State<myFirstPag> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return mySecPag();
}));
},
child: const Scaffold(
backgroundColor: Colors.red,
body: Center(child: Text('my First Page')),
),
);
}
}
class mySecPag extends StatefulWidget {
const mySecPag({Key? key}) : super(key: key);
#override
mySecPagState createState() => mySecPagState();
}
class mySecPagState extends State<mySecPag> {
#override
Widget build(BuildContext context) {
return Dismissible(
key: const Key('some key here'),
direction: DismissDirection.down,
background: Container(color: Colors.red),
onDismissed: (l) {
Navigator.pop(context);
},
child: const Scaffold(
backgroundColor: Colors.yellowAccent,
body: Center(
child: Text('my sec page'),
),
),
);
}
}
I have added background property in Dismisible Widget, now whenever you swipe you can see that color will be shown.
But the style you want to achieve, you can do it with CupertinoRoutes.
Example of your code using CupertinoRoutes routes:
class myFirstPag extends StatefulWidget {
const myFirstPag({Key? key}) : super(key: key);
#override
myFirstPagState createState() => myFirstPagState();
}
class myFirstPagState extends State<myFirstPag> {
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.of(context).push(mySecPag.route());
},
child: const Scaffold(
backgroundColor: Colors.red,
body: Center(child: Text('my First Page')),
),
);
}
}
class mySecPag extends StatefulWidget {
const mySecPag({Key? key}) : super(key: key);
static Route<dynamic> route() {
return CupertinoPageRoute(
builder: (BuildContext context) {
return mySecPag();
},
);
}
#override
mySecPagState createState() => mySecPagState();
}
class mySecPagState extends State<mySecPag> {
#override
Widget build(BuildContext context) {
return const Scaffold(
backgroundColor: Colors.yellowAccent,
body: Center(
child: Text('my sec page'),
),
);
}
}
Here's the full tutorial for it: Link

i found solution finally ..
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(
title: 'Navigation Basics',
home: FirstRoute(),
));
}
class FirstRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('First Route'),
),
body: Center(
child: RaisedButton(
child: Text('Open route'),
onPressed: () {
showGeneralDialog(
barrierLabel: "Label",
barrierDismissible: false,
barrierColor: Colors.black.withOpacity(0.5),
transitionDuration: Duration(milliseconds: 400),
context: context,
pageBuilder: (context, anim1, anim2) {
return SecondRoute();
},
transitionBuilder: (context, anim1, anim2, child) {
return SlideTransition(
position: Tween(begin: Offset(0, 1), end: Offset(0, 0))
.animate(anim1),
child: child,
);
},
);
},
),
),
);
}
}
class SecondRoute extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Dismissible(
direction: DismissDirection.vertical,
key: const Key('key'),
onDismissed: (_) => Navigator.of(context).pop(),
child: Scaffold(
appBar: AppBar(
title: Text("Second Route"),
),
body: Align(
alignment: Alignment.center,
child: Container(
height: 300,
width: 300,
child: SizedBox.expand(child: FlutterLogo()),
margin: EdgeInsets.only(bottom: 50, left: 12, right: 12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(40),
),
),
),
),
);
}
}

Try This Code:
it is work fine!
import 'package:flutter/material.dart';
class mySecPag extends StatefulWidget {
const mySecPag({Key? key}) : super(key: key);
#override
mySecPagState createState() => mySecPagState();
}
class mySecPagState extends State<mySecPag> {
#override
Widget build(BuildContext context) {
return Dismissible(
background: Container(
color: Colors.red,
),
key: const Key('some key here'),
direction: DismissDirection.down,
onDismissed: (l) {
},
child: const Scaffold(
backgroundColor: Colors.yellowAccent,
body: Center(child: Text('my Contents'),),
),
);
}
}

You can try this code:
First screen
import 'package:flutter/material.dart';
import 'package:surplus_construction/screens/trash/trash_file.dart';
class NewTrash extends StatefulWidget {
const NewTrash({super.key});
#override
State<NewTrash> createState() => _TrashViewState();
}
class _TrashViewState extends State<NewTrash> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.yellowAccent,
body: Center(
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => TrashView()),
);
},
child: Text('Press me')),
),
),
);
}
}
Second screen:
import 'package:flutter/material.dart';
class TrashView extends StatefulWidget {
const TrashView({super.key});
#override
State<TrashView> createState() => _TrashViewState();
}
class _TrashViewState extends State<TrashView> {
#override
Widget build(BuildContext context) {
return Dismissible(
background: Container(
color: Colors.grey,
),
key: const Key('some key here'),
direction: DismissDirection.down,
onDismissed: (l) {
Navigator.pop(context);
},
child: const Scaffold(
backgroundColor: Colors.red,
),
);
}
}

Related

How to navigate pageview pages with overwrite back button in AppBar?

I have a pageview view and it works with sliding. But how do I integrate this back button as leading: Icon(backbutton), when navigating between forms in the pageview? Thanks
screen1.dart
import 'package:app/src/features/examples/components/body.dart';
class OnboardingExampleFlowPage extends StatelessWidget {
static String routeName = "/onboarding_example_flow";
const OnboardingExampleFlowPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 1,
backgroundColor: AppColors.monochromeWhite,
title: Text(context.l10n.buttonBack),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {},
),
),
body: const Body(),
);
}
}
Body has pageview:
body.dart
class _BodyState extends State<Body> {
int currentPage = 0;
final PageController controller = PageController();
#override
void dispose() {
super.dispose();
controller.dispose();
}
#override
Widget build(BuildContext context) {
final List<Widget> formPages = <Widget>[
ExampleContent01(controller: controller),
ExampleContent02(controller: controller),
ExampleContent03(controller: controller),
ExampleContent04(controller: controller),
];
return SafeArea(
child: SizedBox(
child: Column(
children: [
const SizedBox(height: 6),
AppStepper(
currentPage: currentPage,
length: formPages.length,
noSkip: true,
),
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: getProportionateScreenWidth(20),
),
child: PageView(
controller: controller,
onPageChanged: (value) => setState(() => currentPage = value),
children: formPages,
),
),
),
],
),
),
);
}
These forms: There are contents in ExampleScreens, but I did not add their code because there are AppBar and Pageview in the code I added.
here is view: want to be able to go back inside pageview.
Thanks a lot!
Just move the controller up, to the parent widget, so it's possible to navigate the pages with it.
Check out the live demo on DartPad.
The code is going to be like the following:
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const OnboardingExampleFlowPage(),
scrollBehavior: MyCustomScrollBehavior(),
debugShowCheckedModeBanner: false,
);
}
}
class OnboardingExampleFlowPage extends StatefulWidget {
static String routeName = "/onboarding_example_flow";
const OnboardingExampleFlowPage({Key? key}) : super(key: key);
#override
State<OnboardingExampleFlowPage> createState() =>
_OnboardingExampleFlowPageState();
}
class _OnboardingExampleFlowPageState extends State<OnboardingExampleFlowPage> {
final PageController controller = PageController();
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
extendBodyBehindAppBar: true,
appBar: AppBar(
elevation: 1,
title: const Text('Back'),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
controller.previousPage(
duration: const Duration(milliseconds: 250),
curve: Curves.easeOut,
);
},
),
),
body: Body(controller: controller),
);
}
}
class Body extends StatefulWidget {
const Body({super.key, required this.controller});
final PageController controller;
#override
State<Body> createState() => _BodyState();
}
class _BodyState extends State<Body> {
int currentPage = 0;
#override
Widget build(BuildContext context) {
const List<Widget> formPages = [
Center(child: Text('Page 1')),
Center(child: Text('Page 2')),
Center(child: Text('Page 3')),
Center(child: Text('Page 4')),
];
return SafeArea(
child: SizedBox(
child: Column(
children: [
const SizedBox(height: 6),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: PageView(
controller: widget.controller,
onPageChanged: (value) => setState(() => currentPage = value),
children: formPages,
),
),
),
],
),
),
);
}
}
// Enables scrolling with mouse dragging
class MyCustomScrollBehavior extends MaterialScrollBehavior {
#override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}
Dont have body widget in separate file
Put it in the _OnboardingExampleFlowPageState instead.
And it is the _OnboardingExampleFlowPageState that should have controller and
currentIndex variables.
So on leading button click you'll do something like this:
onPressed: () {
if (currentPage > 0) {
controller.previousPage(
duration: const Duration(milliseconds: 200),
curve: Curves.easeOut,
);
setState(() {
currentPage--;
});
}
},

Unable to navigate from GetX Dialog to another screen

I have follow dialog box. When I click 'Next' I want it to navigate to GamePage() screen. But unfortunately it doesn't work.
Following is the GamePage Widget
class GamePage extends StatelessWidget {
final homeCtrl = Get.find<HomeController>();
GamePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFF8fb1ca),
body: SafeArea(
child: ListView(
children: [
Padding(
padding: EdgeInsets.all(3.0.wp),
child: Row(
children: [
IconButton(
onPressed: () {
Get.back();
},
icon: const Icon(Icons.arrow_back),
),
],
),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 4.0.wp),
child: Column(
children: [
SizedBox(
height: 2.0.wp,
),
Center(
child: Text(
'What ${homeCtrl.currentWord.first.wordtype} is this?',
style: TextStyle(
fontSize: 18.0.sp,
color: Colors.grey[800],
),
),
),
SizedBox(height: 10.0.wp),
WordsWidget(currentWord: homeCtrl.currentWord.first),
],
),
),
],
),
),
);
}
}
Following is the Word Widget being called from GamePage Widget
class WordsWidget extends StatelessWidget {
final currentWord;
WordsWidget({Key? key, this.currentWord}) : super(key: key);
final homeCtrl = Get.find<HomeController>();
#override
Widget build(BuildContext context) {
// var currentWord = homeCtrl.nextWord();
var shuffleword = [].obs;
shuffleword.addAll(homeCtrl.shuffleWord(currentWord.word));
TextToSpeech tts = TextToSpeech();
String language = 'en-US';
tts.setLanguage(language);
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
print('pressed here');
Get.defaultDialog(
title: 'Go to next page',
content: Container(
child: Column(
children: [
Text('You are about to move to another screen'),
ElevatedButton.icon(
onPressed: () {
Get.to(() => GamePage());
},
icon: Icon(
Icons.arrow_right,
),
label: Text('Go'))
],
),
));
},
child: Text('Open Dialog')),
],
);
}
}
Get.back() is working but not Get.to
Try
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) {
return const GamePage();
},
),
);
},
child: Text("Next Word"),
)
Try this code -
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_memory/next_page.dart';
import 'package:image_picker/image_picker.dart';
void main() {
//check getMaterialApp is used
runApp(const GetMaterialApp(
title: 'Temp',
home: const MyApp(),
));
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Image Picker'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
print('pressed here');
Get.defaultDialog(
title: 'Go to next page',
content: Container(
child: Column(
children: [
Text('You are about to move to another screen'),
ElevatedButton.icon(
onPressed: () {
Get.to(() => NextPage());
},
icon: Icon(
Icons.arrow_right,
),
label: Text('Go'))
],
),
));
},
child: Text('Open Dialog')),
),
);
}
}
and next page is -
import 'package:flutter/material.dart';
class NextPage extends StatefulWidget {
const NextPage({ Key? key }) : super(key: key);
#override
State<NextPage> createState() => _NextPageState();
}
class _NextPageState extends State<NextPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Next Page'),
),
body: Container(
child: Center(
child: Text("this is next page"),
),
),
);
}
}
And yes, you need to insure that you are using 'GetMaterialApp'.
If you want to use GetX navigation system, you should wrap your application in a GetMaterialApp instead of MaterialApp.
So in your main use this:
class GetxApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GetMaterialApp(
home: HomePage(),
);
}
}
Instead of this:
class NormalApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}

ListTile tileColor overflowing ListView

I have a ListView with ListTiles which set the tileColor property. All of the text and icons in the ListTile is clipped while the tileColor is visible beyond the ListView. How can I clip the entire ListTile so that nothing is visible beyond the ListView? I have tried wrapping ListView in various containers and the ListTile in a Container with no luck.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: const MyHomePage(title: 'Reminders'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List _reminders = <String>[];
void _addReminder(String text) {
setState(() {
_reminders.add(text);
});
}
Widget _buildRow(String text, int i) {
return ListTile(
title: Text('[enter image description here][1]Reminder'),
trailing: IconButton(
onPressed: () {
setState(() {
_reminders.removeAt(i);
});
},
icon: Icon(Icons.delete)),
subtitle: Text(text),
tileColor: Colors.lightBlue,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
);
}
void _showMenu() {}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: [IconButton(onPressed: _showMenu, icon: const Icon(Icons.list))],
),
body: Column(
children: <Widget>[
Container(
height: 400,
child: ListView.builder(
padding: EdgeInsets.all(8),
itemBuilder: (context, i) => _buildRow(_reminders[i], i),
itemCount: _reminders.length,
),
),
Container(
height: 100,
width: double.infinity,
child: Text('hello'),
)
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_addReminder('hello there');
},
child: const Icon(Icons.add),
),
);
}
}
To solve your problem, wrap the Tile in a Material. Here is a tested solution. The explanation is below the code.
The short version:
Widget _buildRow(String text, int i) {
return Material(
child: ListTile(
title: Text('[enter image description here][$i]Reminder'),
trailing: IconButton(
onPressed: () {
setState(() {
_reminders.removeAt(i);
});
},
icon: const Icon(Icons.delete)),
subtitle: Text(text),
tileColor: Colors.lightBlue,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
));
}
The complete, working example:
```
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: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: const MyHomePage(title: 'Reminders'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List _reminders = <String>[];
void _addReminder(String text) {
setState(() {
_reminders.add(text);
});
}
Widget _buildRow(String text, int i) {
return Material(child: ListTile(
title: Text('[enter image description here][$i]Reminder'),
trailing: IconButton(
onPressed: () {
setState(() {
_reminders.removeAt(i);
});
},
icon: const Icon(Icons.delete)),
subtitle: Text(text),
tileColor: Colors.lightBlue,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
));
}
void _showMenu() {}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: [IconButton(onPressed: _showMenu, icon: const Icon(Icons.list))],
),
body: Column(
children: <Widget>[
Container(
height: 400,
child: ClipRect(
child: ListView.builder(
shrinkWrap: true,
padding: const EdgeInsets.all(8),
itemBuilder: (context, i) => _buildRow(_reminders[i], i),
itemCount: _reminders.length,
),
)
),
Container(
color: Colors.white,
width: double.infinity,
child: Text('hello'),
)
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_addReminder('hello there');
},
child: const Icon(Icons.add),
),
);
}
}
```
This might be considered a bug, but it is expected behavior. The tile colors are painted by the first Material widget ancestor of the ListTile (I believe this allows it to optimize out expensive clipping). See the ListTile documentation for more information.
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
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: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: const MyHomePage(title: 'Reminders'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// ignore: prefer_final_fields
List _reminders = <String>[];
void _addReminder(String text) {
setState(() {
_reminders.add(text);
});
}
Widget _buildRow(String text, int i) {
return ListTile(
title: const Text('Reminder'),
trailing: IconButton(
onPressed: () {
setState(() {
_reminders.removeAt(i);
});
},
icon: const Icon(Icons.delete)),
subtitle: Text(text),
tileColor: Colors.lightBlue,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
);
}
void _showMenu() {}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: [IconButton(onPressed: _showMenu, icon: const Icon(Icons.list))],
),
body: ListView.separated(
padding: const EdgeInsets.all(8),
itemBuilder: (context, i) => _buildRow(_reminders[i], i),
itemCount: _reminders.length, separatorBuilder: (BuildContext context, int index) {
return const SizedBox(height:10);},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_addReminder('hello there');
},
child: const Icon(Icons.add),
),
);
}
}
Here is my code with solution
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.teal,
),
home: const MyHomePage(title: 'Reminders'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List _reminders = <String>[];
void _addReminder(String text) {
setState(() {
_reminders.add(text);
});
}
Widget _buildRow(String text, int i) {
return Container(
margin: EdgeInsets.symmetric(vertical: 5),
child: ListTile(
title: Text('[enter image description here][1]Reminder'),
trailing: IconButton(
onPressed: () {
setState(() {
_reminders.removeAt(i);
});
},
icon: Icon(Icons.delete)),
subtitle: Text(text),
tileColor: Colors.lightBlue,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
);
}
void _showMenu() {}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: [
IconButton(onPressed: _showMenu, icon: const Icon(Icons.list))
],
),
body: Column(
children: <Widget>[
SizedBox(
height: 200,
child: ListView.builder(
scrollDirection: Axis.vertical,
padding: EdgeInsets.all(8),
itemBuilder: (context, i) => _buildRow(_reminders[i], i),
itemCount: _reminders.length,
),
),
Expanded(
child: Container(
color: Colors.white,
width: double.infinity,
child: Text('hello'),
),
)
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_addReminder('hello there');
},
child: const Icon(Icons.add),
),
);
}
}
here is ss

Bounce Dismissible for helping the user

So we have a Dismissible for confirming/denying a item.
However we have some users that are trying to click/tap on the item.
Our UX team suggested that we then "bounce" the item to show that they have to swipe (and reveal the action fields).
But I don't see any option to do so.
Does anybody have a suggestion what might work for this?
The code I have for now is shown below:
Dismissible(
key: const ValueKey(0),
direction: DismissDirection.horizontal,
child: Container(
margin: EdgeInsets.symmetric(horizontal: 3, vertical: 3),
child: card(),
),
confirmDismiss: (direction) async {
var newStatus = direction == DismissDirection.startToEnd
? OkNokNvt.OK
: OkNokNvt.NOK;
_changeStatus(newStatus);
return false;
},
background: ok(),
secondaryBackground: nok(),
),
The Dismissable doesn't seeem to have this functionality.
Instead, you could use the flutter_slidable package.
Here, you can programmatically open the underlying actions by calling Slideable.of(context)?.open(). No fancy bounce-animation though.
Here's the code:
import 'package:flutter/material.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Bouncing Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Slidable(
key: const Key('key'),
actionPane: const SlidableDrawerActionPane(),
actionExtentRatio: 0.25,
child: Builder(
builder: (context) => GestureDetector(
onTap: () {
Slidable.of(context)
?.open(actionType: SlideActionType.primary);
},
child: Container(
color: Colors.grey,
height: 50,
child: const Center(child: Text('Tap me')),
),
),
),
actions: [
IconSlideAction(
caption: 'Delete',
color: Colors.red,
icon: Icons.delete,
onTap: () => print('remove me from list'),
),
],
dismissal: SlidableDismissal(
onDismissed: (_) => print('remove me from list'),
dragDismissible: true,
child: const SlidableDrawerDismissal(),
),
),
],
),
),
);
}
}
Here is my minimal example which does what you are looking for.
Basically, the GestureDetector onTap callback triggers the animation which has a bouncing-like effect by using a sin function on the _animation.value. The behaviour can be tweeked by changing the parameters cyclesPerAnimation and bounceOffset.
Simply put your Dismissible in the place of the Container and you should be good to go.
environment:
sdk: ">=2.12.0 <3.0.0"
import 'dart:math';
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(
theme: ThemeData.dark(),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late final AnimationController _animation = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
);
Offset _bounceOffset(double animationValue) {
const cyclesPerAnimation = 2;
const bounceOffset = 10;
return Offset(
0,
sin(animationValue * pi * 2 * cyclesPerAnimation) * bounceOffset,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Bouncing Widget Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedBuilder(
animation: _animation,
builder: (context, widget) => Transform.translate(
offset: _bounceOffset(_animation.value),
child: GestureDetector(
onTap: () {
_animation.reset();
_animation.forward();
},
child: Container(
color: Colors.grey,
height: 50,
width: 200,
child: const Center(child: Text('Tap to bounce')),
),
),
),
),
],
),
),
);
}
}

flutter dependOnInheritedWidgetOfExactType() returns null

I am trying to use InheritedWidget approach to share state down the Widget tree. For this, I am making a simple counter app. You can add, subtract, multiply or divide the counter however you like.
It's a small demo so best practices are not followed. The line with code context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>() seem to be null for some reason. When looking at samples and doc, it should find the MyInheritedWidget in the widget tree and return it. However, I am getting complaints from flutter tool that it is null. And, in deed it is null when asserted as well.
What is the reasoning here for failed return here? And, how do I need to do it such that I can receive the instance?
File: main.dart
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(
home: Counter(),
);
}
}
class Counter extends StatefulWidget {
const Counter({Key? key}) : super(key: key);
#override
CounterState createState() => CounterState();
}
class CounterState extends State<Counter> {
int counter = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
centerTitle: true,
),
body: MyInheritedWidget(
counterState: this,
child: Builder(
builder: (BuildContext innerContext) {
return CounterViewer(
counterState: MyInheritedWidget.of(context).counterState);
},
),
),
);
}
void addCounter(int value) {
setState(() {
counter++;
});
}
void subtractCounter(int value) {
setState(() {
counter--;
});
}
void multiplyCounter(int value) {
setState(() {
counter *= value;
});
}
void divideCounter(int value) {
setState(() {
counter = (counter / value).toInt();
});
}
}
class MyInheritedWidget extends InheritedWidget {
final CounterState counterState;
const MyInheritedWidget(
{Key? key, required Widget child, required this.counterState})
: super(key: key, child: child);
static MyInheritedWidget of(BuildContext context) {
final MyInheritedWidget? widget =
context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
assert(widget != null);
return widget!;
}
#override
bool updateShouldNotify(covariant InheritedWidget oldWidget) {
return true;
}
}
class CounterViewer extends StatelessWidget {
final CounterState counterState;
const CounterViewer({Key? key, required this.counterState}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
color: Colors.green.shade200,
width: MediaQuery.of(context).size.width,
height: 180,
child: Center(
child: Text(
'220',
style: TextStyle(
color: Colors.grey.shade50,
fontSize: 60,
fontWeight: FontWeight.bold,
),
),
),
),
Container(
color: Colors.grey.shade300,
padding: EdgeInsets.symmetric(vertical: 16),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {},
child: Text('Add'),
),
ElevatedButton(
onPressed: () {},
child: Text('Subtract'),
),
ElevatedButton(
onPressed: () {},
child: Text('Multiply'),
),
ElevatedButton(
onPressed: () {},
child: Text('Divide'),
),
],
),
)
],
);
}
}
Update: I seem to have passed the wrong context to the dependOnInheritedWidgetOfExactType() method. Changing from context to innerContext fixed the issue.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
centerTitle: true,
),
body: MyInheritedWidget(
counterState: this,
child: Builder(
builder: (BuildContext innerContext) {
return CounterViewer(
counterState: MyInheritedWidget.of(innerContext).counterState);
},
),
),
);
}