Related
I have the following code that is passing an object as an Argument to another screen using Push named:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_nsd/flutter_nsd.dart';
import 'package:australremote/screens/screen5.dart';
import 'package:australremote/screens/screen6.dart';
void main() {
runApp(const Screen1());
}
class Screen1 extends StatefulWidget {
const Screen1({Key? key}) : super(key: key);
#override
State createState() => _Screen1State();
}
class _Screen1State extends State<Screen1> {
final flutterNsd = FlutterNsd();
final services = <NsdServiceInfo>[];
bool initialStart = true;
bool _scanning = false;
//List<String> _deviceIPAddresses = [];
_Screen1State();
#override
void initState() {
super.initState();
// Try one restart if initial start fails, which happens on hot-restart of
// the flutter app.
flutterNsd.stream.listen(
(NsdServiceInfo service) {
setState(() {
services.add(service);
});
},
onError: (e) async {
if (e is NsdError) {
if (e.errorCode == NsdErrorCode.startDiscoveryFailed &&
initialStart) {
await stopDiscovery();
} else if (e.errorCode == NsdErrorCode.discoveryStopped &&
initialStart) {
initialStart = false;
await startDiscovery();
}
}
},
);
startDiscovery();
}
Future<void> startDiscovery() async {
if (_scanning) return;
setState(() {
services.clear();
_scanning = true;
});
await flutterNsd.discoverServices('_http._tcp.');
/*List<InternetAddress> addresses = await services.resolve();
setState(() {
_deviceIPAddresses.add(addresses[0].address);
});*/
}
Future<void> stopDiscovery() async {
if (!_scanning) return;
setState(() {
services.clear();
_scanning = false;
});
flutterNsd.stopDiscovery();
}
#override
Widget build(BuildContext context) {
//return MaterialApp(
return Scaffold(
appBar: AppBar(
title: const Text('Your devices',style: TextStyle(color: Colors.black87),),
titleSpacing: 00.0,
centerTitle: true,
toolbarHeight: 60.2,
toolbarOpacity: 0.6,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(25),
bottomLeft: Radius.circular(25)),
),
elevation: 0.00,
backgroundColor: Colors.transparent,
),
body:
Column(
children: <Widget>[
Expanded(
child: _buildMainWidget(context),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
SafeArea(
child: IconButton(
iconSize: 32.0,
icon: const Icon(Icons.add),
tooltip: 'Add a new device',
onPressed: () {
// Navigate to the second screen using a named route.
Navigator.pushNamed(context, '/second');
},
),
),
],
),
],
),
);
// );
}
Widget _buildMainWidget(BuildContext context) {
if (services.isEmpty && _scanning) {
return const Center(
child: CircularProgressIndicator(),
);
} else if (services.isEmpty && !_scanning) {
return const SizedBox.shrink();
} else {
print(services);
return ListView.builder(
itemBuilder: (context, index) => ListTile(
leading: Icon(
Icons.speaker,
color: Colors.grey[500],
),
title: Text(services[index].name ?? 'Invalid service name',textAlign: TextAlign.left,style: TextStyle(color: Colors.black,fontWeight: FontWeight.w500,
fontSize: 20,)
),
subtitle: Text(services[index].hostname ?? 'Invalid service name',textAlign: TextAlign.left,style: TextStyle(color: Colors.grey,fontWeight: FontWeight.w500,
fontSize: 10,)
),
trailing: Icon(
Icons.arrow_forward_ios,
),
onTap: ()
{
Navigator.of(context).pushNamed(
'/sixth',
arguments:services,
);
},
),
itemCount: services.length,
);
}
}
}
Second screen:
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import 'package:australremote/screens/screen1.dart';
import 'package:convert/convert.dart';
void main() {
runApp(MyHomePage6());
}
class MyHomePage6 extends StatefulWidget {
const MyHomePage6({Key? key}) : super(key: key);
#override
_MyHomePage6State createState() => _MyHomePage6State();
}
class _MyHomePage6State extends State<MyHomePage6> {
// final String args = "";
#override
Widget build(BuildContext context) {
//final services args = ModalRoute.of(context)?.settings?.arguments;
//String hostname = args[0];
final args = ModalRoute.of(context)?.settings?.arguments as List<String>;
final String services = '';
final int index;
final String hostname ='';
final String service = '';
return Scaffold(
appBar: AppBar(
title: const Text('Connect your DAC to your network',
style: TextStyle(color: Colors.black87)),
titleSpacing: 00.0,
centerTitle: true,
toolbarHeight: 60.2,
toolbarOpacity: 0.6,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(25),
bottomLeft: Radius.circular(25)),
),
elevation: 0.00,
backgroundColor: Colors.transparent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(service),
//Text("Your name is :$name"),
/*SizedBox(height: 20),
Text("HEX value: $_hexValue"),
SizedBox(height: 20),
Text("API response: $_apiResponse"),
SizedBox(height: 20),
Text("SSID Hex: $_ssidHexValue"),*/
SizedBox(height: 20),
TextButton(
onPressed:() async{
// Send an API request with the HEX value
var response = await http.get(Uri.parse(
"http://10.10.10.254/httpapi.asp?command=getStatusEx"),);
if (response.statusCode == 200) {
print(response);
// Navigator.pushNamed(context, '/');
} else {
print("There is something wrong here");
}
},
child: Text("Next", style: TextStyle(color: Colors.grey)),
),
],
),
),
);
}
}
I tried to define the getters, but I'm not quite sure I can extract the content from the arguments I've sent from the previous screen.Also, I'm receiving the following error:
type 'List' is not a subtype of type 'List' in type cast
Problem:
At first screen you defined services with generic NsdServiceInfo like:
final services = <NsdServiceInfo>[];
but on second screen , at modalRoute you used String as generic like:
final args = ModalRoute.of(context)?.settings?.arguments as List<String>;
Solution:
so make String to NsdServiceInfo in route arg defining variable like:
final args = ModalRoute.of(context)?.settings?.arguments as List<NsdServiceInfo>;
I have a navigation menu that I made for a test application, there are some tabs that I want to hide if I am not logged into the application. After logging in, these tabs should appear. The problem is that after logging in, I go to the desired page and I don't see all the navigation menu icons. For them to appear, I need to click on one of the available icons (only 2 icons are available for authorization) and only then the navigation menu will be updated and everything will be as it should be. All 6 icons will be visible! Can someone help me with this? Here I described the problem with the code that I am using. I would be grateful for any help.
import 'package:flutter/material.dart';
import 'package:flutter_app_seals/model/object_main/Status.dart';
import 'package:flutter_app_seals/model/seals/Seals_List.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_app_seals/Setting_glob.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:flutter_app_seals/model/add_seals/JsonAddSeals.dart';
import 'package:flutter_app_seals/model/user_page/page.dart';
import 'package:flutter_app_seals/model/setting/globalvar.dart' as global;
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:io';
import 'package:flutter_aes_ecb_pkcs5/flutter_aes_ecb_pkcs5.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/foundation.dart';
void main() => runApp(Main_Page());
class Main_Page extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage());
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
var test;
class _HomePageState extends State<HomePage> {
Future<bool> _onBackPressed() {
return showDialog(
context: context,
builder: (context) => new AlertDialog(
title: new Text('Ви впевнині?'),
content: new Text('Ви хочете вийти з додатку',
style: TextStyle(
fontSize: 20,
),
),
actions: <Widget>[
new GestureDetector(
onTap: () => Navigator.of(context).pop(false),
child:
Text("Ні",
style: TextStyle(
fontSize: 25,
),
),
),
SizedBox(height: 40),
new GestureDetector(
onTap: () => Navigator.of(context).pop(true),
child: Text("Так",
style: TextStyle(
fontSize: 25,
),
),
),
],
),
) ??
false;
}
int _pageIndex = 0;
PageController _pageController;
List<Widget> tabPages = [
Login(),
Setting(),
UserPage(),
Status_Obj(),
Status_Seals(),
Add_Seals(),
] ;
#override
void initState(){
super.initState();
_pageController = PageController(initialPage: _pageIndex);
}
#override
void dispose() {
_pageController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onBackPressed,
child: new Scaffold(
resizeToAvoidBottomInset: false,
bottomNavigationBar: BottomNavigationBar(
showSelectedLabels: true, // <-- HERE
showUnselectedLabels: true, // <-- AND
currentIndex: _pageIndex,
onTap: onTabTapped,
backgroundColor: Colors.blue,
items: <BottomNavigationBarItem>[
new BottomNavigationBarItem( icon: Icon(Icons.admin_panel_settings_outlined), title: Text(" Вхід"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.settings), title: Text("Налаштування"),backgroundColor: Colors.lightBlue),
if( global.nameUser ?.isNotEmpty == true)...[
new BottomNavigationBarItem(icon: Icon(Icons.person_pin), title: Text("Користувач"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("Пломбування"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.qr_code), title: Text("Пломби"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.add_outlined), title: Text("Акт приймання"),backgroundColor: Colors.lightBlue),
]
],
),
body: PageView(
children: tabPages,
onPageChanged: onPageChanged,
controller: _pageController,
),
),
);
}
void onPageChanged(int page) {
setState(() {
this._pageIndex = page;
});
}
void onTabTapped(int index) {
this._pageController.animateToPage(index,duration: const Duration(milliseconds: 500),curve: Curves.easeInOut);
}
}
class Login extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new LoginPage(
storage: Storage()
)
);
}
}
class LoginPage extends StatefulWidget {
final Storage storage;
LoginPage({Key key, #required this.storage}) : super(key: key);
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
//Info about users
String state;
#override
void initState() {
super.initState();
widget.storage.readData().then((String value) {
setState(() {
global.urlVar = value;
});
});
}
bool _isLoading = false;
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light.copyWith(statusBarColor: Colors.transparent));
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue, Colors.white],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
),
child: _isLoading ? Center(child: CircularProgressIndicator()) : ListView(
children: <Widget>[
headerSection(),
textSection(),
buttonSection(),
],
),
),
);
}
signIn(String login, pass) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
var AESLogin = login;
var AESpass = pass;
//generate a 16-byte random key
var key = '11111';
print(key);
//encrypt
var encryptLogin = await FlutterAesEcbPkcs5.encryptString(AESLogin, key);
var encryptPass = await FlutterAesEcbPkcs5.encryptString(AESpass, key);
HttpClient client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
String url = global.urlVar + "/auth_user";
Map map = {
"login": encryptLogin,
"pass": encryptPass
};
HttpClientRequest request = await client.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(map)));
HttpClientResponse response = await request.close();
var responseBody = await response.transform(utf8.decoder).join();
Map jsonResponse = json.decode(responseBody);
print(jsonResponse);
if (response.statusCode == 200) {
if (jsonResponse['message'] ==
'200') { //if( jsonResponse['message'] == '200') {
setState(() {
_isLoading = false;
});
global.nameUser = jsonResponse['name'];
global.dataArea = jsonResponse['data_area'];
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => UserPage()),
);
}
else {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Error_Auth()),
);
}
}
else {
setState(() {
_isLoading = false;
});
}
}
Container buttonSection() {
return Container(
width: MediaQuery.of(context).size.width,
height: 40.0,
padding: EdgeInsets.symmetric(horizontal: 15.0),
margin: EdgeInsets.only(top: 15.0),
child: RaisedButton(
onPressed: emailController.text == "" || passwordController.text == "" ? null : () {
setState(() {
_isLoading = true;
});
signIn(emailController.text, passwordController.text);
},
elevation: 0.0,
color: Colors.purple,
child: Text("Авторизація", style: TextStyle(color: Colors.white70)),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),
),
);
}
final TextEditingController emailController = new TextEditingController();
final TextEditingController passwordController = new TextEditingController();
Container textSection() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
child: Column(
children: <Widget>[
TextFormField(
controller: emailController,
cursorColor: Colors.white,
style: TextStyle(color: Colors.white70),
decoration: InputDecoration(
icon: Icon(Icons.login, color: Colors.white70),
hintText: "Логін",
border: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white70)),
hintStyle: TextStyle(color: Colors.white70),
),
),
SizedBox(height: 30.0),
TextFormField(
controller: passwordController,
cursorColor: Colors.white,
obscureText: true,
style: TextStyle(color: Colors.white70),
decoration: InputDecoration(
icon: Icon(Icons.lock, color: Colors.white70),
hintText: "Пароль",
border: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white70)),
hintStyle: TextStyle(color: Colors.white70),
),
),
],
),
);
}
Container headerSection() {
return Container(
alignment: Alignment.topCenter,
margin: EdgeInsets.only(top: 50.0),
child: Text("Пломби",
style: TextStyle(
color: Colors.white70,
fontSize: 40.0,
fontWeight: FontWeight.bold)),
);
}
}
class Error_Auth extends StatelessWidget {
#override
Widget build(BuildContext context) {
final AlertDialog dialog = AlertDialog(
title: Text('Помилка при авторизації'),
content:
Text('Повторити спробу авторизації'),
actions: [
FlatButton(
textColor: Color(0xFF6200EE),
onPressed: () => SystemNavigator.pop(),
child: Text('Ні'),
),
FlatButton(
textColor: Color(0xFF6200EE),
onPressed: () { Navigator.push(
context,MaterialPageRoute(builder: (context) => Login()),
);
},
child: Text('Так'),
),
],
);
return Scaffold(
body:dialog
);
}
}
class Storage {
Future<String> get localPath async {
final dir = await getApplicationDocumentsDirectory();
return dir.path;
}
Future<File> get localFile async {
final path = await localPath;
return File('$path/db.txt');
}
Future<String> readData() async {
try {
final file = await localFile;
String body = await file.readAsString();
return body;
} catch (e) {
return e.toString();
}
}
Future<File> writeData(String data) async {
final file = await localFile;
return file.writeAsString("$data");
}
}
In this part of the code I am automated and if the status code is 200, then I parse the Jason and add a name for the variable global.nameUser. And in the navigation menu I check if it is not zero then show all the icons of the navigation menu. But the first time it doesn't work. I have clicked on this menu again and only then it will work.
if (response.statusCode == 200) {
if (jsonResponse['message'] ==
'200') { //if( jsonResponse['message'] == '200') {
setState(() {
_isLoading = false;
});
global.nameUser = jsonResponse['name'];
global.dataArea = jsonResponse['data_area'];
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => UserPage()),
);
}
Check the navigation menu which icons to display!
items: <BottomNavigationBarItem>[
new BottomNavigationBarItem( icon: Icon(Icons.admin_panel_settings_outlined), title: Text(" Вхід"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.settings), title: Text("Налаштування"),backgroundColor: Colors.lightBlue),
if( global.nameUser ?.isNotEmpty == true)...[
new BottomNavigationBarItem(icon: Icon(Icons.person_pin), title: Text("Користувач"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("Пломбування"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.qr_code), title: Text("Пломби"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.add_outlined), title: Text("Акт приймання"),backgroundColor: Colors.lightBlue),
]
],
Your page is not re built after logging in the user, that is why your nav bar is not updated. When you click on the button it refreshes and correctly displays the new elements.
Instead of using a global variable you could look into a state management package in order to make the logged-in user available throughout your app. (article for getx the simplest one out there)
If this is simply a prototype and you want some quick and dirty, I guess you could trigger a reload of your app once a user logs in by wrapping your app with a widget that exposes a rebuild method. (article)
EDIT: Example with Getx:
class UserController extends GetxController {
var nameUser = "".obs;
void setName(String str) => nameUser = str;
}
class Home extends StatelessWidget {
final UserController c = Get.put(UserController());
#override
Widget build(context)
...
Obx(() => /// You are watching your controller
...
items: <BottomNavigationBarItem>[
if( c.nameUser.isNotEmpty)...[
...
]
)))
...
class LoginPage extends StatelessWidget {
// You can ask Get to find a Controller that is being used by another page and redirect you to it.
final UserController c = Get.find();
#override
Widget build(context){
...
onPressed: () => c.setName(username);
}
}
I have a navigation menu that I made for the test application, there are some tabs as I want to hide if I have not logged in to the application. Once I log in, these tabs should appear. Here is my code for the navigation menu.
import 'package:flutter/material.dart';
import 'package:flutter_app_seals/Status.dart';
import 'package:flutter_app_seals/Seals_List.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_app_seals/auth_page.dart';
import 'package:flutter_app_seals/Setting_glob.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:flutter_app_seals/model/add_seals/JsonAddSeals.dart';
import 'package:flutter_app_seals/model/user_page/page.dart';
import 'package:flutter_app_seals/model/setting/globalvar.dart' as global;
class Main_Page extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new LoginPage());
}
}
class LoginPage extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
int _pageIndex = 0;
PageController _pageController;
List<Widget> tabPages = [
Login(),
Setting(),
UserPage(),
Status_Obj(),
Status_seals(),
JsonParseAddSeals(),
];
#override
void initState(){
super.initState();
_pageController = PageController(initialPage: _pageIndex);
}
#override
void dispose() {
_pageController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return WillPopScope(
child: new Scaffold(
resizeToAvoidBottomInset: false,
bottomNavigationBar: BottomNavigationBar(
showSelectedLabels: true, // <-- HERE
showUnselectedLabels: true, // <-- AND
currentIndex: _pageIndex,
onTap: onTabTapped,
backgroundColor: Colors.blue,
items: <BottomNavigationBarItem>[
new BottomNavigationBarItem( icon: Icon(Icons.admin_panel_settings_outlined), title: Text(" Вхід"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.settings), title: Text("Налаштування"),backgroundColor: Colors.lightBlue),
if(global.nameUser ?.isNotEmpty == true)...[
new BottomNavigationBarItem(icon: Icon(Icons.person_pin), title: Text("Користувач"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("Пломбування"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.qr_code), title: Text("Пломби"),backgroundColor: Colors.lightBlue),
new BottomNavigationBarItem(icon: Icon(Icons.add_outlined), title: Text("Акт приймання"),backgroundColor: Colors.lightBlue),
]
],
),
body: PageView(
children: tabPages,
onPageChanged: onPageChanged,
controller: _pageController,
),
),
);
}
void onPageChanged(int page) {
setState(() {
this._pageIndex = page;
});
}
void onTabTapped(int index) {
this._pageController.animateToPage(index,duration: const Duration(milliseconds: 500),curve: Curves.easeInOut);
}
}
The problem is that when I log in I go to the desired page, I do not see all the icons of the navigation menu. In order for them to appear, I need to click on one of the icons that are available (only 2 icons are available for authorization) and only then the navigation menu will be updated and everything will be as it should be. All 6 icons will be visible! Here is my auto authorization code:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'Status.dart';
import 'dart:io';
import 'package:flutter_app_seals/model/setting/globalvar.dart' as global;
import 'package:flutter_aes_ecb_pkcs5/flutter_aes_ecb_pkcs5.dart';
import 'package:flutter/widgets.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_app_seals/model/user_page/page.dart' ;
void main() => runApp(Login());
class Login extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new LoginPage(
storage: Storage()
)
);
}
}
class LoginPage extends StatefulWidget {
final Storage storage;
LoginPage({Key key, #required this.storage}) : super(key: key);
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
//Info about users
String state;
#override
void initState() {
super.initState();
widget.storage.readData().then((String value) {
setState(() {
global.urlVar = value;
});
});
}
bool _isLoading = false;
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light.copyWith(statusBarColor: Colors.transparent));
return Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue, Colors.white],
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
),
child: _isLoading ? Center(child: CircularProgressIndicator()) : ListView(
children: <Widget>[
headerSection(),
textSection(),
buttonSection(),
],
),
),
);
}
signIn(String login, pass) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
var AESLogin = login;
var AESpass = pass;
//generate a 16-byte random key
var key = '123111111111111111121212';
print(key);
//encrypt
var encryptLogin = await FlutterAesEcbPkcs5.encryptString(AESLogin, key);
var encryptPass = await FlutterAesEcbPkcs5.encryptString(AESpass, key);
HttpClient client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) => true);
String url = 'testUrl';
Map map = {
"login": encryptLogin,
"pass": encryptPass
};
HttpClientRequest request = await client.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(map)));
HttpClientResponse response = await request.close();
var responseBody = await response.transform(utf8.decoder).join();
Map jsonResponse = json.decode(responseBody);
print(jsonResponse);
if (response.statusCode == 200) {
if (jsonResponse['message'] ==
'200') { //if( jsonResponse['message'] == '200') {
setState(() {
_isLoading = false;
});
global.nameUser = jsonResponse['name'];
global.dataArea = jsonResponse['data_area'];
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => UserPage()),
);
}
else {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Error_Auth()),
);
}
}
else {
setState(() {
_isLoading = false;
});
}
}
Container buttonSection() {
return Container(
width: MediaQuery.of(context).size.width,
height: 40.0,
padding: EdgeInsets.symmetric(horizontal: 15.0),
margin: EdgeInsets.only(top: 15.0),
child: RaisedButton(
onPressed: emailController.text == "" || passwordController.text == "" ? null : () {
setState(() {
_isLoading = true;
});
signIn(emailController.text, passwordController.text);
},
elevation: 0.0,
color: Colors.purple,
child: Text("Log in", style: TextStyle(color: Colors.white70)),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),
),
);
}
final TextEditingController emailController = new TextEditingController();
final TextEditingController passwordController = new TextEditingController();
Container textSection() {
return Container(
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
child: Column(
children: <Widget>[
TextFormField(
controller: emailController,
cursorColor: Colors.white,
style: TextStyle(color: Colors.white70),
decoration: InputDecoration(
icon: Icon(Icons.login, color: Colors.white70),
hintText: "Name",
border: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white70)),
hintStyle: TextStyle(color: Colors.white70),
),
),
SizedBox(height: 30.0),
TextFormField(
controller: passwordController,
cursorColor: Colors.white,
obscureText: true,
style: TextStyle(color: Colors.white70),
decoration: InputDecoration(
icon: Icon(Icons.lock, color: Colors.white70),
hintText: "Pass",
border: UnderlineInputBorder(borderSide: BorderSide(color: Colors.white70)),
hintStyle: TextStyle(color: Colors.white70),
),
),
],
),
);
}
Container headerSection() {
return Container(
alignment: Alignment.topCenter,
margin: EdgeInsets.only(top: 50.0),
child: Text("Пломби",
style: TextStyle(
color: Colors.white70,
fontSize: 40.0,
fontWeight: FontWeight.bold)),
);
}
}
class Error_Auth extends StatelessWidget {
#override
Widget build(BuildContext context) {
final AlertDialog dialog = AlertDialog(
title: Text('Помилка при авторизації'),
content:
Text('Повторити спробу авторизації'),
actions: [
FlatButton(
textColor: Color(0xFF6200EE),
onPressed: () => SystemNavigator.pop(),
child: Text('Ні'),
),
FlatButton(
textColor: Color(0xFF6200EE),
onPressed: () { Navigator.push(
context,MaterialPageRoute(builder: (context) => Login()),
);
},
child: Text('Так'),
),
],
);
return Scaffold(
body:dialog
);
}
}
class Storage {
Future<String> get localPath async {
final dir = await getApplicationDocumentsDirectory();
return dir.path;
}
Future<File> get localFile async {
final path = await localPath;
return File('$path/db.txt');
}
Future<String> readData() async {
try {
final file = await localFile;
String body = await file.readAsString();
return body;
} catch (e) {
return e.toString();
}
}
Future<File> writeData(String data) async {
final file = await localFile;
return file.writeAsString("$data");
}
}
After I log in to the application and go to the user page, the navigation menu is not updated and only 2 icons are available.
Solution 1: Pass the controller to the Login page
List<Widget> tabPages = [];
#override
void initState() {
super.initState();
_pageController = PageController(initialPage: _pageIndex);
tabPages = [
Login(_pageController),
Setting(),
UserPage(),
Status_Obj(),
Status_seals(),
JsonParseAddSeals(),
];
}
And instead of
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => UserPage()),
);
use
widget.pageController?.animateToPage(2,
duration: const Duration(milliseconds: 500), curve: Curves.easeInOut);
Solution 2: Put your controller in your global dart.
Cool login page by the way :-)
I want to show a text after onPressed function happened, this function is a recording function and wants to show a text 'recording' when the function happening
voiceCreate.dart
import 'package:flutter/material.dart';
class VoiceCreate extends StatelessWidget {
final VoidCallback onPressed;
VoiceCreate({this.onPressed});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blueGrey,
body: Center(
child: IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 70,
onPressed: onPressed),
),
),
);
}
}
**main.dart**
import 'dart:io';
import 'package:audioplayer/audioplayer.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'dart:async';
import 'package:path_provider/path_provider.dart';
import 'package:record_mp3/record_mp3.dart';
import 'package:permission_handler/permission_handler.dart';
import 'regitration.dart';
import 'voiceCreate.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String statusText = "";
bool isComplete = false;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Builder(
builder: (context) => Scaffold(
drawer: Drawer(
elevation: 2.0,
child: ListView(
children: <Widget>[
ListTile(
title: Text('Home'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return MyApp();
},
),
);
},
),
ListTile(
title: Text('Sign up'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return LoginScreen();
},
),
);
},
),
ListTile(
title: Text('Sign in'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return LoginScreen();
},
),
);
// add sign in page
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return VoiceCreate(onPressed: startRecord);
}),
);
},
// Add your onPressed code here!
child: Icon(Icons.add),
backgroundColor: Colors.tealAccent.shade700,
),
backgroundColor: Colors.grey.shade900,
appBar: AppBar(
title: Text('Myvo'),
centerTitle: true,
backgroundColor: Colors.tealAccent.shade700,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: GestureDetector(
child: IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 40,
onPressed: () async {
startRecord();
}),
),
),
Expanded(
child: GestureDetector(
child: IconButton(
icon: Icon(Icons.pause),
color: Colors.white,
iconSize: 40,
onPressed: () async {
pauseRecord();
}),
),
),
Expanded(
child: GestureDetector(
child: IconButton(
icon: Icon(Icons.stop),
color: Colors.white,
iconSize: 40,
onPressed: () async {
stopRecord();
}),
),
),
],
),
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Text(
statusText,
style: TextStyle(color: Colors.red, fontSize: 20),
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
play();
},
child: Container(
margin: EdgeInsets.only(top: 30),
alignment: AlignmentDirectional.center,
width: 100,
height: 50,
child: isComplete && recordFilePath != null
? Text(
"play",
style: TextStyle(color: Colors.red, fontSize: 20),
)
: Container(),
),
),
]),
),
),
);
}
Future<bool> checkPermission() async {
if (!await Permission.microphone.isGranted) {
PermissionStatus status = await Permission.microphone.request();
if (status != PermissionStatus.granted) {
return false;
}
}
return true;
}
void startRecord() async {
bool hasPermission = await checkPermission();
if (hasPermission) {
statusText = "Recording...";
recordFilePath = await getFilePath();
isComplete = false;
RecordMp3.instance.start(recordFilePath, (type) {
statusText = "Record error--->$type";
setState(() {});
});
} else {
statusText = "No microphone permission";
}
setState(() {});
}
void pauseRecord() {
if (RecordMp3.instance.status == RecordStatus.PAUSE) {
bool s = RecordMp3.instance.resume();
if (s) {
statusText = "Recording...";
setState(() {});
}
} else {
bool s = RecordMp3.instance.pause();
if (s) {
statusText = "Recording pause...";
setState(() {});
}
}
}
void stopRecord() {
bool s = RecordMp3.instance.stop();
if (s) {
statusText = "Record complete";
isComplete = true;
setState(() {});
}
}
void resumeRecord() {
bool s = RecordMp3.instance.resume();
if (s) {
statusText = "Recording...";
setState(() {});
}
}
String recordFilePath;
void play() {
if (recordFilePath != null && File(recordFilePath).existsSync()) {
AudioPlayer audioPlayer = AudioPlayer();
audioPlayer.play(recordFilePath, isLocal: true);
}
}
int i = 0;
Future<String> getFilePath() async {
Directory storageDirectory = await getApplicationDocumentsDirectory();
String sdPath = storageDirectory.path + "/record";
var d = Directory(sdPath);
if (!d.existsSync()) {
d.createSync(recursive: true);
}
return sdPath + "/test_${i++}.mp3";
}
}
VoiceCreate function will happen on a new page when clicking on the Floating button in main.dart and recording will happen when click on mic Icon, want show the text 'recording' whine the fuction happening.
First of all, you need to have StatefulWidget to manage changes in state, then you can use two functions startRecording and stopRecording to toggle the isRecording variable. Then based on the value of isRecording you can make changes in the view, e.g., displaying a text. For displaying the text you can use a Visibility widget and set its visible parameter to isRecording.
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _isRecording = false;
_startRecording() {
this.setState(() {
_isRecording = true;
});
}
_stopRecording() {
this.setState(() {
_isRecording = false;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.blueGrey,
body: Center(
child: Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 70,
onPressed: () => _startRecording(),
),
IconButton(
icon: Icon(Icons.stop),
color: Colors.white,
iconSize: 70,
onPressed: () => _stopRecording(),
),
Visibility(
visible: _isRecording,
child: Text(
'recording',
style: TextStyle(
color: Colors.red
),
),
)
],
),
),
),
);
}
}
Maybe a snackbar could be useful here, something like:
class VoiceCreate extends StatefulWidget {
VoiceCreate({Key key, this.title}) : super(key: key);
final String title;
#override
_VoiceCreateState createState() => _VoiceCreateState();
}
class _VoiceCreateState extends State<VoiceCreate> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
var isRecording = false;
void showRecordingMessage(String message, [Color color = Colors.red]) {
_scaffoldKey.currentState.showSnackBar(
new SnackBar(backgroundColor: color, content: new Text(message)));
}
void setRecordingState() {
this.setState(() {
isRecording = true;
});
print("isRecording is set to $isRecording");
showRecordingMessage('Recording now!');
}
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
backgroundColor: Colors.blueGrey,
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(Icons.mic),
color: Colors.white,
iconSize: 70,
onPressed: () {
setRecordingState();
},
),
],
),
),
);
}
}
I'm working with Enums through my application and I noticed that it resets every time I leave the page or of course when I close the app, I know about shared_preferences but I don't know if it's the right way or actually how to implement it with an enum. Any information on this would be much appreciated
here is a sample from my application:
`enum Gender {
male,
female,
}
class InputPage extends StatefulWidget {
#override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
Gender selectedGender;
int height = 180;
int weight = 60;
int age = 20;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BMI CALCULATOR'),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
Expanded(
child: ReusableCard(
onPress: () {
setState(() {
selectedGender = Gender.male;
});
},
colour: selectedGender == Gender.male
? kActiveCardColour
: kInactiveCardColour,
cardChild: IconContent(
icon: FontAwesomeIcons.mars,
label: 'MALE',
),
),
),
Expanded(
child: ReusableCard(
onPress: () {
setState(() {
selectedGender = Gender.female;
});
},
colour: selectedGender == Gender.female
? kActiveCardColour
: kInactiveCardColour,
cardChild: IconContent(
icon: FontAwesomeIcons.venus,
label: 'FEMALE',
),
),
),
],
))
,`
You can copy paste run full code below
You can use package https://pub.dev/packages/enum_to_string to save and get enum as String
Step 1: init selectedGender in initState() with EnumToString.fromString
#override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
initGender();
});
super.initState();
}
void initGender() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
selectedGender =
EnumToString.fromString(Gender.values, prefs.getString("gender"));
setState(() {});
}
Step 2: Save selectedGender with prefs.setString("gender", enumToString.parse(Gender.male));
onPress: () async {
setState(() {
selectedGender = Gender.male;
});
SharedPreferences prefs =
await SharedPreferences.getInstance();
prefs.setString(
"gender", EnumToString.parse(Gender.male));
}
working demo
full code
import 'package:flutter/material.dart';
import 'package:enum_to_string/enum_to_string.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
const kBottomContainerHeight = 80.0;
const kActiveCardColour = Color(0xFF1D1E33);
const kInactiveCardColour = Color(0xFF111328);
const kBottomContainerColour = Color(0xFFEB1555);
const kLabelTextStyle = TextStyle(
fontSize: 18.0,
color: Color(0xFF8D8E98),
);
const kNumberTextStyle = TextStyle(
fontSize: 50.0,
fontWeight: FontWeight.w900,
);
const kLargeButtonTextStyle = TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold,
);
const kTitleTextStyle = TextStyle(
fontSize: 50.0,
fontWeight: FontWeight.bold,
);
const kResultTextStyle = TextStyle(
color: Color(0xFF24D876),
fontSize: 22.0,
fontWeight: FontWeight.bold,
);
const kBMITextStyle = TextStyle(
fontSize: 100.0,
fontWeight: FontWeight.bold,
);
const kBodyTextStyle = TextStyle(
fontSize: 22.0,
);
class IconContent extends StatelessWidget {
IconContent({this.icon, this.label});
final IconData icon;
final String label;
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
icon,
size: 80.0,
),
SizedBox(
height: 15.0,
),
Text(
label,
style: kLabelTextStyle,
)
],
);
}
}
enum Gender {
male,
female,
}
class ReusableCard extends StatelessWidget {
ReusableCard({#required this.colour, this.cardChild, this.onPress});
final Color colour;
final Widget cardChild;
final Function onPress;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onPress,
child: Container(
child: cardChild,
margin: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: colour,
borderRadius: BorderRadius.circular(10.0),
),
),
);
}
}
class InputPage extends StatefulWidget {
#override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
Gender selectedGender;
int height = 180;
int weight = 60;
int age = 20;
#override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) {
initGender();
});
super.initState();
}
void initGender() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
selectedGender =
EnumToString.fromString(Gender.values, prefs.getString("gender"));
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BMI CALCULATOR'),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Row(
children: <Widget>[
Expanded(
child: ReusableCard(
onPress: () async {
setState(() {
selectedGender = Gender.male;
});
SharedPreferences prefs =
await SharedPreferences.getInstance();
prefs.setString(
"gender", EnumToString.parse(Gender.male));
},
colour: selectedGender == Gender.male
? kActiveCardColour
: kInactiveCardColour,
cardChild: IconContent(
icon: FontAwesomeIcons.mars,
label: 'MALE',
),
),
),
Expanded(
child: ReusableCard(
onPress: () async {
setState(() {
selectedGender = Gender.female;
});
SharedPreferences prefs =
await SharedPreferences.getInstance();
prefs.setString(
"gender", EnumToString.parse(Gender.female));
},
colour: selectedGender == Gender.female
? kActiveCardColour
: kInactiveCardColour,
cardChild: IconContent(
icon: FontAwesomeIcons.venus,
label: 'FEMALE',
),
),
),
],
))
]));
}
}
Future<void> main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: InputPage(),
);
}
}
I think shared prefs only stores simple types. You could copy what json_serializable does and just decode a string value with a simple function and a mapping. This is their implementation but I'll add comments.
// _$CategoryEnumMap is a Map<dynamic, String> mapping from enum entry to string
const _$CategoryEnumMap = {
Category.action: 'action',
Category.drama: 'drama',
};
T _$enumDecode<T>(
// enumValues would be _$CategoryEnumMap in this case
Map<T, dynamic> enumValues,
// source is the string value you would get from shared prefs
dynamic source, {
T unknownValue,
}) {
if (source == null) {
throw ArgumentError('A value must be provided. Supported values: '
'${enumValues.values.join(', ')}');
}
final value = enumValues.entries
.singleWhere((e) => e.value == source, orElse: () => null)
?.key;
if (value == null && unknownValue == null) {
throw ArgumentError('`$source` is not one of the supported values: '
'${enumValues.values.join(', ')}');
}
return value ?? unknownValue;
}
You could get rid of the _$ stuff to make the function publicly accessible and I'm sure you could automatically create the EnumMap using a function like this.
enum Category {
action,
drama,
}
final Map<dynamic, String> CategoryEnumMap = Map.fromIterable(
Category.values.map((e) => MapEntry(e, describeEnum(e))),
);