I'm building my first web app using Flutter Webview in which I embedded a bottom Navigation bar that further has 4 Icons.
Each Icon has its Own Class and by pressing on it launches a different Webview for each tab like the below example:
But the problem that I am facing right above is that you can see each tab cannot be pressed more than once at a time. What I'm looking for is to reopen the same tab like a hyperlink in html instead of once only.
Also, I have no idea how to refresh webview page when hitting the refresh icon no matter what page or tab I'm
main.dart
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:splash_screen_view/SplashScreenView.dart';
import 'pages/home_page.dart';
import 'pages/profile.dart';
import 'pages/cart.dart';
void main(){
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Color(0xff1e2229)
));
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
Widget spalshfirst = SplashScreenView(
navigateRoute: WebViewClass(),
duration: 3000,
imageSize: 80,
imageSrc: 'assets/splash.png',
text: "Food Delivery",
textType: TextType.TyperAnimatedText,
textStyle: TextStyle(
fontSize: 25.0,
),
colors: const [
Colors.purple,
Colors.blue,
Colors.yellow,
Colors.red,
],
backgroundColor: Colors.white,
);
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: spalshfirst
)
);
}
}
class WebViewClass extends StatefulWidget {
WebViewState createState() => WebViewState();
}
class WebViewState extends State<WebViewClass> with TickerProviderStateMixin{
#override
void initState() {
super.initState();
// Enable hybrid composition.
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
int currentIndex = 0;
#override
Widget build(BuildContext context) {
//Including Dart Webview pages
final screens = [
HomeClass(),
Center(child: Text('refresh')),
ProfileClass(),
CartClass()
];
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: null,
body: SafeArea(
child: screens[currentIndex]
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentIndex,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.white60,
onTap: (index) => setState(() => currentIndex = index),
items: const [
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.home),
label: 'Home',
backgroundColor: Colors.pink
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.refresh),
label: 'Refresh',
backgroundColor: Colors.pink
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.profile_circled),
label: 'Profile',
backgroundColor: Colors.pink
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.cart),
label: 'Cart',
backgroundColor: Colors.pink
)
],
) ,
);
}
}
Webview HomeClass() refrence
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class HomeClass extends StatefulWidget {
Homestate createState() => Homestate();
}
class Homestate extends State<HomeClass> with TickerProviderStateMixin{
late WebViewController _controller;
final Completer<WebViewController> _controllerCompleter = Completer<WebViewController>();
//Make sure this function return Future<bool> otherwise you will get an error
Future<bool> _onWillPop(BuildContext context) async {
if (await _controller.canGoBack()) {
_controller.goBack();
return Future.value(false);
} else {
return Future.value(true);
}
}
bool isLoading = false;
final key = UniqueKey();
int position = 0;
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () => _goBack(context),
child: Scaffold(
appBar: null,
body: IndexedStack(
index: position,
children: [
WebView(
initialUrl: 'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
key: key,
onPageStarted: (value) {
setState(() {
position = 1;
});
},
onPageFinished: (value) {
setState(() {
position = 0;
});
},
onWebViewCreated: (WebViewController webViewController) {
_controllerCompleter.future.then((value) => _controller = value);
_controllerCompleter.complete(webViewController);
},
),
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white.withOpacity(0.5),
child: Center(
child: SpinKitDualRing(
color: Colors.pinkAccent,
size: 45.0,
controller: AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1200),
),
),
),
)
],
))
);
}
//Go back coding
Future<bool> _goBack(BuildContext context) async {
if (await _controller.canGoBack()) {
_controller.goBack();
return Future.value(false);
} else {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Do you want to exit from Foodrive?'),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('No'),
),
TextButton(
onPressed: () {
SystemNavigator.pop();
},
child: const Text('Yes'),
),
],
));
return Future.value(true);
}
}
}
I found a solution after paid someone for this answer. In this solution developer added 2 new packages import 'package:get/get.dart'; and import 'package:testing/pages/navigation_controller.dart';
dependencies
dependencies:
flutter:
sdk: flutter
webview_flutter: ^2.3.0
flutter_spinkit: ^5.1.0
splash_screen_view: ^3.0.0
flutter_icons: ^1.1.0
pull_to_refresh: ^2.0.0
get:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.4
main.dart
// ignore_for_file: prefer_const_constructors
// ignore: use_key_in_widget_constructors
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:testing/pages/navigation_controller.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:splash_screen_view/SplashScreenView.dart';
import 'initial_bindings.dart';
import 'pages/home_page.dart';
import 'pages/profile.dart';
import 'pages/cart.dart';
void main() {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(statusBarColor: Color(0xff1e2229)));
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
Widget spalshfirst = SplashScreenView(
navigateRoute: WebViewClass(),
duration: 3000,
imageSize: 80,
imageSrc: 'assets/splash.png',
text: "Food Delivery",
textType: TextType.TyperAnimatedText,
textStyle: TextStyle(
fontSize: 25.0,
),
colors: const [
Colors.purple,
Colors.blue,
Colors.yellow,
Colors.red,
],
backgroundColor: Colors.white,
);
return GetMaterialApp(
initialBinding: InitialBindings(),
debugShowCheckedModeBanner: false,
home: Scaffold(body: spalshfirst));
}
}
class WebViewClass extends StatefulWidget {
WebViewState createState() => WebViewState();
}
class WebViewState extends State<WebViewClass> with TickerProviderStateMixin {
#override
void initState() {
super.initState();
// Enable hybrid composition.
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
int currentIndex = 0;
#override
Widget build(BuildContext context) {
//Including Dart Webview pages
final screens = [
HomeClass(),
// Center(child: Text('refresh')),
ProfileClass(),
CartClass()
];
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: null,
body: SafeArea(child: screens[currentIndex]),
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.pink,
currentIndex: currentIndex,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.white60,
onTap: (index) {
setState(() => currentIndex = index);
Get.find<NavigationController>().controller.value?.reload();
},
items: const [
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.home),
label: 'Home',
backgroundColor: Colors.pink),
// BottomNavigationBarItem(
// icon: Icon(CupertinoIcons.refresh),
// label: 'Refresh',
// backgroundColor: Colors.pink),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.profile_circled),
label: 'Profile',
backgroundColor: Colors.red),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.cart),
label: 'Cart',
backgroundColor: Colors.pink)
],
),
);
}
}
initial_bindings.dart
import 'package:get/get.dart';
import 'package:webview_flutter/webview_flutter.dart';
class NavigationController extends GetxController {
Rx<WebViewController?> controller = null.obs;
}
Home_page.dart same code for(profile.dart and cart.dart)
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:testing/pages/navigation_controller.dart';
import 'package:webview_flutter/webview_flutter.dart';
class HomeClass extends StatefulWidget {
Homestate createState() => Homestate();
}
class Homestate extends State<HomeClass> with TickerProviderStateMixin {
late WebViewController _controller;
final Completer<WebViewController> _controllerCompleter =
Completer<WebViewController>();
final RefreshController _refreshController =
RefreshController(initialRefresh: false);
late AnimationController animController;
#override
void initState() {
super.initState();
animController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1200),
);
}
#override
void dispose() {
animController.dispose();
super.dispose();
}
//Make sure this function return Future<bool> otherwise you will get an error
Future<bool> _onWillPop(BuildContext context) async {
if (await _controller.canGoBack()) {
_controller.goBack();
return Future.value(false);
} else {
return Future.value(true);
}
}
bool isLoading = false;
final key = UniqueKey();
int position = 0;
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () => _goBack(context),
child: Scaffold(
appBar: null,
body: SmartRefresher(
controller: _refreshController,
enablePullDown: true,
onRefresh: () {
Get.find<NavigationController>().controller.value?.reload();
_refreshController.refreshCompleted();
},
child: IndexedStack(
index: position,
children: [
WebView(
initialUrl: 'https://canada.ca',
javascriptMode: JavascriptMode.unrestricted,
key: key,
onPageStarted: (value) {
setState(() {
position = 1;
});
},
onPageFinished: (value) {
setState(() {
position = 0;
});
},
onWebViewCreated: (WebViewController webViewController) {
_controllerCompleter.future
.then((value) => _controller = value);
_controllerCompleter.complete(webViewController);
Get.find<NavigationController>().controller =
webViewController.obs;
},
),
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white.withOpacity(0.5),
child: Center(
child: SpinKitDualRing(
color: Colors.pinkAccent,
size: 45.0,
controller: animController,
),
),
)
],
),
),
),
);
}
//Go back coding
Future<bool> _goBack(BuildContext context) async {
if (await _controller.canGoBack()) {
_controller.goBack();
return Future.value(false);
} else {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Do you want to exit from Foodrive?'),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text('No'),
),
TextButton(
onPressed: () {
SystemNavigator.pop();
},
child: const Text('Yes'),
),
],
));
return Future.value(true);
}
}
}
Related
I created the named routes in my main but its not navigating.
Inside the mainbutton widget i'm passing the navigator it accepts three parameters all of them are required...
import 'package:flutter/material.dart';
import 'package:texty/screens/welcome_screen.dart';
import 'package:texty/screens/login_screen.dart';
import 'package:texty/screens/registration_screen.dart';
import 'package:texty/screens/chat_screen.dart';
void main() => runApp(FlashChat());
class FlashChat extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: WelcomeScreen.id,
routes: {
WelcomeScreen.id: (context) => WelcomeScreen(),
ChatScreen.Id: (context) => ChatScreen(),
LoginScreen.Id: (context) => LoginScreen(),
RegistrationScreen.Id: (context) => RegistrationScreen(),
},
);
}
}
my welcome screen ->
import 'package:flutter/material.dart';
import 'package:texty/widgets/mainbutton.dart';
import 'login_screen.dart';
import 'registration_screen.dart';
import 'package:animated_text_kit/animated_text_kit.dart';
class WelcomeScreen extends StatefulWidget {
static const String id = 'welcome_screen';
#override
_WelcomeScreenState createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen>
with SingleTickerProviderStateMixin {
late AnimationController controller;
late Animation animation;
#override
void initState() {
super.initState();
controller =
AnimationController(duration: Duration(seconds: 1), vsync: this);
animation = ColorTween(begin: Colors.blueGrey, end: Colors.white)
.animate(controller);
controller.forward();
controller.addListener(() {
setState(() {});
});
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: animation.value,
body: Padding(
padding: EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
children: <Widget>[
Hero(
tag: 'logo',
child: Container(
child: Image.asset('images/logo.png'),
height: 60.0,
),
),
TypewriterAnimatedTextKit(
text: ['Texxty '],
textStyle: TextStyle(
fontSize: 45.0,
fontWeight: FontWeight.w900,
),
),
],
),
SizedBox(
height: 48.0,
),
mainButton(
title: 'Log In',
colour: Colors.lightBlueAccent,
onPressed: () {
Navigator.pushNamed(context, LoginScreen.Id);
},
),
mainButton(
title: 'Register',
colour: Colors.blueAccent,
onPressed: () {
Navigator.pushNamed(context, RegistrationScreen.Id);
},
),
],
),
),
);
}
}
try an other Option
instead of naming the pages
Navigator.push(
context,
MaterialPageRoute(builder: (context) => LoginScreen()),
);
I was working on my android app with flutter and it has a bug right now where when the app is in the background, it still plays a sound. The idea of the app is to play a bell sound when you shake your phone. It also likes to slow down the phone when it is in the background as well. Here is the code for my home page. (the code might not be the best, this is my first app)
import 'package:flutter/material.dart';
import 'package:audioplayers/audio_cache.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:sensors/sensors.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:provider/provider.dart';
import 'package:bell/ad_state.dart';
import 'package:bell/globals.dart' as globals;
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home>{
bool isBackground;
BannerAd banner;
Future<AudioPlayer> playLocalAsset() async {
AudioCache cache = new AudioCache();
return await cache.play(globals.playerBellSound);
}
Future<AudioPlayer> shakeBell() async {
AudioCache cache1 = new AudioCache();
return await cache1.play(globals.shakeBellSound);
}
#override
void initState() {
super.initState();
accelerometerEvents.listen((AccelerometerEvent event) {
if (event.x > 5.0 || event.x < -5.0) {
shakeBell();
}
});
}
#override
void dispose() {
super.dispose();
}
void didChangeDependencies() {
super.didChangeDependencies();
final adState = Provider.of<AdState>(context);
adState.initialization.then((status) {
setState(() {
banner = BannerAd(
adUnitId: adState.bannerAdUnitId,
size: AdSize.banner,
request: AdRequest(),
listener: adState.adListener,
);
});
});
}
#override
Widget build(BuildContext context) {
banner.load();
return Scaffold(
appBar: AppBar(
leading: GestureDetector(
onTap: () {
Navigator.pushNamed(context, '/settings');
},
child: Icon(
Icons.settings,
),
),
title: Text("Any Bell"),
centerTitle: true,
backgroundColor: Colors.blue[300],
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/ocean.jpg'),
fit: BoxFit.cover,
),
),
child: Center(
child: Column(
children: <Widget>[
IconButton(
onPressed: () {
playLocalAsset();
},
icon: Icon(
Icons.notifications,
color: Colors.white,
),
iconSize: 70,
),
Flexible(
flex: 2,
child: Container(),
),
Container(
height: 50,
child: AdWidget(ad: banner),
),
],
),
),
),
);
}}
Return an AudioPlayer from AudioCache.play()
AudioPlayer audioPlayer = await cache.play('your file name');
Call AudioPlayer.stop in dispose
#override
void dispose() {
audioPlayer.stop();
super.dispose();
}
I'm new to flutter and making my first webview app. Here I'm trying to add a spinner every time when a user tries to click the link or page load. I want to make spinner background opacity a bit low just like the given example, but opacity doesn't work at all.
My approach
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white.withOpacity(0.5),
child: Center(
child: SpinKitDualRing(
color: Colors.pinkAccent,
size: 45.0,
controller: AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1200),
),
),
),
)
I'm using here flutter_spinkit package as a spinner.
Full code
// ignore_for_file: prefer_const_constructors
// ignore: use_key_in_widget_constructors
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:splash_screen_view/SplashScreenView.dart';
void main(){
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Color(0xff1e2229)
));
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
Widget spalshfirst = SplashScreenView(
navigateRoute: WebViewClass(),
duration: 3000,
imageSize: 80,
imageSrc: 'assets/splash.png',
text: "Food Delivery",
textType: TextType.TyperAnimatedText,
textStyle: TextStyle(
fontSize: 25.0,
),
colors: const [
Colors.purple,
Colors.blue,
Colors.yellow,
Colors.red,
],
backgroundColor: Colors.white,
);
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: spalshfirst
)
);
}
}
class WebViewClass extends StatefulWidget {
WebViewState createState() => WebViewState();
}
class WebViewState extends State<WebViewClass> with TickerProviderStateMixin{
late WebViewController _controller;
final Completer<WebViewController> _controllerCompleter =
Completer<WebViewController>();
//Make sure this function return Future<bool> otherwise you will get an error
Future<bool> _onWillPop(BuildContext context) async {
if (await _controller.canGoBack()) {
_controller.goBack();
return Future.value(false);
} else {
return Future.value(true);
}
}
#override
void initState() {
super.initState();
// Enable hybrid composition.
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
bool isLoading = false;
final key = UniqueKey();
int position = 0;
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () => _goBack(context),
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: null,
body: SafeArea(
child: IndexedStack(
index: position,
children: [
WebView(
initialUrl: 'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
key: key,
onPageStarted: (value) {
setState(() {
position = 1;
});
},
onPageFinished: (value) {
setState(() {
position = 0;
});
},
onWebViewCreated: (WebViewController webViewController) {
_controllerCompleter.future
.then((value) => _controller = value);
_controllerCompleter.complete(webViewController);
},
),
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white.withOpacity(0.5),
child: Center(
child: SpinKitDualRing(
color: Colors.pinkAccent,
size: 45.0,
controller: AnimationController(
vsync: this,
duration: const Duration(milliseconds: 1200),
),
),
),
)
],
),
),
),
);
}
Future<bool> _goBack(BuildContext context) async {
if (await _controller.canGoBack()) {
_controller.goBack();
return Future.value(false);
} else {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Do you want to exit from Foodrive?'),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('No'),
),
TextButton(
onPressed: () {
SystemNavigator.pop();
},
child: Text('Yes'),
),
],
));
return Future.value(true);
}
}
}
Since the container is containing only the spinner, and not the background widget, settings its opacity won't work,
I'd suggest using the Stack widget with the Opacity widget
Something like this (just a reference point):
return Stack(children: [
Opacity(opacity: 0.5, child: resetOfTheWidgetTree),
Container(child: spinWidgetHere),
]);
**main.dart**
import 'package:flutter/material.dart';
import 'package:world_time/pages/choose_location.dart';
import 'package:world_time/pages/home.dart';
import 'package:world_time/pages/loading.dart';
void main() => runApp(MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => Loading(),
'/home': (context) => Home(),
'/location': (context) => ChooseLocation(),
},
));
**home.dart**
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
Map data = {};
#override
Widget build(BuildContext context) {
data = data.isNotEmpty ? data : ModalRoute.of(context).settings.arguments;
print(data);
// set background
String bgImage = data['isDaytime'] ? 'day.png' : 'night.png';
Color bgColor = data['isDaytime'] ? Colors.blue : Colors.indigo[700];
return Scaffold(
backgroundColor: bgColor,
body: SafeArea(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/$bgImage'),
fit: BoxFit.cover,
),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 120.0, 0, 0),
child: Column(
children: <Widget>[
FlatButton.icon(
onPressed: () async {
dynamic result =
await Navigator.pushNamed(context, '/location');
setState(() {
data = {
'time': result['time'],
'result': result['location'],
'isDaytime': result['isDaytime'],
'flag': result['flag'],
};
});
},
icon: Icon(
Icons.edit_location,
color: Colors.grey[300],
),
label: Text(
'Edit Location',
style: TextStyle(
color: Colors.grey[300],
),
),
),
SizedBox(height: 20.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
data['location'] ?? '',
style: TextStyle(
fontSize: 38.0,
letterSpacing: 2.0,
color: Colors.white,
),
),
],
),
SizedBox(height: 20.0),
Text(
data['time'] ?? '',
style: TextStyle(
fontSize: 66.0,
color: Colors.white,
),
),
],
),
),
),
),
);
}
}
**choose_location.dart**
import 'package:flutter/material.dart';
import 'package:world_time/services/world_time.dart';
class ChooseLocation extends StatefulWidget {
#override
_ChooseLocationState createState() => _ChooseLocationState();
}
class _ChooseLocationState extends State<ChooseLocation> {
List<WorldTime> locations = [
WorldTime(url: 'Europe/London', location: 'London', flag: 'uk.png'),
WorldTime(url: 'Europe/Berlin', location: 'Athens', flag: 'greece.png'),
WorldTime(url: 'Africa/Cairo', location: 'Cairo', flag: 'egypt.png'),
WorldTime(url: 'Africa/Nairobi', location: 'Nairobi', flag: 'kenya.png'),
WorldTime(url: 'America/Chicago', location: 'Chicago', flag: 'usa.png'),
WorldTime(url: 'America/New_York', location: 'New York', flag: 'usa.png'),
WorldTime(url: 'Asia/Seoul', location: 'Seoul', flag: 'south_korea.png'),
WorldTime(url: 'Asia/Jakarta', location: 'Jakarta', flag: 'indonesia.png'),
];
void updateTime(index) async {
WorldTime instance = locations[index];
await instance.getTime();
// navigate to home screen
Navigator.pop(context, {
'location': instance.location,
'flag': instance.flag,
'time': instance.time,
'isDaytime': instance.isDaytime,
});
}
#override
Widget build(BuildContext context) {
print('build function ran');
return Scaffold(
backgroundColor: Colors.grey[200],
appBar: AppBar(
backgroundColor: Colors.blue[900],
title: Text('Choose a Location'),
centerTitle: true,
elevation: 0,
),
body: ListView.builder(
itemCount: locations.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 1.0, horizontal: 4.0),
child: Card(
child: ListTile(
onTap: () {
updateTime(index);
},
title: Text(locations[index].location),
leading: CircleAvatar(
backgroundImage:
AssetImage('assets/${locations[index].flag}'),
),
),
),
);
},
),
);
}
}
**loading.dart**
import 'package:flutter/material.dart';
import 'package:world_time/services/world_time.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
class Loading extends StatefulWidget {
#override
_LoadingState createState() => _LoadingState();
}
class _LoadingState extends State<Loading> {
void setupWorldTime() async {
WorldTime instance = WorldTime(
location: 'Berlin', flag: 'germany.png', url: 'Europe/Berlin');
await instance.getTime();
Navigator.pushReplacementNamed(context, '/home', arguments: {
'location': instance.location,
'flag': instance.flag,
'time': instance.time,
'isDaytime': instance.isDaytime,
});
}
#override
void initState() {
super.initState();
setupWorldTime();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue[900],
body: Center(
child: SpinKitFadingCircle(
color: Colors.white,
size: 50.0,
),
),
);
}
}
**world_time.dart**
import 'package:http/http.dart';
import 'dart:convert';
import 'package:intl/intl.dart';
class WorldTime {
String location; // location name for the UI
String time; //the time in that location
String flag; //url to an asset flag icon
String url; //location url for api endpoint
bool isDaytime; //true or false if daytime or not
WorldTime({this.location, this.flag, this.url});
Future<void> getTime() async {
//make the request
Response response =
await get(Uri.parse('https://worldtimeapi.org/api/timezone/$url'));
Map data = jsonDecode(response.body);
//print(data);
//get properties from data
String datetime = data['datetime'];
String offset = data['utc_offset'].substring(1, 3);
//print(datetime);
//print(offset);
//create DateTime object
DateTime now = DateTime.parse(datetime);
now = now.add(Duration(hours: int.parse(offset)));
//set the time property
isDaytime = now.hour > 6 && now.hour < 20 ? true : false;
time = DateFormat.jm().format(now);
}
}
WorldTime instance =
WorldTime(location: 'Berlin', flag: 'germany.png', url: 'Europe/Berlin');
Here are my codes for building a World time app on flutter
No error message seen on the output, but when a new city or location is selected, It displays only the time on the device without displaying the corresponding city for the current time displayed on the screen. Please how can I fix this without blowing up my codes. Thanks
On your flatbutton onpressed you have set the location key to 'result' change it to 'location'.
FlatButton.icon(
onPressed: () async {
dynamic result =
await Navigator.pushNamed(context, '/location');
setState(() {
data = {
'time': result['time'],
// Change This
>>> 'result': result['location'], <<<
// To This
>>> 'location': result['location'], <<<
'isDaytime': result['isDaytime'],
'flag': result['flag'],
};
});
},
I'm doing a college assignment, I'm trying to do a listview in the "Cursos" class, and it's giving me some problems, if anyone can help I appreciate it!
If someone has a solution, how and for school work, there is a problem if it gets ugly.
Error:
════════ Exception caught by rendering library ═════════════════════════════════
'package:flutter/src/rendering/sliver_multi_box_adaptor.dart': Failed assertion: line 545 pos 12: 'child.hasSize': is not true.
The relevant error-causing widget was
ListView
lib\userscreen\userscreen.dart:82
════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by rendering library ═════════════════════════════════
Null check operator used on a null value
The relevant error-causing widget was
ListView
lib\userscreen\userscreen.dart:82
════════════════════════════════════════════════════════════════════════════════
Main class
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:signupexample/Database/database_helper.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:signupexample/main.dart';
import './avaliacao.dart';
import './consultoria.dart';
import './cursos.dart';
import './sair.dart';
class UserScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => _UserScreen();
}
class _UserScreen extends State<UserScreen> with WidgetsBindingObserver {
final dbHelper = DatabaseHelper.instance;
Map<String, dynamic> _useData;
bool _fetchingData = true;
#override
void initState() {
_query();
super.initState();
}
int indice = 0;
static List<Widget> telas = <Widget>[
Curso(),
Consultoria(),
Avaliacao(),
Sair()
];
void selecionar(int indice) {
setState(
() {
this.indice = indice;
},
);
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
exit(0);
return true;
},
child: Scaffold(
appBar: AppBar(
title: Text('Home'),
automaticallyImplyLeading: true,
),
bottomNavigationBar: BottomNavigationBar(
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
backgroundColor: Colors.red,
icon: Icon(Icons.home),
label: 'Cursos',
),
BottomNavigationBarItem(
backgroundColor: Colors.red,
icon: Icon(Icons.business),
label: 'Consultoria',
),
BottomNavigationBarItem(
backgroundColor: Colors.red,
icon: Icon(Icons.warning_rounded),
label: 'Avaliação',
),
BottomNavigationBarItem(
backgroundColor: Colors.red,
icon: Icon(Icons.exit_to_app),
label: 'Sair',
),
],
currentIndex: this.indice,
selectedItemColor: Colors.red[0],
onTap: selecionar,
),
body: _fetchingData
? CircularProgressIndicator()
: ListView(
children: [telas.elementAt(this.indice)],
),
),
);
}
void _query() async {
final allRows = await dbHelper.queryAllRows();
print('query all rows:');
allRows.forEach((row) => print(row));
setState(() {
_useData = allRows[0];
_fetchingData = false;
});
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setBool('isLogin', true);
}
}
class Cursos. This is the class where I want the listview to be made
import 'package:flutter/material.dart';
class Curso extends StatefulWidget {
State<StatefulWidget> createState() => _Curso();
}
class _Curso extends State<Curso> with WidgetsBindingObserver {
#override
Widget build(BuildContext context) {
return ListView(
padding: const EdgeInsets.all(8),
children: <Widget>[
Container(
height: 50,
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 50,
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 50,
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
],
);
}
}
Add shrinkWrap: true, to your Curso class ListView()