I am building a photo editor in Flutter. My home page contains variables such as a list of layers and the currentlySelected layer. My home page has a child widget, Toolbar, which needs access to those variables and must update homePage after changing them. I want to use Provider for this, but I can't figure out how to set that up since I cant extend two classes at once.
import 'package:provider/provider.dart';
class Toolbar extends StatefulWidget {
const Toolbar({super.key});
@override
State<Toolbar> createState() => _ToolbarState();
}
class _ToolbarState extends State<Toolbar> { //EXTENDS ChangeNotifer????
XFile? _image;
final _picker = ImagePicker();
Future<void> _getImageFromGallery() async {
final XFile? pickedFile = await _picker.pickMedia();
if (pickedFile != null) {
_image = XFile(pickedFile.path);
}
}
void _addTextEntity() {
TextEntity newTextEntity = TextEntity(
controller: TextEntityController(),
);
selectedLayer = newTextEntity; //Variable from parent
textLayers.add(newTextEntity); //Variable from Parent
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
PopupMenuButton(
icon: const Icon(Icons.edit), //Leftmost icon on the toolbar
itemBuilder: (BuildContext context) => [
PopupMenuItem(
child: ListTile(
title: const Text("Add Image"),
trailing: const Icon(Icons.image),
onTap: () => {
_getImageFromGallery(),
Navigator.pop(context) //Terminates the project manager
},
)
),
PopupMenuItem(
child: ListTile(
title: const Text("Add Shape"),
trailing: const Icon(Icons.shape_line),
onTap: () => {
/** Add Shape */
Navigator.pop(context),
}
)
),
PopupMenuItem(
child: ListTile(
title: const Text("Add Text"),
trailing: const Icon(Icons.text_fields),
onTap: () => {
_addTextEntity(),
Navigator.pop(context)
}
)
),
],
),
const VerticalDivider(), //To seperate persistent project manager from the rest of the toolbar
Row(
children: [
//Change Font
IconButton(
icon: const Icon(BoxIcons.bx_font),
onPressed: () { /** Launch change font menu */},
),
//Change Font Size
IconButton(
icon: const Icon(BoxIcons.bx_font_size),
onPressed: () { /** Launch change font size slider */},
),
//Justify
IconButton(
icon: const Icon(Icons.format_align_left),
onPressed: () { /** Launch formating menu */},
),
//Change Color
IconButton(
icon: const Icon(BoxIcons.bx_font_color),
onPressed: () { /** Launch color picker */},
),
//Add Stroke
IconButton(
icon: const Icon(LineAwesome.heading_solid),
onPressed: () { /** Launch stroke slider */},
),
//Add Shadow
IconButton(
icon: const Icon(Bootstrap.shadows),
onPressed: () { /** Launch shadow sliders */},
),
]
)
]
);
}
}
You can achieve this by introducing a separate class for Change Notifiers. I will provide sample codes to get an idea.
Here I created a class called AppData to update the value of textToBeDisplayed variable and to keep notify about the value changes.
Then add ChangeNotifiersProvider and AppData to the MyApp class as demonstrated below:
Now, you can access the value of textToBeDisplayed from anywhere in the app using the following code:
Whenever you need to change the value of textToBeDisplayed, you can achieve that with the following code:
Hope this explanation helps. Feel free to ask if anything remains unclear.