i have retrieving json data locally and negative to single screen in flutter
Make an asset folder in your project root directory and put my JSON file into that.
Entry the JSON file into pubspec.yaml file
Made a method to read the JSON file into your flutter application
List Screen
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' as rootBundle;
import 'package:license_app/data/data.dart';
import 'package:license_app/model/pqtnj_model.dart';
import 'package:license_app/page/detail.dart';
class MyList extends StatelessWidget {
MyList({Key? key}) : super(key: key);
//final list = Pquestion.generate();
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: ReadJsonData(),
builder: (context, data) {
if (data.hasData) {
var items = data.data as List<PjQuestion>;
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
contentPadding: const EdgeInsets.all(15.0),
leading: CircleAvatar(
backgroundColor: Colors.blue.shade400,
child: Text(
items[index].id.toString(),
style: const TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w500,
),
),
),
title: Text(
items[index].question.toString(),
style: const TextStyle(
color: Colors.black,
fontSize: 18,
fontWeight: FontWeight.w500,
),
),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return DetailScreen(snapshot.lists[index]);
}));
},
),
elevation: 5,
margin: const EdgeInsets.all(10),
shadowColor: Colors.black12,
shape: OutlineInputBorder(
borderRadius: BorderRadius.circular(20),
borderSide: const BorderSide(color: Colors.white)),
);
});
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
));
}
Future<List<PjQuestion>> ReadJsonData() async {
final jsondata =
await rootBundle.rootBundle.loadString('assets/json/pquestion.json');
final list = json.decode(jsondata) as List<dynamic>;
return list.map((e) => PjQuestion.fromJson(e)).toList();
}
}
on Tab is not navigating
the error i am getting now
"Undefined name 'snapshot'.
Try correcting the name to one that is defined, or defining the name."
Detail Screen
import 'package:flutter/material.dart';
import 'package:license_app/data/data.dart';
class DetailScreen extends StatelessWidget {
final Pquestion pquestion;
const DetailScreen(this.pquestion, {Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(pquestion.question),
),
body: SingleChildScrollView(
padding: const EdgeInsets.all(20.0),
child: Row(
children: <Widget>[
Expanded(
child: Text(
pquestion.answer,
style: const TextStyle(fontSize: 20.0, color: Colors.black),
overflow: TextOverflow.visible,
),
)
],
)),
);
}
}
when you tap in the first screen to load the detail screen it actually sends a data with it self which you literally changed its name to data instead of snapshot, and you initialized data to items so,
try this:
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return DetailScreen(items[index]);
}));
},
Related
I made a simple store app where I put data in a json file. I've managed to call the data into the Tabbar & TabbarView by FutureBuilder. Also I put the list of these products in a drawer. I want if I click on one of the product names from Drawer, it will navigate to specific TabBar respective IDs.
I've done this trick before, but only on static pages, not FutureBuilder like this. I really appreciate any help
HomePage.dart
import 'dart:convert';
import 'package:contoh_tabbar_json/model.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class HomePage extends StatefulWidget {
const HomePage({Key key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
Future<List<Product>> _getProduct() async {
final dataString = await rootBundle.loadString('assets/myproduct.json');
final List<dynamic> json = jsonDecode(dataString);
final products = <Product>[];
for (var v in json) {
products.add(Product.fromJson(v));
}
return products;
}
#override
void initState() {
_getProduct();
super.initState();
}
#override
void dispose() {
super.dispose();
}
Product product;
#override
Widget build(BuildContext context) {
return FutureBuilder<List<Product>>(
future: _getProduct(),
builder: (context, mydata) {
if (mydata.hasData) {
List<Tab> tabs = <Tab>[];
for (int index = 0; index < mydata.data.length; index++) {
tabs.add(Tab(
child: Text(
mydata.data[index].title,
),
));
}
return DefaultTabController(
length: mydata.data.length,
child: Scaffold(
endDrawer: Drawer(
child: SingleChildScrollView(
physics: const ScrollPhysics(),
child: Column(
children: [
Center(
child: Container(
height: 100,
alignment: Alignment.center,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(50),
),
),
child: const Text("Product List",
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w700,
),
textAlign: TextAlign.center),
),
),
),
//
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: mydata.data.length,
itemBuilder: (BuildContext context, index) {
return ListTile(
dense: true,
title: Text(mydata.data[index].title, style: const TextStyle(fontSize: 15, fontWeight: FontWeight.w500)),
onTap: () {
Navigator.pop(context);
},
);
}),
const SizedBox(height: 70),
],
),
),
),
appBar: AppBar(
title: const Text("My Store"),
bottom: TabBar(
isScrollable: true,
tabs: tabs,
),
),
body: FutureBuilder<List<Product>>(
future: _getProduct(),
builder: (context, mydata) {
if (mydata.hasData) {
List<Widget> tabs = <Widget>[];
for (int index = 0; index < mydata.data.length; index++) {
tabs.add(Tab(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(height: 30),
Text(
mydata.data[index].title,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 30),
Text(mydata.data[index].title),
const SizedBox(height: 30),
Text(mydata.data[index].description),
const SizedBox(height: 30),
Text(mydata.data[index].category),
],
),
),
),
));
}
return TabBarView(
children: tabs,
);
}
return Container();
},
),
),
);
}
return Scaffold(
body: Center(child: Text(mydata.hasError ? mydata.error.toString() : "Loading...")),
);
},
);
}
}
Model
import 'dart:convert';
List<Product> productFromJson(String str) =>
List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));
class Product {
Product({
this.id,
this.title,
this.description,
this.category,
});
final int id;
final String title;
final String description;
final String category;
factory Product.fromJson(Map<String, dynamic> json) => Product(
id: json["id"],
title: json["title"],
description: json["description"],
category: json["category"],
);
String getTitle() {
return title;
}
String getDescription() {
return description;
}
String getCategory() {
return category;
}
}
Mungkin bisa dicek pada github saya :
https://github.com/kuldii/navigate_drawer_tabbar
The data from mysql server isn't automatically reflected in my app when I fill a form to enter the data from my app and comeback to the page... But if I login again or do a hot reload the data is reflected and I'm not sure where to add a setState({}) and what to write inside of it so please tell me how to update my list automatically.........
import 'dart:convert';
import 'package:finance_returns/Screens/Admin/AdminLogin.dart';
import 'package:finance_returns/Screens/Admin/CreateUser.dart';
import 'package:finance_returns/constants.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:http/http.dart' as http;
class AdminDashboard extends StatefulWidget {
#override
_AdminDashboardState createState() => _AdminDashboardState();
}
class _AdminDashboardState extends State<AdminDashboard> {
Future getData() async {
var url = Uri.parse('http://$ip/EmployeesDB/admin/read.php');
var response = await http.get(url);
return json.decode(response.body);
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Dashboard'),
actions: <Widget>[
IconButton(
icon: Icon(FontAwesomeIcons.signOutAlt),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AdminLogin(),
),
);
})
],
),
floatingActionButton: Container(
margin: EdgeInsets.only(bottom: 10),
child: FloatingActionButton.extended(
backgroundColor: kPrimaryColor,
onPressed: () {
Navigator.push( context, MaterialPageRoute( builder: (context) => Register()), ).then((list) => setState);
},
icon: Icon(
Icons.add,
),
label: Text("User"))),
body: FutureBuilder(
future: getData(),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
List list = snapshot.data;
return ListTile(
//leading: GestureDetector(
//child: Icon(Icons.mode_edit_outline),
onTap: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => Register(
list: list,
index: index,
),
),
);
debugPrint('Edit Clicked');
},
//),
title: Text(list[index]['username']),
subtitle: Text(list[index]['level']),
trailing: GestureDetector(
child: Icon(Icons.delete),
onTap: () {
setState(() {
var url =
Uri.parse('http://$ip/EmployeesDB/admin/delete.php');
http.post(url, body: {
'id': list[index]['id'],
});
});
debugPrint('delete Clicked');
},
),
);
})
: CircularProgressIndicator();
},
)
);
}
}
This is the registration page:
import 'dart:convert';
import 'package:finance_returns/Screens/Admin/AdminDashboard.dart';
import 'package:finance_returns/components/text_field_container.dart';
import 'package:finance_returns/constants.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:http/http.dart' as http;
class Register extends StatefulWidget {
final List list;
final int index;
Register({this.list, this.index});
#override
_RegisterState createState() => _RegisterState();
}
class _RegisterState extends State<Register> {
TextEditingController name = TextEditingController();
TextEditingController user = TextEditingController();
TextEditingController pass = TextEditingController();
TextEditingController level = TextEditingController();
bool editMode = false;
Future addUpdateData() async {
if (editMode) {
var url = Uri.parse("http://$ip/EmployeesDB/admin/edit.php");
http.post(url, body: {
'id': widget.list[widget.index]['id'],
"name": name.text,
"username": user.text,
"password": pass.text,
"level": level.text,
});
} else {
var url = Uri.parse("http://$ip/EmployeesDB/admin/user_register.php");
var response = await http.post(url, body: {
"name": name.text,
"username": user.text,
"password": pass.text,
"level": level.text,
});
var data = json.decode(response.body);
if (data == "Error") {
Fluttertoast.showToast(
msg: "This user already exists!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.red,
textColor: Colors.white,
fontSize: 16.0);
} else {
Fluttertoast.showToast(
msg: "Successfully registered",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.green,
textColor: Colors.white,
fontSize: 16.0);
// Navigator.pop(
// context,
// MaterialPageRoute(
// builder: (context) => AdminDashboard(),
// ),
// );
}
}
}
#override
void initState() {
super.initState();
if (widget.index != null) {
editMode = true;
name.text = widget.list[widget.index]['name'];
user.text = widget.list[widget.index]['username'];
pass.text = widget.list[widget.index]['password'];
level.text = widget.list[widget.index]['level'];
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Create/Update Users',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
body: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFieldContainer(
child: TextField(
decoration: InputDecoration(
labelText: 'Name',
icon: Icon(
Icons.person,
color: kPrimaryColor,
),
border: InputBorder.none,
),
controller: name,
),
),
TextFieldContainer(
child: TextField(
decoration: InputDecoration(
labelText: 'Email id',
icon: Icon(
Icons.person,
color: kPrimaryColor,
),
border: InputBorder.none,
),
controller: user,
),
),
TextFieldContainer(
child: TextField(
obscureText: true,
decoration: InputDecoration(
labelText: 'Password',
icon: Icon(
Icons.lock,
color: kPrimaryColor,
),
border: InputBorder.none,
),
controller: pass,
),
),
TextFieldContainer(
child: TextField(
decoration: InputDecoration(
labelText: 'level (eg:member,admin,HR)',
icon: Icon(
Icons.person,
color: kPrimaryColor,
),
border: InputBorder.none,
),
controller: level,
),
),
MaterialButton(
color: kPrimaryColor,
child: Text(editMode ? 'Update' : 'Create',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white)),
onPressed: () {
setState(() {
addUpdateData();
});
Navigator.pop(
context,
MaterialPageRoute(
builder: (context) => AdminDashboard(),
),
);
debugPrint('Clicked Button Button');
},
),
],
),
),
),
);
}
}
I think you are doing the navigation before getting data and that setState is updating the state of the current page, not the previous one. Try this:
onPressed: () async {
await addUpdateData();
}
and in the first page:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Register(
list: list,
index: index,
),
),
).then((_) => setState(() {});
I have worked a little on a flutter json tutorial, where I am able to fetch and parse json data, I am now trying to put the code into a SliverList. But when I debug my app it throws the follwing error on Builder on line 96: The getter 'length' was called on null. Receiver: null Tried calling: length
I am not sure what to do or what to change. Please note that my app consists of 1 Page with tabbar view.
Here is my full code:
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:innbo_app/product_model.dart';
Future<List> fetchData(http.Client client) async {
final response = await client
.get('http://my-json-server.typicode.com/tariksalihovic/innbo/receipt');
// Use the compute function to run parsePhotos in a separate isolate.
return compute(parseData, response.body);
}
// A function that converts a response body into a List<Photo>.
List parseData(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map((json) => Receipt.fromJson(json)).toList();
}
class PlaceholderWidget1 extends StatelessWidget {
final Color color;
PlaceholderWidget1(this.color);
#override
Widget build(BuildContext context) {
return Container(
color: color,
);
}
}
class Indbo1 extends StatelessWidget {
final List data;
Indbo1({Key key, this.data}) : super(key: key);
final List<String> listItems = [];
final List<String> _tabs = <String>[
"Alle",
"Anmeldt",
];
#override
Widget build(BuildContext context) {
return Material(
child: Scaffold(
body: Container(
color: Colors.grey[100],
child: DefaultTabController(
length: _tabs.length, // This is the number of tabs.
child: NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
// These are the slivers that show up in the "outer" scroll view.
return <Widget>[
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
context),
sliver: SliverSafeArea(
top: false,
sliver: SliverAppBar(
centerTitle: true,
title: const Text(
"Indbo",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 16,
),
),
floating: true,
pinned: true,
snap: true,
stretch: false,
bottom: TabBar(
// These are the widgets to put in each tab in the tab bar.
tabs: _tabs
.map((String name) => Tab(text: name))
.toList(),
),
),
),
),
];
},
body: TabBarView(
// These are the contents of the tab views, below the tabs.
children: _tabs.map((String name) {
return SafeArea(
top: false,
bottom: false,
child: Builder(
builder: (BuildContext context) {
return CustomScrollView(
key: PageStorageKey<String>(name),
slivers: <Widget>[
SliverOverlapInjector(
// This is the flip side of the SliverOverlapAbsorber above.
handle: NestedScrollView
.sliverOverlapAbsorberHandleFor(context),
),
SliverPadding(
padding: EdgeInsets.fromLTRB(15, 0, 15, 10),
sliver: SliverList(
delegate: SliverChildListDelegate([
SizedBox(height: 30),
Text(
'Genstande',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700),
),
]),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
Container(
child: FutureBuilder<List>(
future: fetchData(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError)
print(snapshot.error);
return snapshot.hasData
? Indbo1(data: snapshot.data)
: Center(
child:
CircularProgressIndicator());
},
),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1.0,
color: Colors.grey[200]),
),
color: Colors.white,
),
margin:
EdgeInsets.only(left: 15, right: 15),
),
Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1.0,
color: Colors.grey[200]),
),
color: Colors.white,
),
margin:
EdgeInsets.only(left: 15, right: 15),
child: ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return ListTile(
/*onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
Detail(choice: choices[index])),
);
},*/
leading: CircleAvatar(
radius: 26,
backgroundColor: Colors.grey[400],
child: Icon(Icons.phone_iphone,
color: Colors.white),
),
title: Text(
'${data[index].receiptlines[index].name ?? "Empty"}',
style: TextStyle(
color: Colors.black,
fontSize: 16.5,
fontWeight: FontWeight.w700),
),
subtitle: Text(
'${data[index].orderNumber ?? "Empty"}',
style: TextStyle(
color: Colors.grey[700],
fontSize: 12.0),
),
trailing: Text(
'${data[index].price.amount ?? "Empty"}',
style: TextStyle(
color: Colors.black,
fontSize: 16.5,
fontWeight: FontWeight.w800),
),
);
},
),
),
],
),
),
],
);
},
),
);
}).toList(),
),
),
),
),
),
);
}
}
Here is the product_model.dart which is linked to above code:
class Lines {
final String name;
final String productNumber;
Lines({this.name, this.productNumber});
factory Lines.fromJson(Map<String, dynamic> json) {
return Lines(name: json['name'], productNumber: json['productNumber']);
}
}
class Prices {
final int amount;
Prices({this.amount});
factory Prices.fromJson(Map<String, dynamic> json) {
return Prices(
amount: json['amount'],
);
}
}
class Receipt {
final int id;
final String type;
final String receiptId;
final String orderNumber;
final Prices price;
final List<Lines> receiptlines;
Receipt(
{this.id,
this.type,
this.receiptId,
this.orderNumber,
this.price,
this.receiptlines});
factory Receipt.fromJson(Map<String, dynamic> json) {
var list = json['receiptLines'] as List;
List<Lines> receiptLines =
List<Lines>.from(list.map((i) => Lines.fromJson(i))).toList();
return Receipt(
id: json['id'],
type: json['type'],
receiptId: json['receiptId'],
orderNumber: json['orderNumber'],
price: Prices.fromJson(json['price']),
receiptlines: receiptLines
);
}
}
I use the following code to generate 10 predefined cards on a flutter screen which doesn't change:
List cards = new List.generate(10, (i)=>new QuestionCard()).toList();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('My First App'),
backgroundColor:new Color(0xFF673AB7),
),
body: new Container(
child: new ListView(
children: cards,
)
)
);
}
}
class QuestionCard extends StatefulWidget {
#override
_QuestionCardState createState() => _QuestionCardState();
}
class _QuestionCardState extends State<QuestionCard> {
#override
Widget build(BuildContext context) {
return Container(
child: Card(
borderOnForeground: true,
color: Colors.green,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
trailing: Icon(Icons.album),
title: Text('Q1'),
subtitle: Text('What is the name of this location?'),
),
new TextFormField(
decoration: new InputDecoration(
labelText: "Answer Question",
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(
),
),
//fillColor: Colors.green
),
validator: (val) {
if(val.length==0) {
return "Type your answer here";
}else{
return null;
}
},
keyboardType: TextInputType.text,
style: new TextStyle(
fontFamily: "Poppins",
),
),
ButtonBar(
children: <Widget>[
FlatButton(
child: const Text('Save'),
onPressed: () {/* ... */},
),
],
),
],
),
),
);
}
}
My json is simple (questions.json):
{
"Questions":
[
{
"id" : 1,
"quest" : ["question one"]
},
{
"id" : 2,
"quest" : ["question two", "question three"]
},
{
"id" : 3,
"quest" : ["question four"]
},
{
"id" : 4,
"quest" : ["question five", "question six", "question seven"]
}
]
}
So I have 2 questions I need to solve:
1. If I have more than 1 question I'll need to add an additional text box for a response for which I'll use a different card type, 2, 3, 4 max, which I'll need to define once.
But my real question here:
How do I generate the list based on the json response:
Future _loadQuestionAssets() async
{
return await rootBundle.loadString('assets/questions.json');
}
Future loadQuestion() async{
String jsonString = await _loadQuestionAssets();
final jsonResponse = json.decode(jsonString);
Questions question = new Questions.fromJson(jsonResponse);
//List cards = new List.generate(length, generator)
}
try this:
class MyFirstApp extends StatefulWidget{
#override
createState()=> new _appState();
}
class _appState extends State<MyFirstApp>{
List _displayData;
//assuming that you saved your json file in your assets folder
loadJson() async {
String data = await rootBundle.loadString('assets/json/questions.json');
jsonResult = json.decode(data);
print(jsonResult);
setState((){
_displayData = jsonResult["Questions"];
});
}
#override
void initState(){
super.initState();
loadJson();
}
#override
Widget build(BuildContext context){
return Scaffold(
appbar: Appbar(
title: Text("My APP")
),
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: _displayData == null ? Center(child: CircularProgressIndicator()) :
ListView.builder(
itemcount: _displayData.length,
itembuilder: (context, index){
return Container(
width: MediaQuery.of(context).size.width,
height: 80,
margin: EdgeInsets.only(bottom: 5),
child: Text(_displayData[index]["id"])
);
}
)
)
);
}
}
I have a view as attach files
body: TabBarView(
controller: _tabController,
children: [
TabSreen(index: _tabController.index, eventId: widget.eventEntity.eventId),
TabScreen(index: _tabController.index, eventId: widget.eventEntity.eventId)
]
),
TabScreen is StatefulWiget,
Click on each item in List of TabScreen, open to SecondScreen
How to make the second screen show as fullscreen. I mean the SecondView should remove the part: Event1, Event Name, Status. Just showing the view with below navigation as Fullscreen
Currently, I am using following code to open the SecondScreen (StatefulWiget) from TabScreen
Navigator.push(
context,
MaterialPageRoute(builder: (context) => new SecondScreen(title: _forms[index].name)),
);
Here is a simple example since you didn't share enough code, you can compare your code with this.
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
theme: ThemeData(
brightness: Brightness.dark,
primaryColor: Color(0xFF048ec8),
indicatorColor: Colors.red,
cursorColor: Colors.red,
),
home: MainScreenWithTab(),
);
}
}
class MainScreenWithTab extends StatefulWidget {
#override
State<StatefulWidget> createState() => MainScreenWithTabState();
}
class MainScreenWithTabState extends State<MainScreenWithTab> {
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text('Screen'),
),
body: Column(
children: <Widget>[
TabBar(
tabs: <Widget>[
Tab(
text: 'Left',
),
Tab(
text: 'Right',
)
],
),
Expanded(
child: TabBarView(children: [
RaisedButton(
child: Text('Tap for new screen'),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => Screen()));
},
),
FlatButton(
child: Text('Push View 2'),
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => Screen()));
},
),
]),
),
],
),
),
);
}
}
class Screen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Screen'),
),
body: Container(
width: double.infinity,
height: double.infinity,
color: Colors.yellow,
child: Center(
child: Text('New Screen'),
),
),
);
}
}
Navigator.of(context,rootNavigator: true)
.push(
MaterialPageRoute(
builder: (context) => PDFScreen(path: pathPDF.path),
),
);
You should allow the screen a new navigator, try the above code, it should work now.