I have a problem with the search implementation - flutter

in this code a have a search function but when ever I search for apple its shows me apple a few times instead of only once
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({Key key, #required this.title}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
//Search TextField Controller
final _searchController = TextEditingController();
List<Fruit> mainList = [
Fruit(name: 'Apple', imageUrl: 'https://images.pexels.com/photos/102104/pexels-photo-102104.jpeg'),
Fruit(name: 'Banana', imageUrl: 'https://images.pexels.com/photos/5945848/pexels-photo-5945848.jpeg'),
Fruit(name: 'Pineapple', imageUrl: 'https://images.pexels.com/photos/1071878/pexels-photo-1071878.jpeg'),
Fruit(name: 'Mango', imageUrl: 'https://images.pexels.com/photos/918643/pexels-photo-918643.jpeg'),
];
List<Fruit> searchList = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
height: 60.0,
child: TextFormField(
controller: _searchController,
onChanged: (text){
final String queryString = _searchController.text;
setState((){
if(queryString.isNotEmpty){
for(final fruit in mainList){
if(fruit.name.contains(queryString)){
searchList.add(fruit);
} else{
searchList.remove(fruit);
}
}
}else{
searchList.clear();
}
});
}
),
),
Expanded(
child: _searchController.text.isEmpty
? GridView.count(
crossAxisCount: 2,
children: mainList.map((fruit)=> CardWidget(fruit: fruit)).toList(),
)
:GridView.count(
crossAxisCount: 2,
children: searchList.map((searchedFruit)=>CardWidget(fruit: searchedFruit)).toList()
),
),
],
),
);
}
}
I think that the main problem here is with the searchList, It just add the same fruit over and over.
Class to hold Fruit
class Fruit{
final String imageUrl;
final String name;
Fruit({this.imageUrl, this.name});
}
widget to be built for each fruit object found in the mainList
//Card Widget
class CardWidget extends StatefulWidget{
final Fruit fruit;
CardWidget({this.fruit});
#override
_CardWidgetState createState()=> _CardWidgetState();
}
class _CardWidgetState extends State<CardWidget>{
#override
Widget build(BuildContext context){
return Container(
width: 100.0,
height: 140.0,
child: Column(
children:[
Image(image: NetworkImage(widget.fruit.imageUrl)),
SizedBox(height: 10.0),
Text(widget.fruit.name),
]
)
);
}
}

Ok, I believe the problem is every time you enter a new character the code will search and add to the search list, but you have to reset the list for each search otherwise the list will have repeated characters. Here's how to do it:
onChanged: (text){
final String queryString = _searchController.text;
setState((){
if(queryString.isNotEmpty){
searchList.clear(); // clear the list before the search loop
for(final fruit in mainList){
if(fruit.name.contains(queryString)){
searchList.add(fruit);
} else{
searchList.remove(fruit);
}
}
}else{
searchList.clear();
}
}

try this..
initialize debounce below the TextEditingController
final _searchController = TextEditingController();
final _deBouncer = Debouncer(millisecound: 400);
replace onChanged function
onChanged: (text) async {
searchList.clear();
await _deBouncer.run(() {
final String queryString = text;
if (queryString.isNotEmpty) {
for (final fruit in mainList) {
if
(fruit.name?.toLowerCase().contains(queryString.toLowerCase()) ??
false) {
searchList.add(fruit);
}
}
}
setState(() {});
});
}),
add this class for when user stop to typing in search text field
class Debouncer {
final int? millisecound;
VoidCallback? action;
Timer? _timer;
Debouncer({this.millisecound});
run(VoidCallback action) {
if (_timer != null) {
_timer?.cancel();
}
_timer = Timer(Duration(milliseconds: millisecound ?? 300), action);
}
}

Related

How to display data from nested list in Flutter

When I try display data from nested list it gives me that data which is not list at all.
Please help how to get that options data as list and display on Flutter widget.
class QuizData {
List<BrainData> getData = [
BrainData(
questionID: "biology1",
question:
"Pine, fir, spruce, cedar, larch and cypress are the famous timber-yielding plants of which several also occur widely in the hilly regions of India. All these belong to",
options: [
"angiosperms",
"gymnosperms",
"monocotyledons",
"dicotyledons",
],
answer: [false, true, false, false],
),
];
}
From the question, I have created a sample example for you.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Test App',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
List<BrainData> list = [];
var selectedValue;
List<BrainData> getData = [
BrainData(
questionID: "biology1",
question:
"Pine, fir, spruce, cedar, larch and cypress are the famous timber-yielding plants of which several also occur widely in the hilly regions of India. All these belong to",
options: [
"angiosperms",
"gymnosperms",
"monocotyledons",
"dicotyledons",
],
answer: [false, true, false, false],
),
];
#override
void initState() {
super.initState();
setState(() {
list = getData;
});
}
void showInSnackBar(String value, bool isCorrect) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
backgroundColor: isCorrect ? Colors.green : Colors.red,
content: Text(value),
duration: const Duration(milliseconds: 200),
));
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: list.isEmpty
? Container()
: ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
var item = list[index];
return Column(
children: [
Padding(
padding: const EdgeInsets.all(15.0),
child: Text('${index + 1} : ${item.question}'),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: item.options.map((e) {
return RadioListTile(
title: Text(e),
value: e,
groupValue: selectedValue,
onChanged: (value) {
setState(() {
selectedValue = value;
var correctAnswerIndex = item.answer.indexWhere((element) => element == true);
var selectedItemIndex =
item.options.indexWhere((element) => element == value);
if (correctAnswerIndex == selectedItemIndex) {
showInSnackBar('Selected Correct Value', true);
} else {
showInSnackBar('Better luck next time', false);
}
});
},
);
}).toList(),
),
)
],
);
}),
);
}
}
class BrainData {
final String questionID;
final String question;
final List<String> options;
final List<bool> answer;
BrainData({
required this.questionID,
required this.question,
required this.options,
required this.answer,
});
}
This is the Sample UI:
Check the example and let me know if it works for you.

Flutter post HTTP request

I'm trying to send a post request and then get some response. This is the site: www.reqres.in and the user data https://reqres.in/api/users.
When I press the Button I don't see any text. Posting name and job to an API and receiving name, id, Datetime and job. If I don't use Widget _showData and show the text in the build below text field then I see the Data, but with a lateInitialization error, but I want to show it using the Widget _showData.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:http_req_advanced/usermodel.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'HTTP Request 2',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var users;
Future<UserModel> createUser(String name, String job) async {
final apiUrl = "https://reqres.in/api/users";
final response =
await http.post(Uri.parse(apiUrl), body: {"name": name, "job": job});
if (response.statusCode == 201) {
users = userModelFromJson(response.body);
} else
throw Exception('Failed to load');
return users;
}
late UserModel user;
final nameController = TextEditingController();
final jobController = TextEditingController();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('HTTP Request'),
),
body: Container(
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
controller: nameController,
),
TextField(
controller: jobController,
),
//Text(
// "The user ${user.name} ${user.id} is created at ${user.createdAt} with job${user.job}"),
ElevatedButton(
onPressed: () async {
final String name = nameController.text;
final String job = jobController.text;
final UserModel userr = await createUser(name, job);
setState(() {
user = userr;
_showData(user.name, user.job, user.id, user.createdAt);
});
},
child: Text('Make a Request'),
),
],
),
),
),
);
}
Widget _showData(String name, String job, String id, DateTime createdat) {
return Container(
alignment: Alignment.bottomCenter,
child: SizedBox(
height: 32,
child:
Text('The user $name [$id] is created at $createdat with job $job'),
),
);
}
}
Instead of using late initialization:
late UserModel user;
Use:
UserModel? user;
When you use late you are declaring a non null variable that will be later initialized, in this case you don't need to use late because user can be null.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:http_req_advanced/usermodel.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'HTTP Request 2',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var users;
Future<UserModel> createUser(String name, String job) async {
final apiUrl = "https://reqres.in/api/users";
final response =
await http.post(Uri.parse(apiUrl), body: {"name": name, "job": job});
if (response.statusCode == 201) {
users = userModelFromJson(response.body);
} else
throw Exception('Failed to load');
return users;
}
late UserModel user;
final nameController = TextEditingController();
final jobController = TextEditingController();
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
title: Text('HTTP Request'),
),
body: Container(
padding: EdgeInsets.all(16),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
controller: nameController,
),
TextField(
controller: jobController,
),
user != null
? _showData(user.name, user.job, user.id, user.createdAt)
: Container(),
//Text(
// "The user ${user.name} ${user.id} is created at ${user.createdAt} with job${user.job}"),
ElevatedButton(
onPressed: () async {
final String name = nameController.text;
final String job = jobController.text;
final UserModel userr = await createUser(name, job);
setState(() {
user = userr;
});
},
child: Text('Make a Request'),
),
],
),
),
),
);
}
Widget _showData(String name, String job, String id, DateTime createdat) {
return Container(
alignment: Alignment.bottomCenter,
child: SizedBox(
height: 32,
child:
Text('The user $name [$id] is created at $createdat with job $job'),
),
);
}
}

Flutter error: type '(String, ItemPriority) => void' is not a subtype of type '(String, [ItemPriority]) => dynamic'

I'm new to Flutter and working on a simple todo list app. For the homepage, I would like to have a list of todo items and a button to add a new todo item. Tapping the 'new' button should pull up a window to type a title for the todo item and add a priority from 1-5 using my custom radio buttons. Clicking the send/submit button on this window should add it to the list of todo items (displayed in a ListView).
I'm getting this error: type '(String, ItemPriority) => void' is not a subtype of type '(String, [ItemPriority]) => dynamic'
It's coming from line 79 "TodoInputWidget(this.newTodoItem)," and I've tried to trace the cause of the error, but I'm not sure I fully understand it. I can't find anywhere that would be producing a list of ItemPrioritys.
I really appreciate any insight on this issue!
Here's the code I have right now:
import 'package:flutter/material.dart';
import 'textInputWidget.dart';
void main() {
runApp(MyApp());
}
enum ItemPriority { low, low_med, med, med_high, high }
extension ItemPriorityExtension on ItemPriority {
RadioModel get radio {
switch (this) {
case ItemPriority.low:
return new RadioModel(true, '1', Colors.green);
case ItemPriority.low_med:
return new RadioModel(true, '2', Colors.lightGreen);
case ItemPriority.med:
return new RadioModel(true, '3', Colors.yellow);
case ItemPriority.med_high:
return new RadioModel(true, '2', Colors.orange);
case ItemPriority.high:
return new RadioModel(true, '2', Colors.red);
default:
return new RadioModel(true, '3', Colors.yellow);
}
}
}
class TodoItem {
String task;
ItemPriority priority;
TodoItem(this.task, this.priority);
}
class RadioModel {
bool isSelected;
String radioNumText;
Color color;
RadioModel(this.isSelected, this.radioNumText, this.color);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Weekly ToDo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<TodoItem> todos = [];
void newTodoItem(String text, ItemPriority priority) {
this.setState(() {
todos.add(new TodoItem(text, priority));
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Weekly ToDo')),
body: Column(
children: <Widget>[
Expanded(child: TodoList(this.todos)),
TodoInputWidget(this.newTodoItem),
],
),
);
}
}
class TodoInputWidget extends StatefulWidget {
final Function(String, [ItemPriority]) callback;
TodoInputWidget(this.callback);
#override
_TodoInputWidgetState createState() => _TodoInputWidgetState();
}
class _TodoInputWidgetState extends State<TodoInputWidget> {
String text;
ItemPriority priority;
CustomRadio radio = new CustomRadio(ItemPriority.med);
bool selected = false;
void createTodo(String text) {
this.setState(() {
widget.callback(text, radio.priority);
});
}
createTodoWindow(BuildContext context) {
return showDialog(
context: context,
builder: (context) => SimpleDialog(
title: Text('Create new task'),
children: <Widget>[radio, TextInputWidget(this.createTodo)],
));
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
createTodoWindow(context);
},
child: Container(
alignment: Alignment.center,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.green,
),
),
);
}
}
class TodoList extends StatefulWidget {
final List<TodoItem> todoItems;
TodoList(this.todoItems);
#override
_TodoListState createState() => _TodoListState();
}
class _TodoListState extends State<TodoList> {
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: this.widget.todoItems.length,
itemBuilder: (context, index) {
var todoItem = this.widget.todoItems[index];
return ListTile(title: Text(todoItem.task));
},
);
}
}
class RadioItem extends StatelessWidget {
final RadioModel item;
RadioItem(this.item);
#override
Widget build(BuildContext context) {
return Container(
child: Text(item.radioNumText),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: item.color,
),
alignment: Alignment.center,
);
}
}
//ignore: must_be_immutable
class CustomRadio extends StatefulWidget {
ItemPriority priority;
CustomRadio(this.priority);
#override
_CustomRadioState createState() => _CustomRadioState();
}
class _CustomRadioState extends State<CustomRadio> {
List<RadioModel> priorityChoices = new List<RadioModel>();
ItemPriority priority;
#override
void initState() {
super.initState();
widget.priority = priority;
priorityChoices.add(ItemPriority.low.radio);
priorityChoices.add(ItemPriority.low_med.radio);
priorityChoices.add(ItemPriority.med.radio);
priorityChoices.add(ItemPriority.med_high.radio);
priorityChoices.add(ItemPriority.high.radio);
}
#override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: priorityChoices.length,
itemBuilder: (context, index) {
return IconButton(
onPressed: () {
priorityChoices.forEach((element) {
element.isSelected = false;
});
priorityChoices[index].isSelected = true;
priority = ItemPriority.values[index];
},
icon: RadioItem(priorityChoices[index]),
);
},
);
}
}
Replace function ;
dynamic newTodoItem(String text, [ItemPriority priority]) {
this.setState(() {
todos.add(new TodoItem(text, priority));
});
return some.. or null;
}

Text not getting updated with new value in flutter

Hi I am new to flutter and experimenting with statefull widget. I am trying to build a timer and want to show it in a Text.
This is my widget class.
class MobileVerification extends StatefulWidget {
static const String MOBILE = 'mobile';
final Map<String, dynamic> args;
MobileVerification(this.args);
#override
State<StatefulWidget> createState() {
return MobileVerificationState(args);
}
}
This is my State class
class MobileVerificationState extends State<MobileVerification> {
int remainingTime = 30;
Timer timer;
bool isResendBtnEnabled = false;
MobileVerificationState(this.args);
#override
void initState() {
super.initState();
startResendTimer();
}
startResendTimer() {
timer = new Timer.periodic(new Duration(seconds: 1), (time) {
setState(() {
remainingTime -= 1;
});
if (remainingTime == 0) {
time.cancel();
setState(() {
isResendBtnEnabled = true;
});
}
});
}
#override
void dispose() {
timer.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return CustomScreenBg(
body: _getOtpVerificationPage());
}
_getOtpVerificationPage() {
return Container(
margin: EdgeInsets.only(top: 24, bottom: 24, left: 12, right: 12),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
getResendWidget(),
CustomButton(
AppString.verify,
isValidateBtnEnabled ? _onValidate : null,
textColor: AppColor.WHITE.color,
bgColor: AppColor.PRIMARY.color,
),
],
),
);
}
Widget getResendWidget() {
Logger.d(remainingTime.toString()); // Here I am getting changed value.
if (isResendBtnEnabled) {
return CustomButton(
AppString.resend,
_onResend,
textColor: AppColor.WHITE.color,
bgColor: AppColor.PRIMARY.color,
);
}
return RichText(
text: TextSpan(
text: 'Resend in ${remainingTime}s', <== But here value is not getting reflected. It stays same as 30
style: TextStyle(color: AppColor.GRAY.color, fontSize: 18),
),
);
}
}
Timer is working perfectly fine, and I am getting updated value as well. But the updated value is not getting reflected inside RichText. Can someone point me out, where i am making the mistake?
Thanks!!
I was making a mistake. I was using StatefulWidget instead of statelessWidget for inheritance. Hope it can help someone. I have created my own custom widget to use. Structure of my widget is follows:
class CustomScreenBg extends StatefulWidget {
final String title;
final Widget body;
CustomScreenBg(this.title, this.body);
#override
State<StatefulWidget> createState() {
return _CustomScreenBgState(title, body);
}
}
class _CustomScreenBgState extends State<CustomScreenBg> {
final String title;
final Widget body;
_CustomScreenBgState(this.title, this.body);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
backgroundColor: AppColor.SNOW_WHITE.color,
body: SingleChildScrollView(child: body),
resizeToAvoidBottomInset: true,
);
}
}
I changed it to following and it is working fine.
class CustomScreenBg extends StatelessWidget {
final String title;
final Widget body;
CustomScreenBg(this.title, this.body);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
backgroundColor: AppColor.SNOW_WHITE.color,
body: SingleChildScrollView(child: body),
resizeToAvoidBottomInset: true,
);
}
}

Flutter: Dissmissible widgets disable Tabview drag detection

I have two tabs, the left tab having a list of tiles and the right tab having nothing. The user can drag the screen from right-to-left or left-to-right to get from one tab to the other.
The left tab has a list of dismissible tiles that only have "direction: DismissDirection.startToEnd" (from left-to-right) enabled so that the user can still theoretically drag (from right-to-left) to go to the right tab.
However, I believe the Dismissible widget still receives the right-to-left drag information which is disabling the TabView drag to change tabs.
In essence, how do I allow the right-to-left drag to be detected by only the TabView and not the Dismissible item?
If an explicit solution/example with code snippets can be given, I would very very much appreciate the help!
Here's a paste for your main.dart file:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/semantics.dart';
void main() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: MainPage(),
);
}
}
class MainPage extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage>
with SingleTickerProviderStateMixin {
TabController _tabController;
#override
void initState() {
_tabController = TabController(vsync: this, length: 2, initialIndex: 1);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
color: Colors.black,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: TabBarView(
controller: _tabController,
children: <Widget>[
TabWithSomething(),
TabWithNothing(),
],
),
),
],
),
),
),
);
}
}
class TabWithNothing extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Container(
child: Text("Swipe from left-to-right!"),
),
);
}
}
class TabWithSomethingItem implements Comparable<TabWithSomethingItem> {
TabWithSomethingItem({this.index, this.name, this.subject, this.body});
TabWithSomethingItem.from(TabWithSomethingItem item)
: index = item.index,
name = item.name,
subject = item.subject,
body = item.body;
final int index;
final String name;
final String subject;
final String body;
#override
int compareTo(TabWithSomethingItem other) => index.compareTo(other.index);
}
class TabWithSomething extends StatefulWidget {
const TabWithSomething({Key key}) : super(key: key);
static const String routeName = '/material/leave-behind';
#override
TabWithSomethingState createState() => TabWithSomethingState();
}
class TabWithSomethingState extends State<TabWithSomething> {
List<TabWithSomethingItem> TabWithSomethingItems;
void initListItems() {
TabWithSomethingItems =
List<TabWithSomethingItem>.generate(10, (int index) {
return TabWithSomethingItem(
index: index,
name: 'Item $index',
subject: 'Swipe from left-to-right to delete',
body: "Swipe from right-to-left to go back to old tab");
});
}
#override
void initState() {
super.initState();
initListItems();
}
void _handleDelete(TabWithSomethingItem item) {
setState(() {
TabWithSomethingItems.remove(item);
});
}
#override
Widget build(BuildContext context) {
Widget body;
body = ListView(
children:
TabWithSomethingItems.map<Widget>((TabWithSomethingItem item) {
return _TabWithSomethingListItem(
item: item,
onDelete: _handleDelete,
dismissDirection: DismissDirection.startToEnd,
);
}).toList());
return body;
}
}
class _TabWithSomethingListItem extends StatelessWidget {
const _TabWithSomethingListItem({
Key key,
#required this.item,
#required this.onDelete,
#required this.dismissDirection,
}) : super(key: key);
final TabWithSomethingItem item;
final DismissDirection dismissDirection;
final void Function(TabWithSomethingItem) onDelete;
void _handleDelete() {
onDelete(item);
}
#override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
return Semantics(
customSemanticsActions: <CustomSemanticsAction, VoidCallback>{
const CustomSemanticsAction(label: 'Delete'): _handleDelete,
},
child: Dismissible(
key: ObjectKey(item),
direction: dismissDirection,
onDismissed: (DismissDirection direction) => _handleDelete(),
background: Container(
color: theme.primaryColor,
child: const ListTile(
leading: Icon(Icons.delete, color: Colors.white, size: 36.0))),
child: Container(
decoration: BoxDecoration(
color: theme.canvasColor,
border: Border(bottom: BorderSide(color: theme.dividerColor))),
child: ListTile(
title: Text(item.name),
subtitle: Text('${item.subject}\n${item.body}'),
isThreeLine: true),
),
),
);
}
}
UPDATE:
I'm thinking we could change the "dismissible.dart" file to change the "TabControlller", but i'm not sure how I might do that.
In the "dismissible.dart" file:
...
void _handleDragUpdate(DragUpdateDetails details) {
if (!_isActive || _moveController.isAnimating)
return;
final double delta = details.primaryDelta;
if (delta < 0) print(delta); // thinking of doing something here
...