Wrong Flutter error Convert image ImagePicker type File to base64, Wrong Encoded - flutter

I need to convert an image that I get from the device with ImagePicker, convert it from File type to base64 to store it through a post in a db, but the procedure I do to convert it does not do it well, it converts only a thin line and the rest blank, apparently readAsbyte does not convert well when implemented as "var bytes = imageFile.readAsBytesSync ();" makes it incomplete
this is how i am implementing it
File imageFile;
void _openGallery(BuildContext context) async{
var picture = await ImagePicker().getImage(source: ImageSource.gallery);
this.setState(() {
imageFile = File(picture.path);
var bytes = imageFile.readAsBytesSync();
String imagenConvertida = base64.encode(bytes);
print(bytes);
print(imagenConvertida);
});
Navigator.of(context).pop();
}

From your implementation,
File imageFile;
void _openGallery(BuildContext context) async{
var picture = await ImagePicker().getImage(source: ImageSource.gallery);
this.setState(() {
imageFile = File(picture.path);
var bytes = imageFile.readAsBytesSync();
String imagenConvertida = base64.encode(bytes);
print(bytes);
print(imagenConvertida);
});
Navigator.of(context).pop();
The output of bytes is
[255, 216, 255, 225, 1, 181, 69, 120, 105, 102, 0, 0, 77, 77, 0, 42,
0, 0, 0, 8, 0, 7, 1, 16, 0, 2, 0, 0, 0, 26, 0, 0, 0, 98, 1, 0, 0, 4,
0, 0, 0, 1, 0, 0, 3, 192, 1, 1, 0, 4, 0, 0, 0, 1, 0, 0, 5, 0, 1, 50,
0, 2, 0, 0, 0, 20, 0, 0, 0, 124, 1, 18, 0, 3, 0, 0, 0, 1, 0, 1, 0, 0,
135, 105, 0, 4, 0, 0, 0, 1, 0, 0, 0, 151, 1, 15, 0, 2, 0, 0, 0, 7, 0,
0, 0, 144, 0, 0, 0, 0, 65, 110, 100, 114, 111, 105, 100, 32, 83, 68,
75, 32, 98, 117, 105, 108, 116, 32, 102, 111, 114, 32, 120, 56, 54, 0,
50, 48, 50, 48, 58, 48, 57, 58, 48, 50, 32, 48, 52, 58, 49, 53, 58,
51, 54, 0, 71, 111, 111, 103, 108, 101, 0, 0, 16, 130, 157, 0, 5, 0,
0, 0, 1, 0, 0, 1, 93, 130, 154, 0, 5, 0, 0, 0, 1, 0, 0, 1, 101, 146,
146, 0, 2, 0, 0, 0, 4, 56, 56, 57, 0, 146, 145, 0, 2, 0, 0, 0, 4, 56,
56, 57, 0, 146, 144, 0, 2, 0, 0, 0, 4, 56, 56, 57, 0, 146, 10, 0, 5,
0, 0, 0, 1, 0, 0, 1, 109, 146, 9, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 136,
39, 0, 3, 0, 0, 0, 1, 0, 100, 0, 0, 144, 4, 0, 2, 0, 0, 0, 20, 0, 0,
1, 117, 144, 3, 0, 2, 0, 0, 0, 20, 0,
The output of imagenConvertida is
/9j/4QG1RXhpZgAATU0AKgAAAAgABwEQAAIAAAAaAAAAYgEAAAQAAAABAAADwAEBAAQAAAABAAAFAAEyAAIAAAAUAAAAfAESAAMAAAABAAEAAIdpAAQAAAABAAAAlwEPAAIAAAAHAAAAkAAAAABBbmRyb2lkIFNESyBidWlsdCBmb3IgeDg2ADIwMjA6MDk6MDIgMDQ6MTU6MzYAR29vZ2xlAAAQgp0ABQAAAAEAAAFdgpoABQAAAAEAAAFlkpIAAgAAAAQ4ODkAkpEAAgAAAAQ4ODkAkpAAAgAAAAQ4ODkAkgoABQAAAAEAAAFtkgkAAwAAAAEAAAAAiCcAAwAAAAEAZAAAkAQAAgAAABQAAAF1kAMAAgAAABQAAAGJoAMABAAAAAEAAAUApAMAAwAAAAEAAAAAoAIABAAAAAEAAAPAkgIABQAAAAEAAAGdkgEACgAAAAEAAAGlkAAABwAAAAQwMjIwAAAAAAAAARgAAABkAJiWgDuaygAAABOIAAAD6DIwMjA6MDk6MDIgMDQ6MTU6MzYAMjAyMDowOTowMiAwNDoxNTozNgAAAAEpAAAAZAAAGfMAAAPo/+AAEEpGSUYAAQEAAAEAAQAA/9sAQwACAQEBAQECAQEBAgICAgIEAwICAgIFBAQDBAYFBgYGBQYGBgcJCAYHCQcGBggLCAkKCgoKCgYICwwLCgwJCgoK/9sAQwECAgICAgIFAwMFCgcGBwoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK/8AAEQgFAAPAAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVm
Reversing it, I come up with the following code:
File imageFile;
Image decodedImage;
void _openGallery(BuildContext context) async {
var picture = await ImagePicker().getImage(source: ImageSource.gallery);
this.setState(
() {
imageFile = File(picture.path);
// Convert image to base64
var bytes = imageFile.readAsBytesSync();
String imagenConvertida = base64.encode(bytes);
print('Value of bytes: $bytes');
print('Value of imagenConvertida: $imagenConvertida');
// Convert base64 to image
Uint8List decodedBytes = base64.decode(imagenConvertida);
decodedImage = Image.memory(decodedBytes);
print('Value of decodedBytes: $decodedBytes');
print('Value of decodedImage: $decodedImage');
},
);
// Commented out for testing purposes
// Navigator.of(context).pop();
}
When you compare the output the value of decodedBytes
[255, 216, 255, 225, 1, 181, 69, 120, 105, 102, 0, 0, 77, 77, 0, 42,
0, 0, 0, 8, 0, 7, 1, 16, 0, 2, 0, 0, 0, 26, 0, 0, 0, 98, 1, 0, 0, 4,
0, 0, 0, 1, 0, 0, 3, 192, 1, 1, 0, 4, 0, 0, 0, 1, 0, 0, 5, 0, 1, 50,
0, 2, 0, 0, 0, 20, 0, 0, 0, 124, 1, 18, 0, 3, 0, 0, 0, 1, 0, 1, 0, 0,
135, 105, 0, 4, 0, 0, 0, 1, 0, 0, 0, 151, 1, 15, 0, 2, 0, 0, 0, 7, 0,
0, 0, 144, 0, 0, 0, 0, 65, 110, 100, 114, 111, 105, 100, 32, 83, 68,
75, 32, 98, 117, 105, 108, 116, 32, 102, 111, 114, 32, 120, 56, 54, 0,
50, 48, 50, 48, 58, 48, 57, 58, 48, 50, 32, 48, 52, 58, 49, 53, 58,
51, 54, 0, 71, 111, 111, 103, 108, 101, 0, 0, 16, 130, 157, 0, 5, 0,
0, 0, 1, 0, 0, 1, 93, 130, 154, 0, 5, 0, 0, 0, 1, 0, 0, 1, 101, 146,
146, 0, 2, 0, 0, 0, 4, 56, 56, 57, 0, 146, 145, 0, 2, 0, 0, 0, 4, 56,
56, 57, 0, 146, 144, 0, 2, 0, 0, 0, 4, 56, 56, 57, 0, 146, 10, 0, 5,
0, 0, 0, 1, 0, 0, 1, 109, 146, 9, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 136,
39, 0, 3, 0, 0, 0, 1, 0, 100, 0, 0, 144, 4, 0, 2, 0, 0, 0, 20, 0, 0,
1, 117, 144, 3, 0, 2, 0, 0, 0,
And when you convert it, it will give you the exact original image, see the sample app code below:
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:image_picker/image_picker.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,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// From SO
File imageFile;
Image decodedImage;
void _openGallery(BuildContext context) async {
var picture = await ImagePicker().getImage(source: ImageSource.gallery);
this.setState(
() {
imageFile = File(picture.path);
// Convert image to base64
var bytes = imageFile.readAsBytesSync();
String imagenConvertida = base64.encode(bytes);
print('Value of bytes: $bytes');
print('Value of imagenConvertida: $imagenConvertida');
// Convert base64 to image
Uint8List decodedBytes = base64.decode(imagenConvertida);
decodedImage = Image.memory(decodedBytes);
print('Value of decodedBytes: $decodedBytes');
print('Value of decodedImage: $decodedImage');
},
);
// Commented out for testing purposes
// Navigator.of(context).pop();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 20.0,
),
Text('Original image from gallery'),
SizedBox(height: 10.0),
Container(
color: Colors.blueGrey,
height: 200.0,
width: 150.0,
child: imageFile == null
? Text('Image is not loaded')
: Image.file(imageFile),
),
SizedBox(height: 20.0),
Text('Image decoded from base64'),
SizedBox(height: 10.0),
Container(
color: Colors.grey,
height: 200.0,
width: 150.0,
child: decodedImage == null
? Text('Image is not loaded')
: decodedImage,
),
],
),
),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
// crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
onPressed: () {
// _getImage();
_openGallery(context);
print('Open Gallery');
},
tooltip: 'Pick an image',
child: Icon(Icons.image),
),
SizedBox(
width: 20,
),
],
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Since the decoded image is the same as the original image, I think var bytes = imageFile.readAsBytesSync(); is working fine.

Related

Select-DeSelect Buttons in Flutter

I want to create below tab like rounded buttons named Vehicle & Key in flutter which is selectable and de-selectable. I can use Tab but its part of scaffold. Is there any other way to achieve as below?
You can use the toggle_switch 2.0.1 (https://pub.dev/packages/toggle_switch) package which is in Flutter favorite program.
Its simple to use : -
ToggleSwitch(
minWidth: 200.0,
minHeight: 55.0,
cornerRadius: 35.0,
activeBgColors: const [
[Color.fromARGB(255, 52, 26, 94)],
[Color.fromARGB(255, 52, 26, 94)]
],
borderColor: const [Color.fromARGB(255, 154, 207, 251)],
borderWidth: 0.7,
inactiveBgColor: Colors.white,
inactiveFgColor: const Color.fromARGB(255, 52, 26, 94),
initialLabelIndex: 0,
totalSwitches: 2,
labels: const ['Vechile', 'Key'],
radiusStyle: true,
onToggle: (index) {},
),
Complete Code : -
import 'package:flutter/material.dart';
import 'package:toggle_switch/toggle_switch.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: _title,
home: ToggleSwitchButton(),
);
}
}
class ToggleSwitchButton extends StatefulWidget {
const ToggleSwitchButton({Key? key}) : super(key: key);
#override
_ToggleSwitchButtonState createState() => _ToggleSwitchButtonState();
}
class _ToggleSwitchButtonState extends State<ToggleSwitchButton> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Center(
child: ToggleSwitch(
minWidth: 200.0,
minHeight: 55.0,
cornerRadius: 35.0,
activeBgColors: const [
[Color.fromARGB(255, 52, 26, 94)],
[Color.fromARGB(255, 52, 26, 94)]
],
borderColor: const [Color.fromARGB(255, 154, 207, 251)],
borderWidth: 0.7,
inactiveBgColor: Colors.white,
inactiveFgColor: const Color.fromARGB(255, 52, 26, 94),
initialLabelIndex: 0,
totalSwitches: 2,
labels: const ['Vechile', 'Key'],
radiusStyle: true,
onToggle: (index) {},
),
)),
);
}
}
Output : -
You can create two widgets simultaneously and then provide them a flag for visibility :
Column(
children: [
Row(
children: [
ElevatedButton(
onPressed: (() => flag=true),
child: Text("Vehicle"),),
ElevatedButton(
onPressed: (() => flag=false),
child: Text("Vehicle"),),
]),
flag ? Child1 : Child2,
],
),
This can help you create two buttons which onPressing will change your flag which in turn will change the content you are providing on the screen.

How to create two dynamic SfCartesianChart in Flutter?

I am trying to create multiple dynamic charts (SfCartesianChart from syncfusion), the data is extracted every 1 second from a dynamic json file.
I tried to create two charts; the first one works fine but the second one remains the same , it does not change.
This is what I am getting.
Here is my code
import 'dart:ui';
import 'dart:async';
import 'package:syncfusion_flutter_gauges/gauges.dart';
import 'package:flutter/material.dart';
import 'package:applicationv1/constants.dart';
import 'package:http/http.dart' as http;
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:applicationv1/classDonnee.dart';
import 'dart:convert';
Future<Donnee> fetchDonnee() async {
print('fetch0');
final response = await http.get(Uri.parse('uri'));
if (response.statusCode == 200) {
print('fecth1');
// If the server did return a 200 OK response, then parse the JSON.
return Donnee.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response, then throw an exception.
throw Exception('Failed to load album');
}
}
class depart1 extends StatefulWidget{
const depart1({Key? key}) : super(key: key);
#override
_depart1State createState() => _depart1State();
}
class _depart1State extends State<depart1> with SingleTickerProviderStateMixin{
late List<LiveData> chartData;
late List<LiveData2> chartData2;
ChartSeriesController? _chartSeriesController;
ChartSeriesController? _chartSeriesController2;
late Future<Donnee> futureDonnee;
Timer? timer;
#override
void initState() {
print('initstate');
futureDonnee=fetchDonnee();
chartData = getChartData();
chartData2 = getChartData2();
//super.initState();
timer= Timer.periodic(const Duration(seconds:1), (Timer t){
futureDonnee=fetchDonnee();
setState(() {
});
print('initstate1');
});
super.initState();
}
#override
Widget build(BuildContext context){
Size size = MediaQuery.of(context).size;
FutureBuilder f1;
//TabController _tabController;
print('build');
Center(child: f1=FutureBuilder<Donnee>(
future: futureDonnee,
builder: (context, snapshot) {
if (snapshot.hasData){
updateDataSource(snapshot.data!.w1);
updateDataSource2(snapshot.data!.va1)
return Center(
child:SingleChildScrollView(
child: Column(
children: <Widget>[
//chart 1
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white
),
margin: const EdgeInsets.fromLTRB(20,10,20,0),
padding: EdgeInsets.fromLTRB(2, 7, 2, 7),
//color: Colors.white,
child: Column(
children:[
Text('puissance Active de phase 1 (W)'),
SizedBox(height: 5,),
SfCartesianChart(
series: <LineSeries<LiveData, int>>[
LineSeries<LiveData, int>(
onRendererCreated: (ChartSeriesController controller) {
_chartSeriesController = controller;
},
dataSource: chartData,
color: Colors.blue,
xValueMapper: (LiveData sales, _) => sales.time,
yValueMapper: (LiveData sales, _) => sales.speed,
dataLabelSettings: DataLabelSettings(isVisible: true)
)
],
primaryXAxis: NumericAxis(
majorGridLines: const MajorGridLines(width: 0),
edgeLabelPlacement: EdgeLabelPlacement.shift,
interval: 3,
title: AxisTitle(text: 'Temps (secondes)')),
primaryYAxis: NumericAxis(
axisLine: const AxisLine(width: 0),
majorTickLines: const MajorTickLines(size: 0),
//title: AxisTitle(text: 'puissance Active de pahse 1 (W)')
)
),]
),),
////////////////////chart2
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white
),
margin: const EdgeInsets.fromLTRB(20,10,20,0),
padding: EdgeInsets.fromLTRB(2, 7, 2, 7),
child: Column(
children:[
Text('puissance Apparente de phase 1 (VA)'),
SizedBox(height: 5,),
SfCartesianChart(
series: <LineSeries<LiveData2, int>>[
LineSeries<LiveData2, int>(
onRendererCreated: (ChartSeriesController controller2) {
_chartSeriesController2 = controller2;
},
dataSource: chartData2,
color: Colors.yellow,
xValueMapper: (LiveData2 sales, _) => sales.time,
yValueMapper: (LiveData2 sales, _) => sales.speed,
dataLabelSettings: DataLabelSettings(isVisible: true)
)
],
primaryXAxis: NumericAxis(
majorGridLines: const MajorGridLines(width: 0),
edgeLabelPlacement: EdgeLabelPlacement.shift,
interval: 3,
title: AxisTitle(text: 'Temps (secondes)')),
primaryYAxis: NumericAxis(
axisLine: const AxisLine(width: 0),
majorTickLines: const MajorTickLines(size: 0),
//title: AxisTitle(text: 'puissance Active de pahse 1 (W)')
)
),]
),),
],
),
)
);
//);
}
else if (snapshot.hasError) {
//return const Text('Please wait');
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return Container(
height: 20,
width:20,
child: const CircularProgressIndicator());
},
)
);
return f1;
}
int time = 19;
void updateDataSource(String val) {
ChartSeriesController controller;
var snapshot;
chartData.add(LiveData(time++, double.parse(val)));
//math.Random().nextInt(60) + 30
chartData.removeAt(0);
_chartSeriesController?.updateDataSource(
addedDataIndex: chartData.length - 1, removedDataIndex: 0);
print('update chart');
}
List<LiveData> getChartData() {
return <LiveData>[
LiveData(0, 0),
LiveData(1, 0),
LiveData(2, 0),
LiveData(3, 0),
LiveData(4, 0),
LiveData(5, 0),
LiveData(6, 0),
LiveData(7, 0),
LiveData(8, 0),
LiveData(9, 0),
LiveData(10, 0),
LiveData(11, 0),
LiveData(12, 0),
LiveData(13, 0),
LiveData(14, 0),
LiveData(15, 0),
LiveData(16, 0),
LiveData(17, 0),
LiveData(18, 0)
];
}
//coube2
int time2 = 19;
void updateDataSource2(String val) {
ChartSeriesController controller2;
var snapshot;
chartData2.add(LiveData2(time2++, double.parse(val)));
chartData2.removeAt(0);
_chartSeriesController2?.updateDataSource(
addedDataIndex: chartData2.length - 1, removedDataIndex: 0);
print('update chart2');
}
List<LiveData2> getChartData2() {
return <LiveData2>[
LiveData2(0, 0),
LiveData2(1, 0),
LiveData2(2, 0),
LiveData2(3, 0),
LiveData2(4, 0),
LiveData2(5, 0),
LiveData2(6, 0),
LiveData2(7, 0),
LiveData2(8, 0),
LiveData2(9, 0),
LiveData2(10, 0),
LiveData2(11, 0),
LiveData2(12, 0),
LiveData2(13, 0),
LiveData2(14, 0),
LiveData2(15, 0),
LiveData2(16, 0),
LiveData2(17, 0),
LiveData2(18, 0)
];
}
}
class LiveData {
LiveData(this.time, this.speed);
final int time;
final num speed;
}
class LiveData2 {
LiveData2(this.time, this.speed);
final int time;
final num speed;
}
Any help is much appreciated
I tried to replicate your scenario with the provided code, but both the charts are not updating with your code. Instead of JSON data, we created data dynamically. And we found that, in the timer, you have called the setstate, and in the builder, you have called the updateDataSource method. You have processed setstate and updateDataSource simultaneously. If you comment on the updateDataaSource method, due to the setstate method you have called, the chart is getting updated. But for live update cases, we suggest using the updateDataSource method. In the timer, you can call the updateDataSource method, so that chart will get updated properly. And we are not sure why you have used both methods simultaneously. As of now, we have modified your code snippet by updating the random data at each time by calling the updateDataSource method and ensured that it updates the data properly and attached it below. You can modify the sample as per your requirement.
Code snippet:
import 'dart:math';
import 'dart:ui';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:syncfusion_flutter_charts/charts.dart';
import 'dart:convert';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const Depart1(),
);
}
}
class Depart1 extends StatefulWidget {
const Depart1({Key? key}) : super(key: key);
#override
_Depart1State createState() => _Depart1State();
}
class _Depart1State extends State<Depart1> with SingleTickerProviderStateMixin {
late List<LiveData> chartData;
late List<LiveData2> chartData2;
ChartSeriesController? _chartSeriesController;
ChartSeriesController? _chartSeriesController2;
Timer? timer;
#override
void initState() {
chartData = getChartData();
chartData2 = getChartData2();
timer = Timer.periodic(const Duration(seconds: 1), (Timer t) {
updateDataSource('val');
updateDataSource2('val');
});
super.initState();
}
Future<String> getJsonData() async {
return await rootBundle.loadString('assets/data.json');
}
Future loadData() async {
String response = await getJsonData();
final dynamic responseData = json.decode(response);}
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
FutureBuilder f1;
Center(
child: f1 = FutureBuilder(
future: getJsonData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Center(
child: SingleChildScrollView(
child: Column(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white),
margin: const EdgeInsets.fromLTRB(20, 10, 20, 0),
padding: EdgeInsets.fromLTRB(2, 7, 2, 7),
child: Column(children: [
Text('puissance Active de phase 1 (W)'),
SizedBox(
height: 5,
),
SfCartesianChart(
series: <LineSeries<LiveData, DateTime>>[
LineSeries<LiveData, DateTime>(
onRendererCreated:
(ChartSeriesController controller) {
_chartSeriesController = controller;
},
dataSource: chartData,
color: Colors.blue,
xValueMapper: (LiveData sales, _) => sales.time,
yValueMapper: (LiveData sales, _) => sales.speed,
dataLabelSettings:
DataLabelSettings(isVisible: true))
],
primaryXAxis: DateTimeAxis(
majorGridLines: const MajorGridLines(width: 0),
edgeLabelPlacement: EdgeLabelPlacement.shift,
interval: 3,
title: AxisTitle(text: 'Temps (secondes)')),
primaryYAxis: NumericAxis(
axisLine: const AxisLine(width: 0),
majorTickLines: const MajorTickLines(size: 0),
)),
]),
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white),
margin: const EdgeInsets.fromLTRB(20, 10, 20, 0),
padding: EdgeInsets.fromLTRB(2, 7, 2, 7),
child: Column(children: [
Text('puissance Apparente de phase 1 (VA)'),
SizedBox(
height: 5,
),
SfCartesianChart(
series: <LineSeries<LiveData2, DateTime>>[
LineSeries<LiveData2, DateTime>(
onRendererCreated:
(ChartSeriesController controller2) {
_chartSeriesController2 = controller2;
},
dataSource: chartData2,
color: Colors.yellow,
xValueMapper: (LiveData2 sales, _) => sales.time,
yValueMapper: (LiveData2 sales, _) => sales.speed,
dataLabelSettings:
DataLabelSettings(isVisible: true))
],
primaryXAxis: DateTimeAxis(
majorGridLines: const MajorGridLines(width: 0),
edgeLabelPlacement: EdgeLabelPlacement.shift,
interval: 3,
title: AxisTitle(text: 'Temps (secondes)')),
primaryYAxis: NumericAxis(
axisLine: const AxisLine(width: 0),
majorTickLines: const MajorTickLines(size: 0),
)),
]),
),
],
),
));
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return Container(
height: 20, width: 20, child: const CircularProgressIndicator());
},
));
return Scaffold(appBar: AppBar(), body: f1);
}
int time = 19;
void updateDataSource(String val) {
ChartSeriesController controller;
var snapshot;
chartData.add(LiveData(chartData2.last.time.add(const Duration(days: 1)),
_getRandomInt(10, 100)));
chartData.removeAt(0);
_chartSeriesController?.updateDataSource(
addedDataIndex: chartData.length - 1, removedDataIndex: 0);
print('update chart');
}
List<LiveData> getChartData() {
return <LiveData>[
LiveData(DateTime(2022, 01, 00), 0),
LiveData(DateTime(2022, 01, 01), 0),
LiveData(DateTime(2022, 01, 02), 0),
LiveData(DateTime(2022, 01, 03), 0),
LiveData(DateTime(2022, 01, 04), 0),
LiveData(DateTime(2022, 01, 05), 0),
LiveData(DateTime(2022, 01, 06), 0),
LiveData(DateTime(2022, 01, 07), 0),
LiveData(DateTime(2022, 01, 08), 0),
LiveData(DateTime(2022, 01, 09), 0),
LiveData(DateTime(2022, 01, 10), 0),
LiveData(DateTime(2022, 01, 11), 0),
LiveData(DateTime(2022, 01, 12), 0),
LiveData(DateTime(2022, 01, 13), 0),
LiveData(DateTime(2022, 01, 14), 0),
LiveData(DateTime(2022, 01, 15), 0),
LiveData(DateTime(2022, 01, 16), 0),
LiveData(DateTime(2022, 01, 17), 0),
LiveData(DateTime(2022, 01, 18), 0)
];
}
int time2 = 19;
void updateDataSource2(String val) {
ChartSeriesController controller2;
var snapshot;
chartData2.add(LiveData2(chartData2.last.time.add(const Duration(days: 1)),
_getRandomInt(10, 100)));
chartData2.removeAt(0);
_chartSeriesController2?.updateDataSource(
addedDataIndex: chartData2.length - 1, removedDataIndex: 0);
}
List<LiveData2> getChartData2() {
return <LiveData2>[
LiveData2(DateTime(2022, 01, 31), 0),
LiveData2(DateTime(2022, 01, 01), 0),
LiveData2(DateTime(2022, 01, 02), 0),
LiveData2(DateTime(2022, 01, 03), 0),
LiveData2(DateTime(2022, 01, 04), 0),
LiveData2(DateTime(2022, 01, 05), 0),
LiveData2(DateTime(2022, 01, 06), 0),
LiveData2(DateTime(2022, 01, 07), 0),
LiveData2(DateTime(2022, 01, 08), 0),
LiveData2(DateTime(2022, 01, 09), 0),
LiveData2(DateTime(2022, 01, 10), 0),
LiveData2(DateTime(2022, 01, 11), 0),
LiveData2(DateTime(2022, 01, 12), 0),
LiveData2(DateTime(2022, 01, 13), 0),
LiveData2(DateTime(2022, 01, 14), 0),
LiveData2(DateTime(2022, 01, 15), 0),
LiveData2(DateTime(2022, 01, 16), 0),
LiveData2(DateTime(2022, 01, 17), 0),
LiveData2(DateTime(2022, 01, 18), 0)
];
}
int _getRandomInt(int min, int max) {
return Random().nextInt(max - min);
}
}
class LiveData {
LiveData(this.time, this.speed);
final DateTime time;
final num speed;
}
class LiveData2 {
LiveData2(this.time, this.speed);
final DateTime time;
final num speed;
}

How do I change the Icon color when tapped or swiped and move between pages by tapping the icon or swiping the screen in Flutter?

I want my navbar can change color when tapped or by swiping the screens and also move between pages.
Here is the code
import 'package:flutter/material.dart';
import 'package:project_ukk/constants/color_constant.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class PageNavBar extends StatefulWidget {
const PageNavBar({Key? key}) : super(key: key);
#override
State<PageNavBar> createState() => _PageNavBarState();
}
class BNBCustomPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = kWhiteColor
..style = PaintingStyle.fill;
Path path = Path()..moveTo(0, 20);
path.quadraticBezierTo(size.width * 0.20, 0, size.width * 0.35, 0);
path.quadraticBezierTo(size.width * 0.40, 0, size.width * 0.40, 20);
path.arcToPoint(Offset(size.width * 0.60, 20),
radius: const Radius.circular(10.0), clockwise: false);
path.quadraticBezierTo(size.width * 0.60, 0, size.width * 0.65, 0);
path.quadraticBezierTo(size.width * 0.80, 0, size.width, 20);
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
path.close();
canvas.drawShadow(path, kBlackColor, 5, true);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}
class _PageNavBarState extends State<PageNavBar> {
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
backgroundColor: kDarkGreyColor,
body: Stack(
children: [
Positioned(
bottom: 0,
left: 0,
child: SizedBox(
width: size.width,
height: 80,
child: Stack(
children: [
CustomPaint(
size: Size(size.width, 80),
painter: BNBCustomPainter(),
),
Center(
heightFactor: 0.6,
child: FloatingActionButton(
onPressed: () {
print('add button pressed');
},
backgroundColor: kLightRedColor,
child: const FaIcon(
FontAwesomeIcons.plus,
color: kWhiteColor,
),
elevation: 0.1,
),
),
SizedBox(
width: size.width,
height: 80,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
icon: const Icon(Icons.home),
onPressed: () {},
),
IconButton(
icon: const FaIcon(FontAwesomeIcons.gavel),
onPressed: () {},
),
Container(
width: size.width * 0.20,
),
IconButton(
icon: const Icon(Icons.collections),
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.person),
onPressed: () {},
),
],
),
),
],
),
),
),
],
),
);
}
}
For the color, you can use any color, or you can use mine
import 'package:flutter/material.dart';
const kPrimaryColor = Color(0xFF1B383A);
const kSecondaryColor = Color(0xFF59706F);
const kDarkGreyColor = Color(0xFFA8A8A8);
const kWhiteColor = Color(0xFFFFFFFF);
const kZambeziColor = Color(0xFF5B5B5B);
const kBlackColor = Color(0xFF272726);
const kTextFieldColor = Color(0xFF979797);
const kVeryDarkCyan = Color.fromRGBO(7, 34, 39, 1);
const kDarkModerateCyan = Color.fromRGBO(53, 133, 139, 1);
const kModerateCyan = Color.fromRGBO(79, 189, 186, 1);
const kPowderBlue = Color.fromRGBO(176, 224, 230, 1);
const kDarkBlue = Color.fromRGBO(34, 87, 122, 1);
const kModerateCyanLimeGreen = Color.fromRGBO(87, 204, 153, 1);
const kSoftLimeGreen = Color.fromRGBO(128, 237, 153, 1);
const kRedColor = Color.fromRGBO(218, 18, 18, 1);
const kLightRedColor = Color.fromRGBO(255, 99, 99, 1);
const kLightOrange = Color.fromRGBO(255, 173, 96, 1);
You need to pass color in your BNBCustomPainter.
class BNBCustomPainter extends CustomPainter {
final Color color;
BNBCustomPainter({required this.color});
#override
void paint(Canvas canvas, Size size) {
Paint paint = Paint()
..color = color
Now an int is needed to keep track the selected index;
class _PageNavBarState extends State<PageNavBar> {
int selectedIndex = 0;
Color navBarColor() {
switch (selectedIndex) {
case 0:
return Colors.amber;
case 1:
return Colors.pink;
///number of tabs
default:
return kWhiteColor;
}
}
And painter will be
painter: BNBCustomPainter(color: navBarColor()),
Also, you can use Color navBarColor = kWhiteColor; and change on tap changes.
Lastly, change the selectedIndex on every IconButton
IconButton(
icon: const Icon(Icons.home),
onPressed: () {
setState(() {
selectedIndex = 0; /// index number
});
},
),

File does not get converted to base64 string properly

So I have written some code to capture an image from the user using the better_camera package and then store it in a file. Then I convert it to base64 string for further use. It seems like the image is getting saved properly since Image.file shows the image. But when I convert the image to base64string, it gives the image of a small white screen. I do not know where the problem is coming. Can someone check?
CODE
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_better_camera/camera.dart';
import 'package:frappe/flutter_flow/flutter_flow_theme.dart';
import 'package:path_provider/path_provider.dart';
class AddNewCameraItem extends StatefulWidget {
const AddNewCameraItem({Key key}) : super(key: key);
#override
_AddNewCameraItemState createState() => _AddNewCameraItemState();
}
class _AddNewCameraItemState extends State<AddNewCameraItem> {
CameraController controller;
#override
void initState() {
super.initState();
initCam();
}
void initCam() async {
List<CameraDescription> cameras = await availableCameras();
controller = CameraController(cameras[0], ResolutionPreset.max);
controller.initialize().then((_) {
controller.setFlashMode(FlashMode.off);
if (!mounted) {
return;
}
setState(() {});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: FlutterFlowTheme.secondaryColor,
automaticallyImplyLeading: true,
centerTitle: true,
title: Text(
'ADD NEW ITEMS',
style: FlutterFlowTheme.bodyText1.override(
fontFamily: 'Noto Serif',
color: Color(0xFFFAFAFA),
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
elevation: 4,
),
body: !controller.value.isInitialized
? Container()
// : Image.file(File(
// '/data/user/0/com.flutterflow.frappe/cache/lkpbpyigaqpjsh6iygy8dA4dsFDG9CAcVD7DueDLtd3C3JqzmmRuZcKaFFmAt88Ryyp208CzlE1oYfkJKnvwErBFv3DkO0dSYLZApETWDnsGOur728R7WgoUQ1EEOv9ilz1jAeNLotSsYFaI13Jk9wp5mmGdqhmRx6LYSCfHQHAdalrMCtniqrU3Sqhaw1iJZfeuUsJy.jpg')),
: MaterialApp(
home: CameraPreview(controller),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
try {
Directory tempDir = await getTemporaryDirectory();
String randomName =
tempDir.path + '/' + getRandomString(200) + '.jpg';
// await controller.takePicture(randomName);
File file = File(
'/data/user/0/com.flutterflow.frappe/cache/IfXsEjNsSifPiQJ0d628j2d1HRh2Ww2Flin3urZc4d59WYeZ9DQ8mjpLdrt2jwzBjn2vxqvnkzRd4AGowI6fKCGRNWOfei7B2KufbpOG0RsNH7mobwGa7KS7q1C6ALoNIVJ13XLqpa7BX7pIQSgLobe5lW6z7P01QBms3CVrM9omeEvIZxRwxL5s555HLOGN4Te9Bta2.jpg');
Uint8List list = await file.readAsBytes();
print(list);
print(base64Encode(list.toList()));
print("Random n: " + randomName);
// print(base64Encode((await xfile.readAsBytes()).toList()));
} catch (e) {
print("Error: " + e.toString());
}
},
child: Center(
child: Icon(Icons.camera_alt, color: FlutterFlowTheme.tertiaryColor),
),
),
);
}
String getRandomString(int length) {
String _chars =
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
Random _rnd = Random();
return String.fromCharCodes(Iterable.generate(
length, (_) => _chars.codeUnitAt(_rnd.nextInt(_chars.length))));
}
}
BASE64OUTPUT
/9j/4QurRXhpZgAATU0AKgAAAAgACwEPAAIAAAAHAAAAkgEQAAIAAAARAAAAmgESAAMAAAABAAYAAAEaAAUAAAABAAAArAEbAAUAAAABAAAAtAEoAAMAAAABAAIAAAExAAIAAAA9AAAAvAEyAAIAAAAUAAAA+gITAAMAAAABAAEAAIdpAAQAAAABAAABDoglAAQAAAABAAAC8gAAAvhYaWFvbWkAAFJlZG1pIE5vdGUgNSBQcm8AAAAAAEgAAAABAAAASAAAAAF3aHlyZWQtdXNlciA5IFBLUTEuMTgwOTA0LjAwMSBWMTEuMC41LjAuUEVJTUlYTSByZWxlYXNlLWtleXMAADIwMjE6MDg6MTggMTk6MTY6MTkAAByCmgAFAAAAAQAAAmSCnQAFAAAAAQAAAmyIIgADAAAAAQAAAACIJwADAAAAAQJDAACQAAAHAAAABDAyMjCQAwACAAAAFAAAAnSQBAACAAAAFAAAAoiRAQAHAAAABAECAwCSAQAKAAAAAQAAApySAgAFAAAAAQAAAqSSAwAKAAAAAQAAAqySBwADAAAAAQABAACSCQADAAAAAQAQAACSCgAFAAAAAQAAArSSkAACAAAABwAAArySkQACAAAABwAAAsSSkgACAAAABwAAAsygAAAHAAAABDAxMDCgAQADAAAAAQABAACgAgAEAAAAAQAABpCgAwAEAAAAAQAABOigBQAEAAAAAQAAAtOiFwADAAAAAQACAACjAQAHAAAAAQEAAACkAgADAAAAAQAAAACkAwADAAAAAQAAAACkBQADAAAAAQAEAACkBgADAAAAAQAAAAAAAAAAAAAAAQAAAB4AAADcAAAAZDIwMjE6MDg6MTggMTk6MTY6MTkAMjAyMTowODoxOCAxOToxNjoxOQAAABMqAAAD6AAAAOMAAABkAAAAAAAAAGQAAA7iAAAD6Dk1NTM0OQBzOTU1MzQ5AAA5NTUzNDkAAAIAAQACAAAABFI5OAAAAgAHAAAABDAxMDAAAAAAAAA
UINT8LIST
[255, 216, 255, 225, 11, 171, 69, 120, 105, 102, 0, 0, 77, 77, 0, 42, 0, 0, 0, 8, 0, 11, 1, 15, 0, 2, 0, 0, 0, 7, 0, 0, 0, 146, 1, 16, 0, 2, 0, 0, 0, 17, 0, 0, 0, 154, 1, 18, 0, 3, 0, 0, 0, 1, 0, 6, 0, 0, 1, 26, 0, 5, 0, 0, 0, 1, 0, 0, 0, 172, 1, 27, 0, 5, 0, 0, 0, 1, 0, 0, 0, 180, 1, 40, 0, 3, 0, 0, 0, 1, 0, 2, 0, 0, 1, 49, 0, 2, 0, 0, 0, 61, 0, 0, 0, 188, 1, 50, 0, 2, 0, 0, 0, 20, 0, 0, 0, 250, 2, 19, 0, 3, 0, 0, 0, 1, 0, 1, 0, 0, 135, 105, 0, 4, 0, 0, 0, 1, 0, 0, 1, 14, 136, 37, 0, 4, 0, 0, 0, 1, 0, 0, 2, 242, 0, 0, 2, 248, 88, 105, 97, 111, 109, 105, 0, 0, 82, 101, 100, 109, 105, 32, 78, 111, 116, 101, 32, 53, 32, 80, 114, 111, 0, 0, 0, 0, 0, 72, 0, 0, 0, 1, 0, 0, 0, 72, 0, 0, 0, 1, 119, 104, 121, 114, 101, 100, 45, 117, 115, 101, 114, 32, 57, 32, 80, 75, 81, 49, 46, 49, 56, 48, 57, 48, 52, 46, 48, 48, 49, 32, 86, 49, 49, 46, 48, 46, 53, 46, 48, 46, 80, 69, 73, 77, 73, 88, 77, 32, 114, 101, 108, 101, 97, 115, 101, 45, 107, 101, 121, 115, 0, 0, 50, 48, 50, 49, 58, 48, 56, 58, 49, 56, 32, 49, 57, 58, 49, 5
You have to decode before using the Base64 string
String encoded = stringToBase64.encode(credentials);
String decoded = stringToBase64.decode(encoded);

Is it possible to make a double stack chart in ECharts

The ECharts provide stack option to stack multiple area/line charts together.
https://echarts.apache.org/en/option.html#series-line.stack
I have three charts that look like this:
To achieve it you can paste the following code here: https://echarts.apache.org/examples/en/editor.html?c=area-stack
option = {
title: {
text: 'Double stack',
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985',
},
},
},
legend: {
data: ['stack 1', 'stack 2', 'basis'],
},
toolbox: {
feature: {
saveAsImage: {},
},
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['0', '1', '2', '3', '4', '5', '6'],
},
],
yAxis: [
{
type: 'value',
},
],
series: [
{
name: 'stack 1',
type: 'line',
areaStyle: {
color: 'red',
},
data: [140, 150, 160, 180, 160, 240, 160],
},
{
name: 'stack 2',
type: 'line',
areaStyle: {
color: 'green',
},
data: [120, 140, 130, 150, 120, 160, 125],
},
{
name: 'basis',
type: 'line',
areaStyle: {
color: 'blue',
},
data: [100, 110, 120, 130, 90, 130, 120],
},
],
};
However I would like to stack both the green and the red charts on the blue one to get something like this:
I can add the values of the blue one to both other charts and get the result and get the following options:
option = {
title: {
text: 'Double stack',
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985',
},
},
},
legend: {
data: ['stack 1', 'stack 2', 'basis'],
},
toolbox: {
feature: {
saveAsImage: {},
},
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['0', '1', '2', '3', '4', '5', '6'],
},
],
yAxis: [
{
type: 'value',
},
],
series: [
{
name: 'stack 1',
type: 'line',
areaStyle: {
color: 'red',
},
data: [140 + 100, 150 + 110, 160 + 120, 180 + 130, 160 + 90, 240 + 130, 160 + 120],
},
{
name: 'stack 2',
type: 'line',
areaStyle: {
color: 'green',
},
data: [120 + 100, 140 + 110, 130 + 120, 150 + 130, 120 + 90, 160 + 130, 125 + 120],
},
{
name: 'basis',
type: 'line',
areaStyle: {
color: 'blue',
},
data: [100, 110, 120, 130, 90, 130, 120],
},
],
};
but this way I will loose the interactive functionalities of ECharts.
Is there a possible way to do this? To stack the red and the green chart on the blue one but not on each other?
You need to do the same all series' names like this.
series: [
{
name: 'stack',
type: 'line',
areaStyle: {
color: 'red',
},
data: [140, 150, 160, 180, 160, 240, 160],
},
{
name: 'stack',
type: 'line',
areaStyle: {
color: 'green',
},
data: [120, 140, 130, 150, 120, 160, 125],
},
{
name: 'stack',
type: 'line',
areaStyle: {
color: 'blue',
},
data: [100, 110, 120, 130, 90, 130, 120],
},
],
and also, you can modify the tooltip with this
I hope, it will be helpful for you.
I found a simple solution for this by duplicating the basis graph with the very same data and colors, so the user doesn't see two graphs, then stack the red graph on one example of blue, and the green one on the other copy of the blue one like this:
option = {
legend: {
data: ['blue', 'red', 'green'],
},
xAxis: [
{
boundaryGap: false,
data: ['0', '1', '2', '3', '4', '5', '6'],
},
],
yAxis: [
{
type: 'value',
},
],
series: [
{
name: 'blue',
stack: 'stack 1',
type: 'line',
areaStyle: {
color: 'blue',
},
data: [100, 110, 120, 130, 90, 130, 120],
},
{
name: 'blue',
stack: 'stack 2',
type: 'line',
areaStyle: {
color: 'blue',
},
data: [100, 110, 120, 130, 90, 130, 120],
},
{
name: 'red',
stack: 'stack 1',
type: 'line',
areaStyle: {
color: 'red',
},
data: [140, 150, 160, 180, 160, 240, 160],
},
{
name: 'green',
stack: 'stack 2',
type: 'line',
areaStyle: {
color: 'green',
},
data: [120, 140, 130, 150, 120, 160, 125],
},
],
};
This will insure that both copies of the blue graph (standing as basis for both red and green one) will be disabled/enabled together since they have the same name, and each one of the the red and green graphs is stacked on a different blue copy.