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
Related
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,
),
);
}
}
I'm building my app with Flutter 2.10.5 and Dart 2.16.2.
When i try to refresh the demo content whith a pull, nothing happens. I have multiple navigation routes for different content. So the demo is a litte bit complex.
The main.dart includes the basic code for the app. I use the NavDrawer Widget to build the different pages. Every route is defined in the navigation.dart file, which reference to the content widgets.
My code so far is:
import 'dart:core';
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of the application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Demo Company',
theme: ThemeData(),
debugShowCheckedModeBanner: false,
home: const HomePage(title: 'Demo Company'),
);
}
}
class _HomePageState extends State<HomePage> {
#override
initState() {
super.initState();
}
Widget _infoTile(String title, String subtitle) {
return ListTile(
title: Text(title),
subtitle: Text(subtitle.isEmpty ? 'Not set' : subtitle),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: const NavDrawer(),
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
children: <Widget>[
_infoTile('App name', 'Demo App....'),
// Multiple Liste Tiles...
],
),
),
);
}
}
//----------------------------------------------------------------------
// navigation.dart
//----------------------------------------------------------------------
class NavDrawer extends StatelessWidget {
const NavDrawer({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const <Widget>[
Text(
'Navigation',
style: TextStyle(color: Colors.white, fontSize: 30),
),
SizedBox(height: 30.0),
Text('Firstname', style: TextStyle(color: Colors.black, fontSize: 15)),
Text('Accountname', style: TextStyle(color: Colors.black, fontSize: 15)),
],
),
),
ListTile(
leading: const Icon(Icons.notifications),
title: const Text('Demo'),
onTap: () {
Navigator.push(
context,
Demo.route(),
);
},
),
// Multiple Navigation List Tiles...
],
),
);
}
}
//----------------------------------------------------------------------
// demo.dart
//----------------------------------------------------------------------
class HomePage extends StatefulWidget {
const HomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<HomePage> createState() => _HomePageState();
}
class Demo extends StatefulWidget {
const Demo({Key? key}) : super(key: key);
static Route route() {
return CupertinoPageRoute(builder: (_) => const Demo());
}
#override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
final _data = <WordPair>[];
#override
void initState() {
super.initState();
_data.addAll(generateWordPairs().take(20));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Woolha.com Flutter Tutorial'),
),
body: _buildList(),
);
}
Widget _buildList() {
return RefreshIndicator(
onRefresh: _refreshData,
child: ListView.builder(
padding: const EdgeInsets.all(20.0),
itemBuilder: (context, index) {
WordPair wordPair = _data[index];
return _buildListItem(wordPair.asString, context);
},
itemCount: _data.length,
),
);
}
Widget _buildListItem(String word, BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(word),
),
);
}
Future _refreshData() async {
await Future.delayed(const Duration(seconds: 3));
_data.clear();
_data.addAll(generateWordPairs().take(20));
setState(() {});
}
}
class ShowMessages extends StatelessWidget {
final String type;
final Color color;
const ShowMessages({Key? key, required this.type, required this.color}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView(
//color: color,
physics: const AlwaysScrollableScrollPhysics(),
children: [
ListTile(
title: Text(
type,
style: Theme.of(context).textTheme.bodyText1,
),
),
]);
}
}
Copy this code to DartPad
What is wrong?
Well for me this code... works
I copied it into Dartpad, then Dev Tools in browser (F12) > Device Emulation > Responsive. And you can use pull to refresh.
Of course this doesn't work using web view and mouse. I believe this gesture is not supported.
I am implementing a tutorial of app using https://pub.dev/packages/tutorial_coach_mark . This marked button of beyond the view. So when I need to target this button, I need to scroll/focus this specific part. But I can not find any solution. Can anyone help me with that please?
One Idea is to , Make one Listview with all your widgets . then
Use this :
scroll_to_index: ^2.1.1
Example:
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:scroll_to_index/scroll_to_index.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Scroll To Index Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Scroll To Index Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static const maxCount = 100;
static const double maxHeight = 1000;
final random = math.Random();
final scrollDirection = Axis.vertical;
late AutoScrollController controller;
late List<List<int>> randomList;
#override
void initState() {
super.initState();
controller = AutoScrollController(
viewportBoundaryGetter: () =>
Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),
axis: scrollDirection);
randomList = List.generate(maxCount,
(index) => <int>[index, (maxHeight * random.nextDouble()).toInt()]);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: [
IconButton(
onPressed: () {
setState(() => counter = 0);
_scrollToCounter();
},
icon: Text('First'),
),
IconButton(
onPressed: () {
setState(() => counter = maxCount - 1);
_scrollToCounter();
},
icon: Text('Last'),
)
],
),
body: ListView(
scrollDirection: scrollDirection,
controller: controller,
children: randomList.map<Widget>((data) {
return Padding(
padding: EdgeInsets.all(8),
child: _getRow(data[0], math.max(data[1].toDouble(), 50.0)),
);
}).toList(),
),
floatingActionButton: FloatingActionButton(
onPressed: _nextCounter,
tooltip: 'Increment',
child: Text(counter.toString()),
),
);
}
int counter = -1;
Future _nextCounter() {
setState(() => counter = (counter + 1) % maxCount);
return _scrollToCounter();
}
Future _scrollToCounter() async {
await controller.scrollToIndex(counter,
preferPosition: AutoScrollPosition.begin);
controller.highlight(counter);
}
Widget _getRow(int index, double height) {
return _wrapScrollTag(
index: index,
child: Container(
padding: EdgeInsets.all(8),
alignment: Alignment.topCenter,
height: height,
decoration: BoxDecoration(
border: Border.all(color: Colors.lightBlue, width: 4),
borderRadius: BorderRadius.circular(12)),
child: Text('index: $index, height: $height'),
));
}
Widget _wrapScrollTag({required int index, required Widget child}) =>
AutoScrollTag(
key: ValueKey(index),
controller: controller,
index: index,
child: child,
highlightColor: Colors.black.withOpacity(0.1),
);
}
This will work Perfectly
final dataKey = new GlobalKey();
SingleChildScrollView(
child: Column(
children: [
otherwidgets(),
otherwidgets(),
Container(
key: controller.dataKey,
child: helpPart(context),
),
otherwidgets(),
otherwidgets(),
],
),
on action: Scrollable.ensureVisible(dataKey.currentContext!);
This worked for me!
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')),
),
),
),
),
],
),
),
);
}
}
I have class called A.dart in that I am usnign Interprogressbar as below
new Container(
margin: const EdgeInsets.fromLTRB(0, 10, 0, 0),
child: IntervalProgressBar(
direction: IntervalProgressDirection.horizontal,
max: count,
progress: count1,
intervalSize: 2,
size: Size(600, 10),
highlightColor: Colors.pink,
defaultColor: Colors.grey,
intervalColor: Colors.transparent,
intervalHighlightColor: Colors.transparent,
reverse: false,
radius: 0)),
Once the user clicks a button I am navigating to another class from A.dart to a class called B.dart. Once use completes process in class B.dart I ll pop the class B.dart. Again A.dart will be visible for the user. So my question us how can I restart the IntervalProgressBar with the updated value once user comes from B.dart to A,dart.
You can copy paste run full code below
You can await Navigator.push then call setState
void _gotoB() async {
String parameter = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => RouteB()),
);
setState(() {
count1 = int.tryParse(parameter);
});
}
...
RaisedButton(
child: Text('Go back'),
onPressed: () {
Navigator.pop(context, _textEditingController.text);
},
),
working demo
full code
import 'package:flutter/material.dart';
import 'package:intervalprogressbar/intervalprogressbar.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int count = 10;
int count1 = 3;
void _gotoB() async {
String parameter = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => RouteB()),
);
setState(() {
count1 = int.tryParse(parameter);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.fromLTRB(0, 10, 0, 0),
child: IntervalProgressBar(
direction: IntervalProgressDirection.horizontal,
max: count,
progress: count1,
intervalSize: 2,
size: Size(600, 10),
highlightColor: Colors.pink,
defaultColor: Colors.grey,
intervalColor: Colors.transparent,
intervalHighlightColor: Colors.transparent,
reverse: false,
radius: 0)),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _gotoB,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class RouteB extends StatefulWidget {
#override
_RouteBState createState() => _RouteBState();
}
class _RouteBState extends State<RouteB> {
TextEditingController _textEditingController = TextEditingController();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Column(
children: [
TextField(
controller: _textEditingController,
),
RaisedButton(
child: Text('Go back'),
onPressed: () {
Navigator.pop(context, _textEditingController.text);
},
),
],
)),
);
}
}