Home > Enterprise >  Error : type 'Future<dynamic>' is not a subtype of type 'Widget'
Error : type 'Future<dynamic>' is not a subtype of type 'Widget'

Time:10-24

I have an issue of ' type 'Future' is not a subtype of type 'Widget' ' and I read a lot of solutions but I couldn't fix and don't understand what I have to do make it work

I'd like a load a pdf from firebase storage with pdf_viewer plugin

here's my code

Main.dart

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(
      MultiProvider(
          providers: [
            ChangeNotifierProvider(
              create: (context) => DrawingProvider(),
            )
          ], child: MyApp()
      )
  );
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final Future<FirebaseApp> _initialization = Firebase.initializeApp();
  @override
  Widget build(BuildContext context) {
    return FutureBuilder<dynamic>(
      future: _initialization,
      builder: (context, snapshot) {
        return MaterialApp(
            debugShowCheckedModeBanner: false,
            theme: ThemeData(primaryColor: Colors.white),
            // Error causing widget 
            home: WorkbookPage());
      },
    );
  }
}

class WorkbookPage extends StatefulWidget {
  const WorkbookPage({Key? key}) : super(key: key);

  @override
  State<WorkbookPage> createState() => _WorkbookPageState();
}

class _WorkbookPageState extends State<WorkbookPage> {

  GlobalKey _viewKey = GlobalKey();
  bool isOverlayVisible = false;
  OverlayEntry? entry;


  @override
  Widget build(BuildContext context) {
    var p = Provider.of<DrawingProvider>(context);
    // slider Overlay 숨기기
    void hideOverlay() {
      entry?.remove();
      entry = null;
      isOverlayVisible = false;
    }

    return GestureDetector(
      child: Scaffold(
          appBar: AppBar(title: Text('Workbook Test')),
          body: GestureDetector(
            onTap: () {
              hideOverlay();
            },
            child: Column(
              children: [
                buildPenFunctionWidget(p, hideOverlay, context),
                Expanded(
                  child: Stack(
                    children: [
                      buildPDFViewer(),
                      GestureDetector(
                        child: Listener(
                          behavior: HitTestBehavior.opaque,
                          onPointerHover: (s) {
                            if (s.buttons == kPrimaryStylusButton) {
                              // print("Hovering stylus and button is pressed!");
                            }
                          },
                          onPointerDown: (s) {
                            // Stylus가 화면에 닿을 때
                            if (s.kind == PointerDeviceKind.stylus) {
                              p.penMode
                                  ? p.penDrawStart(s.localPosition)
                                  : null;
                              p.highlighterMode
                                  ? p.highlighterDrawStart(s.localPosition)
                                  : null;
                              p.eraseMode ? p.erase(s.localPosition) : null;
                              // Stylus 버튼이 눌린 상태에서 스크린에 닿을 때
                            } else if (s.buttons == kPrimaryStylusButton) {
                              p.changeEraseModeButtonClicked = true;
                            }
                          },
                          onPointerMove: (s) {
                            if (s.kind == PointerDeviceKind.stylus) {
                              p.penMode ? p.penDrawing(s.localPosition) : null;
                              p.highlighterMode
                                  ? p.highlighterDrawing(s.localPosition)
                                  : null;
                              p.eraseMode ? p.erase(s.localPosition) : null;
                            } else if (s.buttons == kPrimaryStylusButton) {
                              p.changeEraseModeButtonClicked = true;
                            }
                          },
                        ),
                      ),
                      Positioned.fill(
                        child: CustomPaint(
                          painter: DrawingPainter(p.lines),

                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          )),
    );
  }

  /// Pen, eraser , highlighter
  Container buildPenFunctionWidget(DrawingProvider p, void hideOverlay(),
      BuildContext context) {
    return Container(
      width: double.infinity,
      height: 50,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          penWidget(p: p),
          highlighterWidget(p: p),
          erasePenWidget(p: p),

          /// Overlay Slider (Pen Size 조절)
          Container(
            key: _viewKey,
            width: 60,
            child: FittedBox(
              fit: BoxFit.fitWidth,
              child: GestureDetector(
                behavior: HitTestBehavior.deferToChild,
                child: const Icon(
                  Icons.horizontal_rule_rounded,
                  color: Colors.black54,
                ),
                onTap: () {
                  if (isOverlayVisible) {
                    hideOverlay();
                  }
                  isOverlayVisible = true;
                  OverlayState? overlayState = Overlay.of(context);
                  final renderBox = _viewKey.currentContext
                      ?.findRenderObject() as RenderBox;
                  final offset =
                  renderBox.localToGlobal(Offset.zero);

                  /// Build Overlay Widget
                  entry = OverlayEntry(
                    builder: (context) {
                      return StatefulBuilder(
                        builder: (context, setStateSB) {
                          return Positioned(
                            top: offset.dy   60,
                            left: offset.dx - 80,
                            child: buildOverlaySliderWidget(
                                p, setStateSB),
                          );
                        },
                      );
                    },
                  );
                  overlayState?.insert(entry!);
                },
              ),
            ),
          ),
          // SliderOverlayWidget(),
          colorWidget(context: context, color: Colors.black),
          colorWidget(context: context, color: Colors.red),
          colorWidget(context: context, color: Colors.yellow),
          colorWidget(context: context, color: Colors.green),
          colorWidget(context: context, color: Colors.blue),
        ],
      ),
    );
  }

  ///Overlay Entry with Slider widget
  Material buildOverlaySliderWidget(DrawingProvider p, StateSetter setStateSB) {
    return Material(
      elevation: 2.5,
      child: Container(
        width: 250,
        child: FittedBox(
          fit: BoxFit.fill,
          child: Row(
            children: [
              IconButton(
                onPressed: () {
                  double penSize = p.penSize;
                  if (penSize < 2) {
                    penSize = 2;
                  }
                  p.changePenSize = --penSize;
                  setStateSB(() {
                    print("버튼 클릭 후 penSize = ${penSize}");
                  });
                },
                icon: FaIcon(FontAwesomeIcons.minus),
              ),
              Text("${p.penSize.toStringAsFixed(0)}"),
              Slider(
                inactiveColor: Colors.black26,
                activeColor: Colors.black,
                value: p.penSize,
                onChanged: (size) {
                  setStateSB(() {
                    p.changePenSize = size;
                  });
                },
                min: 1,
                max: 15,
              ),
              IconButton(
                onPressed: () {
                  double penSize = p.penSize;
                  if (penSize > 14) {
                    penSize = 14;
                  }
                  p.changePenSize =   penSize;
                  setStateSB(() {
                    print("버튼 클릭 후 penSize = ${penSize}");
                  });
                },
                icon: Icon(Icons.add),
              )
            ],
          ),
        ),
      ),
    );
  }

  /// PDF Open Method
  openPDF(BuildContext context, File file) {
    return Builder(builder: (context) => PdfViewer(file: file));
  }

  buildPDFViewer() async {
    final url = '수특/2023_수능특강_수1.pdf';
    final file = await PDFApi.loadFirebase(url);

    if (file == null) return;
    openPDF(context, file);
  }
}



/// Painter Class
class DrawingPainter extends CustomPainter {
  DrawingPainter(this.lines);

  final List<List<DotInfo>> lines;

  @override
  void paint(Canvas canvas, Size size) {
    for (var oneLine in lines) {
      Color? color;

      double? size;
      var path = Path();
      var l = <Offset>[];
      for (var oneDot in oneLine) {
        color ??= oneDot.color;
        size ??= oneDot.size;
        l.add(oneDot.offset);
      }
      path.addPolygon(l, false);

      canvas.drawPath(
          path,
          Paint()
            ..color = color!
            ..strokeWidth = size!
            ..strokeCap = StrokeCap.round
            ..style = PaintingStyle.stroke
            ..isAntiAlias = true
            ..strokeJoin = StrokeJoin.round);
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

Im pretty sure there's some error in MyApp build method

I tried to wrap the materialApp with Futurebilder and WorkbookPage with Futurebuilder but it shows the same error

pdf_viewer.dart

class PdfViewer extends StatefulWidget {
  final File file;
  const PdfViewer({Key? key, required this.file}) : super(key: key);

  @override
  State<PdfViewer> createState() => _PdfViewerState();
}

class _PdfViewerState extends State<PdfViewer> {
  late PDFViewController controller;
  int pages = 0;
  int indexPage = 0;
  @override
  Widget build(BuildContext context) {
    final name = basename(widget.file.path);
    final text = '${indexPage   1} of $pages';
    return Scaffold(
      body: PDFView(
        filePath: widget.file.path,
        swipeHorizontal: true,
        onRender: (pages) {
          setState(() {
            this.pages = pages!;
          });
        },
        onViewCreated: (controller) {
          setState(() {
            this.controller = controller;
          });
        },
      ),
    );
  }
}

Error code

The following _TypeError was thrown building WorkbookPage(dirty, dependencies: [_InheritedProviderScope<DrawingProvider?>], state: _WorkbookPageState#a99ca):
type 'Future<dynamic>' is not a subtype of type 'Widget'

The relevant error-causing widget was: 
  WorkbookPage WorkbookPage:file:///C:/Users/park/AndroidStudioProjects/stylus_test2/lib/main.dart:54:19

CodePudding user response:

Change this :

buildPDFViewer() async {
    final url = '수특/2023_수능특강_수1.pdf';
    final file = await PDFApi.loadFirebase(url);

    if (file == null) return;
    openPDF(context, file);
  }

to this:

buildPDFViewer() async {
    return Builder(builder: (context) {
       final url = '수특/2023_수능특강_수1.pdf';
       final file = await PDFApi.loadFirebase(url);

       if (file == null) return SizedBox();
       return PdfViewer(file: file)
    });
    
  }

CodePudding user response:

I suspect the error is here.

  1. The function is async, but not awaited.
  2. The function does not return a Widget.
child: Stack(
  children: [
    // error is probably here
    buildPDFViewer(), // this function is async and not awaited
  • Related