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.
- The function is
async
, but not awaited. - The function does not return a
Widget
.
child: Stack(
children: [
// error is probably here
buildPDFViewer(), // this function is async and not awaited