You can try this in Dartpad. Note that I converted your Parent to a simple class that only has a method you want child widgets to access.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Provider<ModelFromParent>(
create: (_) => ModelFromParent(),
child: const Parent()
)
),
),
);
}
}
class ModelFromParent {
onPressed() {
print("onPressed");
}
}
class Parent extends StatelessWidget {
const Parent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Child();
}
}
class Child extends StatelessWidget {
const Child({
Key? key
}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Grandchild();
}
}
class Grandchild extends StatelessWidget {
const Grandchild({
Key? key
}) : super(key: key);
@override
Widget build(BuildContext context) {
return FloatingActionButton(
backgroundColor: Colors.black,
mini: true,
tooltip: 'Change Camera',
onPressed: Provider.of<ModelFromParent>(context, listen:false).onPressed,
child: const Icon(
Icons.cached,
color: Colors.white,
)
);
}
}
Here's another take - in case you wish to use the Parent Widget - as you mentioned in the comments.
You have two options: make parent an InheretedWidget. But note - in this case Parent has no build method, and is used only as a proxy to build a child. This may or may not work for you.
Second option is to call a static method of the parent - but in this case you don't have an access to Parent state and variables initialized in constructor. Again - this may or may not work for you.
I think if none of the options are applicable - you might be trying to achieve an anti-pattern. Typical approach would be my first suggestion - create a model class from you parent, and pass it using Provider or a similar package.
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: const Scaffold(
body: Center(
child: Parent(child: Child())
)
),
);
}
}
class Parent extends InheritedWidget {
const Parent({super.key, required super.child});
static Parent of(BuildContext context) {
final Parent? result = context.dependOnInheritedWidgetOfExactType<Parent>();
assert(result != null, 'No Parent found in context');
return result!;
}
@override
bool updateShouldNotify(Parent old) => false;
onPressed() {
print("onPressed");
}
static void staticOnPressed() {
print("staticOnPressed");
}
}
class Child extends StatelessWidget {
const Child({
Key? key
}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Grandchild();
}
}
class Grandchild extends StatelessWidget {
const Grandchild({
Key? key
}) : super(key: key);
@override
Widget build(BuildContext context) {
return FloatingActionButton(
backgroundColor: Colors.black,
mini: true,
tooltip: 'Change Camera',
onPressed: () {
Parent.of(context).onPressed();
Parent.staticOnPressed();
},
child: const Icon(
Icons.cached,
color: Colors.white,
)
);
}
}