Is there currently in flutter any way to display/load an HTML file from the assets folder in an application for linux? I have been researching for a while but to no avail. I have no code example, since all the approaches I have found are targeted for android and iOS. If anyone knows of an accessible way or a workaround, thank you in advance.
For Linux (desktop) looks like the flutter_html package works too (even if it is still not indicated at pub.dev). So what I did it's the following: I loaded the file from the rootBundle, that is, from my assets folder and parsed it to a Document object. After that, I just got the outerHtml String and passed it as a parameter to an Html Widget from the flutter_html package, as mentioned.
So if you want to give this a try, make sure you have your assets folder correctly set and store the HTML file in it. I took an example HTML file from: https://filesamples.com/formats/html.
After that, make sure you set your dependencies at pubspec.yaml (choose the versions that fit you best):
dependencies:
flutter:
sdk: flutter
html: any # Add this
flutter_html: ^1.3.0 # Add this
Still at pubspec.yaml: set the reference to your assets folder.
flutter:
uses-material-design: true
assets: # Add this
- assets/ # Add this
Then place this code in your main.dart and run it:
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:html/parser.dart' show parse;
import 'package:html/dom.dart' as dom;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Load on Linux for desktop'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
getHtml();
super.initState();
}
Future<dom.Document> getHtml() async {
return parse(await rootBundle.loadString('assets/sample1.html'));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: FutureBuilder<dom.Document>(
future: getHtml(),
builder:
(BuildContext context, AsyncSnapshot<dom.Document> snapshot) {
if (snapshot.hasData) {
return Html(data: snapshot.data.outerHtml);
} else {
return Center(
child: Text("Loading"),
);
}
}),
);
}
}
If needed, these are my OS details.
NAME="Ubuntu" VERSION="18.04.5 LTS (Bionic Beaver)" ID=ubuntu
ID_LIKE=debian PRETTY_NAME="Ubuntu 18.04.5 LTS" VERSION_ID="18.04"
Related
I am trying to call a custom widget that has a function as a parameter, however I got no clue what parameter I could assign to it. I have tested all the ideas I came up with but with no success. The idea for this, I have gained from a tutorial, however I have done some things differently, as I have different requirements.
This is my code:
import 'package:flutter/material.dart';
class NewTransaction extends StatelessWidget {
final Function addTx;
const NewTransaction({Key? key, required this.addTx}) : super(key: key);
#override
Widget build(BuildContext context) {
return Text('I cant solve this problem');
}
}
========================================================================
import 'package:flutter/material.dart';
import 'package:function_parameter_problem/new_transaction.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
NewTransaction(
addTx:
addTx), // What parameter can/should I pass here? It is crucial for my project
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Edit: Okay, but let's say that the NewTransaction() function returnes a scaffold with appbar, etc and I have to call it again, however in the following scenario:
_wykonajZapytanie() { //function called onPressed in the main window
Navigator.push(
context,
MaterialPageRoute(builder: (context) => NewTransaction()),
); /*I have to put a parameter here, but I just want to display another window, I don't know why, but I just can't get any ideas*/
}
IMPORTANT TO NOTICE In the original project, if it comes to the first example I have provided, I do not call NewTransaction(addTx...) in the main class, but in the UserTransaction class.
tldr I need to assemble an expandable list in the main class - which can be done the way below from what I know, but also I need to call this function in the the main class on the onPressed of a button to display all of the textfields, etc.
import 'package:flutter/material.dart';
import './new_transaction.dart';
import './transaction_list.dart';
import '../models/transaction.dart';
class UserTransaction extends StatefulWidget {
#override
_UserTransactionState createState() => _UserTransactionState();
}
class _UserTransactionState extends State<UserTransaction> {
final List<Transaction> _userTransactions = [
Transaction(
id: 1,
date: DateTime.now(),
numTel: 911911911,
// scoring: 'Link wygasł',
user: 'Polizei pau pau'),
Transaction(
id: 2,
date: DateTime.now(),
numTel: 911911911,
// scoring: 'Link wygasł',
user: 'Tha police')
];
void _addNewTransaction(int txNumTel, /* String txScoring,*/ String txUser) {
final newTx = Transaction(
numTel: txNumTel,
/*scoring: txScoring,*/
user: 'PLZ WORK',
date: DateTime.now(),
id: 3,
);
setState(() {
_userTransactions.add(newTx);
});
}
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[
NewTransaction(_addNewTransaction),
]);
}
}
import 'package:flutter/material.dart';
class NewTransaction extends StatelessWidget {
final VoidCallback function;
//if nothing returns
//else typedef CustomFunc = Function(int param); (replace int with your data type)
const NewTransaction({Key? key, required this.function}) : super(key: key);
#override
Widget build(BuildContext context) {
return InkWell(
child: Text('I cant solve this problem'),
onTap:function,
//if custom
//onTap: (){
// function(params);
//}
);
}
}
Call like below...
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
NewTransaction(
function: (){
//todo
},
//if custome function: (params){ todo },
)
],
),
),
If I understood your question correctly, this is the way you can pass a function with parameters:
import 'package:flutter/material.dart';
class NewTransaction extends StatelessWidget {
final Function() addTx;
const NewTransaction({Key? key, required this.addTx}) : super(key: key);
#override
Widget build(BuildContext context) {
return Text('I cant solve this problem');
}
}
When passing this Function, make sure to pass it like this: NewTransaction(addTx: () => addTx());. If you pass it like this: NewTransaction(addTx: addTx()); the function gets called instantly.
When you sayFunction addTx it means any function can be passed.
If Function() addTx it means function with no parameter.
If Function(int) addTx it means function with one required positional parameter integer.
If void Function() addTx it means function with no parameter and return type should be void.
In flutter you can also use
VoidCallback which is basically void Function() written like this
final VoidCallback addTd.
.
or can use ValueChanged<T> which is basically void Function(T value)
More info at:
https://dart.dev/guides/language/language-tour#functions
I've read many posts where someone explains how to do it, but in my case, it's not working and I'm not sure why, I've added the right folder to the pubspec.yaml and everything, this is my code
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:flutter/cupertino.dart';
import 'package:workout_time/Widgets/routines_widget.dart';
void main() => runApp(WorkoutTime());
class WorkoutTime extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My Great App',
home: Scaffold(
body: RoutinesWidget(),
),
);
}
}
class RoutinesWidget extends StatefulWidget {
#override
_RoutinesWidgetState createState() => _RoutinesWidgetState();
}
class _RoutinesWidgetState extends State<RoutinesWidget> {
#override
Widget build(BuildContext context) {
return Center(
child: FutureBuilder(
future: rootBundle.loadString("assets/data.json"),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
var myData = jsonDecode(snapshot.data.toString());
return Center(
child: Text(myData == null ? "Nothing here" : myData),
);
},
),
);
}
}
when I run it, I get the CircularProgressIndicator widget, meaning that the snapshot has no data. Can anyone help me?
Edit: here is the part in the pubspec.yaml where I import the folder:
assets:
- assets/
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
Code - pubspec.yaml
assets:
- assets/json/
Code - In a Class
static Map<dynamic, dynamic> jsonData;
loadJson() async {
String jsonContent = await rootBundle.loadString("assets/json/data.json");
jsonData = json.decode(jsonContent);
}
Hi good day i have a value enum in my mysql pending and done i want to display in my flutter app the the first letter is capitalize like Pending or if if it is done Done
Text('Status:\t' + x.status,
style: TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold,
color: x.status == 'pending'
? Colors.red
: Colors.green)),
Check out this example that I have created.
import 'package:flutter/material.dart';
import 'capitalize.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SampleApp(),
debugShowCheckedModeBanner: false,
);
}
}
class SampleApp extends StatefulWidget {
#override
_SampleAppState createState() => _SampleAppState();
}
class _SampleAppState extends State<SampleApp> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Your heading'),
),
body: Container(
child: Column(
children: <Widget>[
Text("someString".capitalize())
],
)));
}
}
This is the dart file: capitalize.dart
extension StringExtension on String {
String capitalize() {
return "${this[0].toUpperCase()}${this.substring(1)}";
}
}
for the extension to work you should have sdk at minimum at 2.7.0 in pubspec.yaml
environment:
sdk: ">=2.7.0 <3.0.0"
even if you face any problem for undefined class extension then check the below link
Flutter extension-methods not working, it says "undefined class" and "requires the extension-methods language feature"
I have a basic stateful app, with a GoogleMap base, which opens a BottomSheet on FloatingActionButton press. This is used as a settings tab to change/filter some lists which are then used by the map. My Provider is setup and values can be read/saved from both the GoogleMap dart file, and the BottomSheet dart file.
My main problem is how to provide context to the Provider.of() when not in the Widget Tree. For example, the GoogleMap runs onMapCreated: _onMapCreated, when finished loading. From within that function I want to pull a value from the Provider.of() a String, which tells me which list to use (which then populates the markers).
Things I'm trying to do:
onMapCreated() pull value from the Provider (which is later used in a DB sqflite query)
The bottomsheet needs to callback and updateMarkers() somehow, providing correct context
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
GoogleMapController mapController;
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
print(Provider.of<MyAppStateContainer>(context, listen:false).getSomeValue); <---- Doesn't work
...
}
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyAppStateContainer>(
create: (contextooo) => MyAppStateContainer(),
child: MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My Map'),
backgroundColor: Colors.green[700],
),
//Put in a stack widget so can layer other widgets on top of map widget
body: Stack(
children: <Widget>[
//Builder so we can get a CTX made, and then Provider.of() finds the Provider
Builder(
builder: (context) => GoogleMap(
mapType: Provider.of<MyAppStateContainer>(context).getMapType, <--- Works fine
markers: _markers,
onMapCreated: _onMapCreated,
...
}
Provider:
class MyAppStateContainer extends ChangeNotifier {
MyAppStateContainer();
MapType _mapType = MapType.terrain;
String _someValue;
MapType get getMapType => _mapType;
String get getSomeValue => _someValue;
}
I've tried all sorts of combinations of passing back BuildContext context but sadly I'm forever getting this error about the Widget Tree:
Unhandled Exception: Error: Could not find the correct Provider<MyAppStateContainer> above this MyApp Widget
The problem is that within _onMapCreated, you are trying to access the Provider using the context of MyApp, which is higher up the hierarchy of widgets than the Provider itself.
Convert your home widget (the Scaffold and everything below it) into a separate StatefulWidget and everything should start working, as you'll be using the context of the new widget, which is lower down the hierarchy of widgets than the Provider.
the flutter_html package is supposed to enable displaying html elements properly. But when I try to render a simple example, (or the example provided on github) the sub and sup elements aren't displayed.
(Not just shown incorrectly but rather not displayed at all). Neither does
Android Studio throw any warning/error
I'm running the latest version of Android Studio on Ubuntu 18.4.
The problem appears when installing the example app and an emulated Pixel 2 with Android 9.0, as well as on an Samsung Galaxy A5 (2017).
I opened an issue in the flutter_html github repo, but after asking for additional information the author remained silent.
the main.dart file in the flutter project looks like:
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.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(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: SingleChildScrollView(
child: Html(
data: """
<body>
<div>x<sup>2</sup></div>
</body>
""",
),
),
),
);
}
}
and in the pubspec.yaml I wrote:
flutter_html: ^0.10.4
the main.dart results in:
x
instead of:
x^2
Because the "HtmlRichTextParser" doesn't seems to support "<sup>" and "<sub>", but is enabled by default. By setting
Html(
useRichText = false,
...
in the c'tor of the Html widget, the example is displayed correctly.