admin管理员组文章数量:1122832
I have a simple app that consists of checkboxes and a progress indicator. The checkbox widget is stateful as is the progress indicator.
Is there a way to allow my progress indicator to update based on a button click without resorting to something like Riverpod?
I have a number of features (2 in this reduced sample) in a magazine that are check boxes. I have a progress indicator that moves based on the number of checkboxes.
I have tried changing the key on the progress indicator.
Here is the code attempting to do it with globals. I would prefer not to use globals either.
This code is from a Flutter example and they solved the problem with Riverpod. Smart-alack that I am, I thought for sure there had to be an easier way using just Flutter/Dart standard stuff.
import 'package:flutter/material.dart';
int numberOfClicks = 0;
List<Widget> tasks = [
const TaskItem(label: 'Embedded in Thin Slices'),
const TasbkItem(label: 'Technology Features'),
const TaskItem(label: 'Datasheets'),
];
double percentage = 0.0;
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Circuit Cellar!',
theme: ThemeData(primarySwatch: Colors.blue),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Circuit Cellar Reading Planner!'),
),
body: const Column(
children: [
// Progress(percent: percentage),
Progress(),
TaskList(),
],
),
);
}
}
class Progress extends StatefulWidget {
const Progress({super.key});
@override
State<Progress> createState() => _ProgressState();
}
class _ProgressState extends State<Progress> {
@override
Widget build(BuildContext context) {
return Column(
children: [
const Text('Reading Progress:'),
LinearProgressIndicator(value: percentage),
],
);
}
}
class TaskList extends StatelessWidget {
const TaskList({super.key});
@override
Widget build(BuildContext context) {
return Column(children: tasks);
}
}
class TaskItem extends StatefulWidget {
final String label;
const TaskItem({super.key, required this.label});
@override
TaskItemState createState() => TaskItemState();
}
class TaskItemState extends State<TaskItem> {
bool? _value = false;
@override
Widget build(BuildContext context) {
return Row(
children: [
Checkbox(
onChanged: (newValue) {
setState(() {
_value = newValue;
// ! checks for null
if (_value!) {
numberOfClicks++;
} else {
numberOfClicks--;
}
percentage = numberOfClicks / tasks.length;
});
},
value: _value,
),
Text(widget.label),
],
);
}
}
I have a simple app that consists of checkboxes and a progress indicator. The checkbox widget is stateful as is the progress indicator.
Is there a way to allow my progress indicator to update based on a button click without resorting to something like Riverpod?
I have a number of features (2 in this reduced sample) in a magazine that are check boxes. I have a progress indicator that moves based on the number of checkboxes.
I have tried changing the key on the progress indicator.
Here is the code attempting to do it with globals. I would prefer not to use globals either.
This code is from a Flutter example and they solved the problem with Riverpod. Smart-alack that I am, I thought for sure there had to be an easier way using just Flutter/Dart standard stuff.
import 'package:flutter/material.dart';
int numberOfClicks = 0;
List<Widget> tasks = [
const TaskItem(label: 'Embedded in Thin Slices'),
const TasbkItem(label: 'Technology Features'),
const TaskItem(label: 'Datasheets'),
];
double percentage = 0.0;
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Circuit Cellar!',
theme: ThemeData(primarySwatch: Colors.blue),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Circuit Cellar Reading Planner!'),
),
body: const Column(
children: [
// Progress(percent: percentage),
Progress(),
TaskList(),
],
),
);
}
}
class Progress extends StatefulWidget {
const Progress({super.key});
@override
State<Progress> createState() => _ProgressState();
}
class _ProgressState extends State<Progress> {
@override
Widget build(BuildContext context) {
return Column(
children: [
const Text('Reading Progress:'),
LinearProgressIndicator(value: percentage),
],
);
}
}
class TaskList extends StatelessWidget {
const TaskList({super.key});
@override
Widget build(BuildContext context) {
return Column(children: tasks);
}
}
class TaskItem extends StatefulWidget {
final String label;
const TaskItem({super.key, required this.label});
@override
TaskItemState createState() => TaskItemState();
}
class TaskItemState extends State<TaskItem> {
bool? _value = false;
@override
Widget build(BuildContext context) {
return Row(
children: [
Checkbox(
onChanged: (newValue) {
setState(() {
_value = newValue;
// ! checks for null
if (_value!) {
numberOfClicks++;
} else {
numberOfClicks--;
}
percentage = numberOfClicks / tasks.length;
});
},
value: _value,
),
Text(widget.label),
],
);
}
}
Share
Improve this question
asked Nov 23, 2024 at 6:21
rjapengarjapenga
10712 bronze badges
1
- ValueNotifier, callback, possible duplicate of How to pass data from a child Stateful widget to Parent Widget in Flutter – Md. Yeasin Sheikh Commented Nov 23, 2024 at 7:40
1 Answer
Reset to default 2To solve your problem without Riverpod or global variables, you can use InheritedWidget, which is built into Flutter. It helps share state between widgets cleanly.
Get rid of globals, No numberOfClicks or percentage. Add InheritedWidget, It’ll track completed tasks and let both Progress and TaskItem widgets update state dynamically. Keep everything local, The Progress bar updates automatically when a checkbox is toggled.
Here’s the updated code:
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: 'Circuit Cellar!',
theme: ThemeData(primarySwatch: Colors.blue),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int completedTasks = 0;
void updateProgress(bool isChecked) {
setState(() {
completedTasks += isChecked ? 1 : -1;
});
}
@override
Widget build(BuildContext context) {
return TaskInherited(
completedTasks: completedTasks,
totalTasks: 3,
updateProgress: updateProgress,
child: Scaffold(
appBar: AppBar(
title: const Text('Circuit Cellar Reading Planner!'),
),
body: const Column(
children: [
Progress(),
TaskList(),
],
),
),
);
}
}
class TaskInherited extends InheritedWidget {
final int completedTasks;
final int totalTasks;
final void Function(bool) updateProgress;
const TaskInherited({
super.key,
required this.completedTasks,
required this.totalTasks,
required this.updateProgress,
required Widget child,
}) : super(child: child);
static TaskInherited of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<TaskInherited>()!;
}
@override
bool updateShouldNotify(TaskInherited oldWidget) {
return completedTasks != oldWidget.completedTasks;
}
}
class Progress extends StatelessWidget {
const Progress({super.key});
@override
Widget build(BuildContext context) {
final inheritedData = TaskInherited.of(context);
double progress = inheritedData.completedTasks / inheritedData.totalTasks;
return Column(
children: [
const Text('Reading Progress:'),
LinearProgressIndicator(value: progress),
Text('${(progress * 100).toStringAsFixed(0)}% completed'),
],
);
}
}
class TaskList extends StatelessWidget {
const TaskList({super.key});
@override
Widget build(BuildContext context) {
final tasks = [
const TaskItem(label: 'Embedded in Thin Slices'),
const TaskItem(label: 'Technology Features'),
const TaskItem(label: 'Datasheets'),
];
return Column(children: tasks);
}
}
class TaskItem extends StatefulWidget {
final String label;
const TaskItem({super.key, required this.label});
@override
TaskItemState createState() => TaskItemState();
}
class TaskItemState extends State<TaskItem> {
bool _isChecked = false;
@override
Widget build(BuildContext context) {
final inheritedData = TaskInherited.of(context);
return Row(
children: [
Checkbox(
onChanged: (newValue) {
setState(() {
_isChecked = newValue!;
inheritedData.updateProgress(_isChecked);
});
},
value: _isChecked,
),
Text(widget.label),
],
);
}
}
本文标签: flutterHow do you update one Stateful Widget from another stateful widgetStack Overflow
版权声明:本文标题:flutter - How do you update one Stateful Widget from another stateful widget? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736299475a1930466.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论