I'm trying to open a PDF dynamically and not from a static string, so that I can upload multiple pdf's and it opens whichever the user has selected. It instantiates using the FullPDFViewerScreen widget below, and I'd like to be able to pass other PDF's and change the title also subjective to the PDF chosen.
Here is my class for it:
import 'data.dart';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_full_pdf_viewer/full_pdf_viewer_scaffold.dart';
import 'dart:typed_data';
class Detail extends StatelessWidget {
final Book book;
Detail(this.book);
final String _documentPath = 'PDFs/test-en.pdf';
#override
Widget build(BuildContext context) {
Future<String> prepareTestPdf() async {
final ByteData bytes =
await DefaultAssetBundle.of(context).load(_documentPath);
final Uint8List list = bytes.buffer.asUint8List();
final tempDir = await getTemporaryDirectory();
final tempDocumentPath = '${tempDir.path}/$_documentPath';
final file = await File(tempDocumentPath).create(recursive: true);
file.writeAsBytesSync(list);
return tempDocumentPath;
}
//app bar
final appBar = AppBar(
elevation: .5,
title: Text(book.title),
);
///detail of book image and it's pages
final topLeft = Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(16.0),
child: Hero(
tag: book.title,
child: Material(
elevation: 15.0,
shadowColor: Colors.yellow.shade900,
child: Image(
image: AssetImage(book.image),
fit: BoxFit.cover,
),
),
),
),
text('${book.pages} pages', color: Colors.black38, size: 12)
],
);
///detail top right
final topRight = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
text(book.title,
size: 16, isBold: true, padding: EdgeInsets.only(top: 16.0)),
text(
'by ${book.writer}',
color: Colors.black54,
size: 12,
padding: EdgeInsets.only(top: 8.0, bottom: 16.0),
),
Row(
children: <Widget>[
text(
book.price,
isBold: true,
padding: EdgeInsets.only(right: 8.0),
),
],
),
SizedBox(height: 32.0),
Material(
borderRadius: BorderRadius.circular(20.0),
shadowColor: Colors.blue.shade200,
elevation: 5.0,
child: MaterialButton(
onPressed: () {
// We need to prepare the test PDF, and then we can display the PDF.
prepareTestPdf().then(
(path) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FullPdfViewerScreen(path)),
);
},
);
},
minWidth: 160.0,
color: Colors.blue,
child: text('Read Now', color: Colors.white, size: 13),
),
)
],
);
final topContent = Container(
color: Theme.of(context).primaryColor,
padding: EdgeInsets.only(bottom: 16.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Flexible(flex: 2, child: topLeft),
Flexible(flex: 3, child: topRight),
],
),
);
///scrolling text description
final bottomContent = Container(
height: 220.0,
child: SingleChildScrollView(
padding: EdgeInsets.all(16.0),
child: Text(
book.description,
style: TextStyle(fontSize: 13.0, height: 1.5),
),
),
);
return Scaffold(
appBar: appBar,
body: Column(
children: <Widget>[topContent, bottomContent],
),
);
}
//create text widget
text(String data,
{Color color = Colors.black87,
num size = 14,
EdgeInsetsGeometry padding = EdgeInsets.zero,
bool isBold = false}) =>
Padding(
padding: padding,
child: Text(
data,
style: TextStyle(
color: color,
fontSize: size.toDouble(),
fontWeight: isBold ? FontWeight.bold : FontWeight.normal),
),
);
}
class FullPdfViewerScreen extends StatelessWidget {
final String pdfPath;
FullPdfViewerScreen(this.pdfPath);
#override
Widget build(BuildContext context) {
return PDFViewerScaffold(
appBar: AppBar(
title: Text("Document"),
),
path: pdfPath);
}
}
main.dart where it generates the route for the detail page. I need to access the books.path that's where the pdf route is mentioned for each book.
generateRoute(RouteSettings settings) {
final path = settings.name.split('/');
final title = path[1];
Book book = books.firstWhere((it) => it.title == title);
return MaterialPageRoute(
settings: settings,
builder: (context) => Detail(book),
);
}
Update:
It seems, I misunderstood you question.
You just need to pass title and path as a parameter.
Change:
final Book book;
Detail(this.book);
final String _documentPath = 'PDFs/test-en.pdf';
To:
final Book book;
final String documentPath;
Detail(this.book, this.documentPath);
And you can get Title from book.title variable
If you want to get the pdf file from URL, you can use flutter_downloader widget.
Here is a working example.
You can pass the list of files with their file name and url.
Download them using:
task.taskId = await FlutterDownloader.enqueue(
url: task.link,
headers: {"auth": "test_for_sql_encoding"},
savedDir: _localPath,
showNotification: true,
openFileFromNotification: true);
And check if they are completed with:
if(item.task.status == DownloadTaskStatus.complete)
When completed, you can pass _localPath/fileName to FullPdfViewerScreen to open the file. (_localPath is the path you used while downloading the file.
You should also pass the path as parameter. Like this;
class Detail extends StatelessWidget {
final Book book;
final String documentPath; // <-- Add this line
Detail(this.book, this.documentPath); <-- Edit this line
#override
Widget build(BuildContext context) {
Future<String> prepareTestPdf() async {
final ByteData bytes =
await DefaultAssetBundle.of(context).load(documentPath); // Also edit your path
final Uint8List list = bytes.buffer.asUint8List();
final tempDir = await getTemporaryDirectory();
final tempDocumentPath = '${tempDir.path}/$documentPath';
final file = await File(tempDocumentPath).create(recursive: true);
file.writeAsBytesSync(list);
return tempDocumentPath;
}
...
On your generateRoute, you should do like this;
generateRoute(RouteSettings settings) {
final path = settings.name.split('/');
final title = path[1];
Book book = books.firstWhere((it) => it.title == title);
return MaterialPageRoute(
settings: settings,
builder: (context) => Detail(book,settings.name), // <-- This is your path as parameter.
);
}
Related
I wants to put the calendar half on one container and half on another container. I tried it using stack but it doesn't worked well can anyone guide me regarding that? Below code is giving an error as bottom overflowed. I wants to put calendar half on orange colored widget at top and half on white colored widget below that:
import 'dart:async';
import 'package:AtDocHUB/Model/Document.dart';
import 'package:AtDocHUB/Model/User.dart';
import 'package:AtDocHUB/Notification/AptNotification.dart';
import 'package:AtDocHUB/View/BottomNavigationBar.dart';
import 'package:AtDocHUB/View/Document/adminSearchDocStatus.dart';
import 'package:AtDocHUB/View/Document/dateSearch.dart';
import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart';
import 'package:AtDocHUB/View/Activity/ActivityStatusPage.dart';
import 'package:AtDocHUB/View/Document/DocumentPage.dart';
import 'package:AtDocHUB/View/homePageAdmin.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:get/get.dart';
import '../../Controller/AppointmentController.dart';
import '../../Model/Appointment.dart';
import '../Controller/DocumentController.dart';
import 'Appointment/AddNewAppointment.dart';
import 'Appointment/AppointmentsDetailsEditPage.dart';
import 'package:table_calendar/table_calendar.dart'; //import '../Controller/AppointmentController.dart';
// import '../Controller/DocumentController.dart';
//import '../Model/Appointment.dart';
//import 'Appointment/AddNewAppointment.dart';
//import 'Appointment/AppointmentDetailPage.dart';
class AppointmentHomePage extends StatefulWidget {
final String userName;
final String playerid;
AppointmentHomePage(
this.playerid,
this.userName,
);
// final TextEditingController mycontroller = TextEditingController();
#override
State<AppointmentHomePage> createState() => _AppointmentHomePageState(
this.playerid,
this.userName,
);
}
class _AppointmentHomePageState extends State<AppointmentHomePage> {
late final String userName;
final String playerid;
var focusedDay;
_AppointmentHomePageState(
this.playerid,
this.userName,
);
late final String executive;
final TextEditingController typeAheadControllerDate = TextEditingController();
final TextEditingController typeAheadControllerName = TextEditingController();
//String formattedDate = DateFormat('yyyy-MM-dd – kk:mm');
AppointmentController appointmentController =
Get.put(AppointmentController());
final TextEditingController controller = TextEditingController();
final TextEditingController dateController = TextEditingController();
List<UserLogin> logs = [];
String email = '';
String pass = '';
List<Document> docs = [];
//final _myController = TextEditingController(text: '');
TextEditingController dateinput = TextEditingController();
late Future<List<Appointment>> futureAppointments; //call for search bar
late Future<List<Appointment>> futureapt; //call for list of documents
late Future<List<Appointment>> futuretodayapt; //call for list of documents
late Future<List<Appointment>> futuretommorowapt;
late Future<List<Appointment>> aptsExecutive =
[] as Future<List<Appointment>>; //call for search bar
List<Appointment> apmnt = [];
String query = '';
String dTitle = '';
String token = '';
String username = '';
int aptid = 0;
#override
void initState() {
super.initState();
dateinput.text = "";
//set the initial value of text field
futureAppointments = AppointmentController
.fetchSearchAppointmentList(); //call for search bar
futureapt = AppointmentController
.fetchAppointmentList(); //call for list of documents
futuretodayapt = AppointmentController.fetchAptByTodays();
futuretommorowapt = AppointmentController.fetchAptByTommorow();
init();
}
Future init() async {
final apmnt = await AppointmentController.fetchAppointmentList();
final aptsExecutive = await AppointmentController.fetchAppointments;
setState(() {
this.apmnt = apmnt;
// this.aptsExecutive = aptsExecutive as Future<List<Appointment>>;
for (int i = 0; i <= apmnt.length; i++) {
this.username = apmnt[i].userName;
this.aptid = apmnt[i].aptId;
}
});
// final docs = await DocumentController.getdocs(query);
setState(() {
// this.docs = docs;
// for (int i = 0; i <= docs.length; i++) {
// this.dTitle = docs[i].docTitle;
// this.token = docs[i].tokenNo.toString();
// }
});
print(docs);
}
//Widget searchbar() => SearchWidget();
Widget bottomappbar() => BottonNavigationBar(this.userName);
#override
Widget build(BuildContext context) {
const appTitle = 'Appointment';
return MaterialApp(
debugShowCheckedModeBanner: false,
title: appTitle,
home: Scaffold(
// backgroundColor: // Color.fromARGB(
// //255, 3, 87, 156),
// Color.fromARGB(255, 253, 153, 33),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, color: Color.fromARGB(255, 255, 255, 255)),
backgroundColor: Color.fromARGB(255, 253, 153, 33),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => AddAppointment(
this.userName,
//this.createdBY
)));
}),
bottomNavigationBar: bottomappbar(),
body: Stack(children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.end,
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Color.fromARGB(255, 253, 153, 33),
),
height: MediaQuery.of(context).size.height * 0.2,
//padding: EdgeInsets.only(right: 5.0),
child: Padding(
padding: const EdgeInsets.all(3.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
IconButton(
icon: const CircleAvatar(
child: Icon(
Icons.arrow_back_ios_new_sharp,
size: 15,
color:
// Color.fromARGB(255, 3, 87,
// // 156),
Color.fromARGB(255, 253, 153, 33),
),
backgroundColor: Colors.white, maxRadius: 10,
minRadius: 2,
// child: Icons.arrow_back_ios_new_rounded,
),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
DocumentPage(this.userName)))),
Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
'Appointment',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
// textAlign: TextAlign.center,
),
),
Expanded(
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.08,
),
),
IconButton(
alignment: Alignment.center,
icon: Icon(
Icons.notification_important_rounded,
// size: 20,
color: Colors.white,
),
iconSize: 20,
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
DocumentPage(this.userName))),
),
IconButton(
// alignment: Alignment.bottomRight,
icon: Icon(
Icons.edit_attributes_sharp,
// size: 20,
color: Colors.white,
),
iconSize: 20,
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
AppointmentDetailsEditPage(
this.userName, this.aptid, 45)))),
IconButton(
// alignment: Alignment.bottomRight,
icon: Icon(
Icons.add_circle_outline_rounded,
// size: 20,
color: Colors.white,
),
iconSize: 20,
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) =>
AddAppointment(this.userName)))),
],
),
AptSearch(),
Positioned(
top: 40,
child: ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30)),
child: Center(
child: Padding(
padding: const EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
TableCalendar(
focusedDay: DateTime.now(),
firstDay: DateTime.now(),
lastDay: DateTime.utc(2030, 1, 1),
)
],
),
),
),
),
),
],
),
),
),
],
),
]),
),
);
}
Widget AptSearch() => SearchWidget(
text: query,
hintText: 'Title or Token No.',
onChanged: searchdoc,
);
Future searchdoc(String query) async {
debounce() async {
{
final docs = await DocumentController.getdocs(query);
if (!mounted) return;
setState(() {
this.query = query;
this.docs = docs;
});
}
}
}
}
You code is very close to the solution. I think I know what issue you are facing. May be the positioned widget is not taking full height to render the calendar & other items. To solve this simply use Align widget with heightFactor like this.
Align(
alignment: Alignment.topLeft,
heightFactor: 1,
This will generate your widget from the exact top left starting below the last widget & heightFactor will tell that it can use the full available height.
You can also use list view inside this align widget which is using full height so it will provide scroll on smaller devices.
You can check my sample code here https://dartpad.dev/?id=92c59353b949ed0c1cf99843ddb9ccbb
This is a Flutter app that I wrote long ago which pushes a user-selected image to Firebase and generates output using an ML model on the server.
I want to modify the same app. It is a completely offline app, so Firebase is not an option. So there are just 4 images that the user will be using as input. The app must be hardcoded to display a predefined output depending on which image is uploaded.
The possible methods I thought of were,
Store those images as assets in the app. Compare the input image's name to that of the asset images. Display output is there is a match.
Use image comparison algorithms using packages like image_compare.
None of the above methods worked, maybe I am doing it wrong. Please help me out.
Also, sorry for the non systematic code below.
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:firebase_storage/firebase_storage.dart' as firebase_storage;
import 'package:del04/splashscreen.dart';
import 'package:del04/page/info_page.dart';
import 'package:del04/data.dart';
import 'package:dotted_border/dotted_border.dart';
import 'package:iconsax/iconsax.dart';
import 'package:path/path.dart';
import 'package:file_picker/file_picker.dart';
import 'package:file_support/file_support.dart';
late String name, path , domain , phylum , clas , order , family , genus , species ;
File? _photo;
// ignore: prefer_typing_uninitialized_variables
var image;
File a= File('assets/images/1.jpg'), b= File('assets/images/2.jpg'), c= File('assets/images/3.jpg'), d= File('assets/images/4.jpg');
var which=-1;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => const Splash_screen(),
'/home': (context) => ImageUploads(),
'/home/info_page': (context) => Info_page()
}
)
);
}
class ImageUploads extends StatefulWidget {
const ImageUploads({Key? key}) : super(key: key);
#override
// ignore: library_private_types_in_public_api
_ImageUploadsState createState() => _ImageUploadsState();
}
class _ImageUploadsState extends State<ImageUploads> {
//firebase_storage.FirebaseStorage storage = firebase_storage.FirebaseStorage.instance;
Future imgFromGallery() async {
final FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpg', 'pdf'],
);
setState(() {
if (result != null) {
_photo= result as File;
String? filename= FileSupport().getFileNameWithoutExtension(_photo!);
image= _photo as Image;
} else {
if (kDebugMode) {
print('No image selected.');
}
}
});
}
/* Future imgFromCamera() async {
final pickedFile = await _picker.pickImage(source: ImageSource.camera);
setState(() {
if (pickedFile != null) {
_photo = File(pickedFile.path);
image= _photo;
} else {
// ignore: avoid_print
print('No image selected.');
}
});
} //from Camera
Future uploadFile() async {
//if (_photo == null) return;
//const destination = 'Abhinav/';
try {
final ref = firebase_storage.FirebaseStorage.instance
.ref(destination)
.child('file/');
await ref.putFile(_photo!);
}
catch (e) {
if (kDebugMode) {
print('Error occurred, try again.');
}
}
}*/
void _onLoading() {
/*showDialog(
context: this.context,
barrierDismissible: false,
builder: (BuildContext context) {
return Dialog(
child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
SizedBox(height: 80, width: 80),
CircularProgressIndicator(),
Text(" Analyzing..."),
],
),
);
},
);*/
//douploadingshit();
Future.delayed(const Duration(seconds: 2), () async {
if(image.readAsBytesSync().lengthInBytes != a.readAsBytesSync().lengthInBytes)which= 1;
else if(image.readAsBytesSync().lengthInBytes == b.readAsBytesSync().lengthInBytes)which= 2;
else if(image.readAsBytesSync().lengthInBytes == c.readAsBytesSync().lengthInBytes)which= 3;
else if(image.readAsBytesSync().lengthInBytes == d.readAsBytesSync().lengthInBytes)which= 4;
else which= 99;
//pop dialog
//final ref = FirebaseDatabase.instance.ref();
//final snapshot = await ref.child('/').get();
//name = (snapshot.value) as String;
const Data().setData();
//Navigator.pop(this.context); //pop dialog
Navigator.of(this.context).push(MaterialPageRoute(builder: (context)=>Info_page()));
/*if(which==99){
fetch_errorM();
}
else{
Navigator.of(this.context).push(MaterialPageRoute(builder: (context)=>Info_page()));
}*/
});
}
/* Future<void> douploadingshit() async {
uploadFile();
DatabaseReference ref = FirebaseDatabase.instance.ref("");
await ref.update({
"confirm/state": "yes",
});
}*/
void fetch_errorM() {
showDialog(
context: this.context,
barrierDismissible: false,
builder: (BuildContext context) {
return Dialog(
child: Row(
mainAxisSize: MainAxisSize.min,
children: const [
SizedBox(height: 80, width: 30),
Text("Could not analyze sample.\nPlease Retry or try another Image."),
],
),
);
},
);
Future.delayed(const Duration(seconds: 2), () async {
Navigator.pop(this.context); //pop dialog
});
}
//----------------------------------------------------------------------------
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('\t Baclens'),
backgroundColor: Colors.blueGrey.shade900,
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
const SizedBox(height: 80,),
Text('Upload your image file', style: TextStyle(fontSize: 25, color: Colors.grey.shade800, fontWeight: FontWeight.bold),),
const SizedBox(height: 10,),
Text('File should be jpg or png only', style: TextStyle(fontSize: 15, color: Colors.grey.shade500),),
const SizedBox(height: 20,),
GestureDetector(
onTap: () {
_showPicker(context);
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0),
child: DottedBorder(
borderType: BorderType.RRect,
radius: const Radius.circular(10),
dashPattern: const [10, 5],
strokeCap: StrokeCap.round,
color: Colors.grey.shade900,
child: Container(
width: double.infinity,
height: 150,
decoration: BoxDecoration(
color: Colors.blue.shade50.withOpacity(.3),
borderRadius: BorderRadius.circular(10)
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Iconsax.document_upload5, color: Colors.grey.shade900, size: 40,),
const SizedBox(height: 15,),
Text('Click to choose image', style: TextStyle(fontSize: 15, color: Colors.grey.shade400),),
],
),
),
)
),
),
_photo != null
? Container(
padding: const EdgeInsets.all(15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(' Selected File:',
style: TextStyle(color: Colors.grey.shade400, fontSize: 15, ),),
const SizedBox(height:10),
Container(
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(1),
color: Colors.transparent,
),
child: Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(2),
child: Image.file(_photo!, width: 200, height: 200, fit: BoxFit.fitWidth)
),
)
),
const SizedBox(height: 30,),
MaterialButton(
minWidth: double.infinity,
height: 50,
onPressed: () {
_onLoading();
////////////////////////////////////////////////////////////////////////////////
setState((){
const Data().setData();
Navigator.pop(this.context); //pop dialog
Navigator.of(this.context).push(MaterialPageRoute(builder: (context)=>Info_page()));
});
},
color: Colors.blueGrey.shade900,
child: const Text('Upload', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),),
)
],
))
: Container(),
const SizedBox(height: 150,),
],
),
),
);
}
void _showPicker(context) {
showModalBottomSheet(
context: context,
builder: (BuildContext bc) {
return SafeArea(
child: Wrap(
children: <Widget>[
ListTile(
leading: const Icon(Icons.photo_library),
title: const Text('Gallery'),
onTap: () {
imgFromGallery();
Navigator.of(context).pop();
}),
/*ListTile(
leading: const Icon(Icons.photo_camera),
title: const Text('Camera'),
onTap: () {
imgFromCamera();
Navigator.of(context).pop();
},
),*/
],
),
);
});
}
}
I'm currently developing a Fingerspelling learning app. In the fingerspelling_screen.dart file, user will be able to choose which category that he/she would like to learn first. When the user chooses either one of the button, the app will query Firebase Firestore to get a list of signs object which contains the name of the sign, the category to which the sign belongs to and the video URL of each sign before navigating user to sign_video.dart which is a video player. From there, user can press next to switch to the next sign in the category. When the user presses on the check sign button, the user will be navigating to the check sign_checker.dart to check if they are performing a sign correctly.
I've been passing the 'category' variable from one screen to another using constructor and I do not think it is very effective. Is there any way I could solve this?
I wish to initilize vidlist variable (a variable that stores a list of Sign objects) in the initState because the video player controller needs to be initialized first. I've tried using StreamProvider, but for some reason, I couldn't initialize the vidlist variable in initState. The vidlist variable would always be null.
Thank you.
fingerspelling.dart
import 'package:slem_proto/screens/sign_video.dart';
import 'package:slem_proto/shared/constants.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:undraw/undraw.dart';
class FingerspellingScreen extends StatelessWidget {
static String routeName = 'fingerspelling_screen';
#override
Widget build(BuildContext context) {
return Scaffold(
body: Padding(
padding: EdgeInsets.only(left: 20, right: 20, top: 50),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Fingerspelling',
style: kHeadingTextStyle,
),
SizedBox(height: 30),
FingerspellingTab(
title: 'Alphabets',
illustration: UnDrawIllustration.learning,
onTap: () {
print('Alphabet tab tapped');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SignVideoScreen(
category: 'alphabets',
),
),
);
},
),
SizedBox(
height: 15,
),
FingerspellingTab(
title: 'Numbers',
illustration: UnDrawIllustration.calculator,
onTap: () {
print('Number tab tapped');
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SignVideoScreen(
category: 'numbers',
),
),
);
},
),
],
),
),
);
}
}
class FingerspellingTab extends StatelessWidget {
final String title;
final UnDrawIllustration illustration;
final Function onTap;
const FingerspellingTab(
{#required this.title,
#required this.illustration,
#required this.onTap});
#override
Widget build(BuildContext context) {
return InkWell(
child: Container(
width: double.infinity,
height: 250,
decoration: BoxDecoration(
color: Color.fromRGBO(58, 139, 238, 0.2),
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.only(left: 20, top: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: kHeadingTextStyle.copyWith(
color: Color.fromRGBO(80, 80, 80, 0.8),
fontSize: 25,
),
),
SizedBox(
height: 15,
),
Container(
height: 150,
child: UnDraw(
color: Color(0xFF6C63FF),
illustration: illustration,
placeholder: Text(
"Illustration is loading..."), //optional, default is the CircularProgressIndicator().
),
),
],
),
),
),
onTap: onTap,
);
}
}
database.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:slem_proto/models/sign.dart';
class DatabaseService {
// collection reference
final CollectionReference signCollection =
FirebaseFirestore.instance.collection('signs');
// Sign list from snapshot
List<Sign> _signListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.docs.map((doc) {
return Sign(
category: doc.data()['category'] ?? '',
sign_name: doc.data()['sign_name'] ?? '',
sign_url: doc.data()['sign_url'] ?? '',
);
}).toList();
}
// get signs stream
Stream<List<Sign>> get signs {
return signCollection.snapshots().map(_signListFromSnapshot);
}
// get signs stream
Stream<List<Sign>> getSignFromCategory({String category}) {
return signCollection
.where('category', isEqualTo: category)
.snapshots()
.map(_signListFromSnapshot);
}
}
sign_checker.dart
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:image_picker/image_picker.dart';
class SignChecker extends StatefulWidget {
final String category;
SignChecker({this.category});
#override
_SignCheckerState createState() => _SignCheckerState(category: this.category);
}
class _SignCheckerState extends State<SignChecker> {
final String category;
_SignCheckerState({this.category});
File _image;
bool predictionStarted = false;
bool predictionComplete = false;
var predictionResult = 'Please wait...';
Future getImage() async {
setState(() {
predictionStarted = false;
predictionComplete = false;
});
// Get image from camera
// var image = await ImagePicker.pickImage(source: ImageSource.camera);
// Get image from gallery
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
predictionStarted = true;
});
// Base64 Encode the image
List<int> imageBytes = image.readAsBytesSync();
String base64Image = base64.encode(imageBytes);
// Print the base64 encoded string in console
print(base64Image);
// Send the encoded image with POST request
Map<String, String> headers = {"Accept": "application/json"};
Map body = {"image": base64Image};
// var response = await http.post('http://XX.XXX.XXX.X/automl.php',
// body: body, headers: headers);
var response = await http.post('http://XX.XXX.XXX.X/automl_alphabet.php',
body: body, headers: headers);
// Print the status code returned by server
print('Status code');
print(response.statusCode);
// Get prediction Result
setState(() {
predictionResult = response.body;
predictionComplete = true;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Sign Checker'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Text(
'Push the camera button',
textAlign: TextAlign.center,
),
RaisedButton(
onPressed: getImage,
child: Text('Camera'),
),
(_image != null)
? Image.file(
_image,
scale: 50,
)
: Text('No Image Picked'),
predictionBody()
],
),
),
);
}
Widget predictionBody() {
var predictionText = (predictionComplete) ? 'Result' : 'Prediction started';
if (predictionStarted) {
return Column(
children: <Widget>[
Divider(),
Text(predictionText),
Text(predictionResult)
],
);
} else {
return Container();
}
}
}
sign.dart
class Sign {
final String category;
final String sign_name;
final String sign_url;
Sign({this.category, this.sign_name, this.sign_url});
}
Firstly, using constructors to pass variables may not be inefficient, since Flutter only pass on references. Say,
var a = List(...huge list...);
var b = a;
Then the second line is not costly.
Secondly, if you ask about state management, you may try Mobx, Bloc, Redux, etc. There are many ways to do so.
I have deleted my previous question and replaced it by this one may be most clear ,
I receive data from API and convert it to List contain (id , title , description , activity , degree ).
Now I want to display data such as appear in image below :
Note : (the title and description in all rows are same)
class page :
class Digree {
final int index;
final String title_k;
final String title_a;
final String aya;
final String link;
final String activity_k;
final String activity_a;
final String udigree;
Digree(this.index, this.title_k, this.title_a, this.aya, this.link,
this.activity_k, this.activity_a, this.udigree);
}
future function page
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:jiyanUquraan/classes/viewdigree.dart';
class DisplayList extends StatefulWidget {
#override
_DisplayListState createState() => _DisplayListState();
}
class _DisplayListState extends State<DisplayList> {
#override
Widget build(BuildContext context) {
Map rdata = {};
List digrees = [];
double _value = 0;
var widthView = MediaQuery.of(context).size.width;
Future<List> fetchDigrees() async {
Map rdata = ModalRoute.of(context).settings.arguments;
int cm_id = int.parse(rdata['current_m_id'].toString());
int d_id = int.parse(rdata['d_id'].toString());
int w_id = int.parse(rdata['w_id'].toString());
int u_id = int.parse(rdata['u_id'].toString());
var url =
'http://10.0.2.2/jiyan/test/api/digrees/day_digree.php?u_id=$u_id&m_id=$cm_id&d_id=$d_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['udigree']);
digrees.add(newdigree);
}
print(digrees.length);
print(data);
return digrees;
}
return FutureBuilder(
future: fetchDigrees(),
builder: (context, snapshot) {
List digrees = snapshot.data;
if (snapshot.data == null) {
return Center(
child: Text("Loading"),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Directionality(
textDirection: TextDirection.rtl,
child: Column(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(width: 2, color: Colors.white),
color: Color.fromRGBO(230, 200, 200, 0.2)),
width: widthView,
padding: EdgeInsets.all(25),
margin: EdgeInsets.all(25),
child: Column(
children: <Widget>[
Text(
snapshot.data[index].activity_k,
textAlign: TextAlign.justify,
style:
TextStyle(fontSize: 32, color: Colors.white),
),
SliderTheme(
data: SliderTheme.of(context).copyWith(
activeTrackColor: Colors.red[700],
inactiveTrackColor: Colors.red[100],
trackShape: RectangularSliderTrackShape(),
trackHeight: 4.0,
thumbColor: Colors.redAccent,
thumbShape: RoundSliderThumbShape(
enabledThumbRadius: 12.0),
overlayColor: Colors.red.withAlpha(32),
overlayShape: RoundSliderOverlayShape(
overlayRadius: 28.0),
),
child: Slider(
value: 0,
min: 0,
max: 100,
divisions: 10,
label: '$_value',
onChanged: null,
),),],),),],),);});}},);}}
display page :
import 'package:flutter/material.dart';
import 'package:jiyanUquraan/components/daylist.dart';
class Days extends StatefulWidget {
#override
_DaysState createState() => _DaysState();
}
class _DaysState extends State<Days> {
var cm_id;
var d_id;
var w_id;
var u_id;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.pink[900],
title: Text(
'ژیان و قورئان',
style: TextStyle(fontSize: 30),
),
centerTitle: true,
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/background.png"),
fit: BoxFit.cover,
),
),
child: DisplayList()),
);
}
}
Answer 3.0
So, as far as I have understood the situation correctly, the title_k and aya needs to be called once, and then Directionality() which is getting built by Column(). Which will wrap your Directionality based upon the snapshot.data list
ListView(
shrinkWrap: true,
children: [
Text('title_k'),
Text('aya'),
Column(
children: snapshot.data.map<Widget>((e) => Directionality(...)).toList()
)
]
)
Please note: You must get the data in the Directionality as e.key_of_digree_model. e can be anything, whatever, you will describe map((item))
For example: Text(snapshot.data[index].activity_k) will become Text(item.activity_k) in the Directionality only
Now we will write the normal code which will give you the answer. Specifically, your answer lies in DisplayList() only. So posting that as an answer
Assumption: I can see that your title_k and aya is same for every Digree Model, so I will just get the title_k and aya from the index = 0 only. Like this
// title
Text(snapshot.data[0].title_k)
//Description
Text(snapshot.data[0].aya)
DisplayList()
//specific code only, since Column() has all the data required
// inside your else of FutureBuilder
return Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: ListView(
shrinkWrap: true,
children: [
//title
Text(snapshot.data[0].title_k),
//for top margin
SizedBox(height: 20.0),
// dexription
Text(snapshot.data[0].aya),
//for top margin
SizedBox(height: 20.0),
// your Directionality
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: snapshot.data.map<Widget>((item){
// for example snapshot.data[index].activity_k will become
// item.activity_k
return Directionality(....);
}).toList()
)
]
)
);
Please read about Mapping a list item StackoverFlow
Am trying to load a blog on flutter using API. for some reasons, the file is not loading on the emulator, and the code not showing any errors or suggestions. Once i click run, after the connection, it stops abruptly... Please, if anyone can preview the code and and help me out.. The error log is saying something about immutable, which i don't really follow.. Please help.
Main.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:html/parser.dart';
import 'pages/post_view.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _isLoading = true; //For progress bar
var posts;
var imgUrl;
//initialization
void initState() {
super.initState();
_fetchData();
}
//Function to fetch data from JSON
_fetchData() async {
print("attempting");
final url =
"https://www.googleapis.com/blogger/v3/blogs/MY BLOG ID HERE/posts/?key= API KEY HERE";
final response = await http.get(url);
print(response);
if (response.statusCode == 200) {
//HTTP OK is 200
final Map items = json.decode(response.body);
var post = items['items'];
setState(() {
_isLoading = false;
this.posts = post;
});
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Blogger"),
actions: <Widget>[
new IconButton(
icon: new Icon(Icons.refresh),
onPressed: () {
setState(() {
_isLoading = true;
});
_fetchData();
})
],
),
body: new Center(
child: _isLoading
? new CircularProgressIndicator()
: new ListView.builder(
itemCount: this.posts != null ? this.posts.length : 0,
itemBuilder: (context, i) {
final Post = this.posts[i];
final postDesc = Post["content"];
//All the below code is to fetch the image
var document = parse(postDesc);
//Regular expression
RegExp regExp = new RegExp(
r"(https?:\/\/.*\.(?:png|jpg|gif))",
caseSensitive: false,
multiLine: false,
);
final match = regExp
.stringMatch(document.outerHtml.toString())
.toString();
//print(document.outerHtml);
//print("firstMatch : " + match);
//Converting the regex output to image (Slashing) , since the output from regex was not perfect for me
if (match.length > 5) {
if (match.contains(".jpg")) {
imgUrl = match.substring(0, match.indexOf(".jpg"));
print(imgUrl);
} else {
imgUrl =
"https://pbs.twimg.com/profile_images/916384996092448768/PF1TSFOE_400x400.jpg";
}
}
String description = document.body.text.trim();
//print(description);
return new Container(
padding:
const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 8.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Container(
width: 500.0,
height: 180.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
image: new DecorationImage(
fit: BoxFit.fill,
//check if the image is not null (length > 5) only then check imgUrl else display default img
image: new NetworkImage(imgUrl
.toString()
.length >
10
? imgUrl.toString()
: "https://pbs.twimg.com/profile_images/916384996092448768/PF1TSFOE_400x400.jpg")),
),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 10.0),
child: new Text(
Post["title"],
maxLines: 3,
style: new TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
),
),
),
new Text(
description.replaceAll("\n", ", "),
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: new TextStyle(fontSize: 15.0),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0),
child: new RaisedButton(
child: new Text("READ MORE",style: new TextStyle(color: Colors.white),),
color: Colors.blue,
onPressed: () {
//We will pass description to postview through an argument
Navigator
.of(context)
.push(new MaterialPageRoute<Null>(
builder: (BuildContext context) {
return PostView(Post['title'],description,imgUrl);
},
));
},
),
),
Divider(),
],
),
);
},
)));
}
}
Post_view.dart
import 'package:flutter/material.dart';
class PostView extends StatelessWidget {
var desc, title, image;
PostView(String title, String desc, String image) {
this.desc = desc;
this.title = title;
this.image = image;
}
#override
Widget build(BuildContext context) {
if (desc.toString().contains("\n\n\n\n")) {
desc = desc.toString().replaceAll("\n\n\n\n", "\n\n");
}
if (desc.toString().contains("\n\n\n")) {
desc = desc.toString().replaceAll("\n\n\n", "\n");
}
return new Scaffold(
appBar: new AppBar(
title: new Text("Blogger"),
),
body: new Container(
child: new SingleChildScrollView(
child: new Column(
children: <Widget>[
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: new Text(
title,
style: new TextStyle(
fontSize: 22.0,
fontWeight: FontWeight.bold,
),
),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: new Container(
width: 500.0,
height: 180.0,
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
image: new DecorationImage(
fit: BoxFit.fill,
//check if the image is not null (length > 5) only then check imgUrl else display default img
image: new NetworkImage(image.toString().length > 10
? image.toString()
: "https://pbs.twimg.com/profile_images/916384996092448768/PF1TSFOE_400x400.jpg")),
),
),
),
new Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: new Text(
desc,
style: new TextStyle(
fontSize: 18.0,
),
),
),
],
))),
);
}
}
The problem log reads:
main.dart: Name non-constant identifiers using lowerCamelCase.
post_view.dart: This class (or a class which this class inherits from) is marked as '#immutable', but one or more of its instance fields are not final: PostView.desc, PostView.title, PostView.image
my editor marks class post on the post_view.dart as immutable.. how do i fix that.
final url =
"https://www.googleapis.com/blogger/v3/blogs/MY_BLOG_ID_HERE/posts/?key=API_KEY_HERE";
get your blog ID and put it into the required space and also get an API key for the blog from blogger
it should look like this
final url = "https://www.googleapis.com/blogger/v3/blogs/409370562475495748/posts/?key=AIzaSyA3_4OfkfLc10vy5Q2WeUhfirGUUY4J78F8bk";
also try to make these final PostView.desc, PostView.title, PostView.image and see if it works