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();
}
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'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);
}
}
}
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),
]);
I want to build a screen that allows me to take photos in landscape and portrait. My app only runs in portrait mode by calling the following in main:
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
Due to the fact that my screen doesn't rotate anymore, the images are always taken in portrait, even if I tilt the phone to the side. Here is a small example project where you can see it clearly:
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:flutter/services.dart';
List<CameraDescription> cameras = [];
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
cameras = await availableCameras();
runApp(CameraApp());
}
class CameraApp extends StatefulWidget {
#override
_CameraAppState createState() => _CameraAppState();
}
class _CameraAppState extends State<CameraApp> {
CameraController? controller;
bool takingPicture = false;
XFile? selectedImage;
#override
void initState() {
super.initState();
controller = CameraController(cameras[0], ResolutionPreset.max);
controller!.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (!controller!.value.isInitialized) {
return Container();
}
return MaterialApp(
home: Stack(
fit: StackFit.expand,
children: [
RotatedBox(
quarterTurns: 1 - controller!.description.sensorOrientation ~/ 90,
child: CameraPreview(controller!),
),
CameraPreview(controller!),
Align(
alignment: Alignment.bottomRight,
child: FloatingActionButton(
onPressed: () {
if (!takingPicture) {
takingPicture = true;
controller!.takePicture().then(
(value) {
selectedImage = value;
setState(() {});
takingPicture = false;
},
);
}
},
),
),
Align(
alignment: Alignment.bottomLeft,
child: selectedImage != null
? Container(
height: 100,
width: 200,
child: Image.file(
File(selectedImage!.path),
),
)
: Container(),
),
],
),
);
}
}
When rotating the phone and taking a photo, the photo should also appear in Landscape, but it doesn't. How can I work around this without taking out setPreferredOrientations?
The normal mobile app on Android and iOS can do that too.
What I would do is to remove the constraint when entering the screen and reapplying it when entering.
Here is an example adapted from your code which features 2 screens:
A welcome screen which cannot rotate
The camera screen which does rotate
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:flutter/services.dart';
List<CameraDescription> cameras = [];
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
cameras = await availableCameras();
runApp(MaterialApp(home: WelcomeScreen()));
}
class WelcomeScreen extends StatelessWidget {
const WelcomeScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Welcome! Try rotating the screen, you won\'t be able to!'),
SizedBox(height: 10),
ElevatedButton(
onPressed: () => Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => CameraApp()),
),
child: Text('Press me to go to the camera'),
),
],
),
),
);
}
}
class CameraApp extends StatefulWidget {
#override
_CameraAppState createState() => _CameraAppState();
}
class _CameraAppState extends State<CameraApp> {
CameraController? controller;
bool takingPicture = false;
XFile? selectedImage;
#override
void initState() {
super.initState();
// Remove the constraint when entering, this is ok
// not to away since the app is in portrait mode by
// default
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
controller = CameraController(cameras[0], ResolutionPreset.max);
controller!.initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (!controller!.value.isInitialized) {
return Container();
}
return MaterialApp(
home: Stack(
fit: StackFit.expand,
children: [
RotatedBox(
quarterTurns: 1 - controller!.description.sensorOrientation ~/ 90,
child: CameraPreview(controller!),
),
CameraPreview(controller!),
Align(
alignment: Alignment.bottomCenter,
child: ElevatedButton(
onPressed: () async {
// Restore the constraint before navigating away
// DO await here to avoid any other screen in
// landscape mode
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
]);
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => WelcomeScreen()),
);
},
child: Text('Press me to go Home'),
),
),
Align(
alignment: Alignment.bottomRight,
child: FloatingActionButton(
onPressed: () async {
if (!takingPicture) {
takingPicture = true;
controller!.takePicture().then(
(value) {
selectedImage = value;
setState(() {});
takingPicture = false;
},
);
}
},
),
),
Align(
alignment: Alignment.bottomLeft,
child: selectedImage != null
? Container(
height: 100,
width: 200,
child: Image.file(
File(selectedImage!.path),
),
)
: Container(),
),
],
),
);
}
}
I am a newbie in flutter and this is my first real use app.
This is what i want to achieve my app is going to be used to detect number-plates automatically when the camera would be pointed on the numberplate, for the text detection part i am going to use flutter ml kit. How should i write the start image stream method if i want the output of 10 images in the File data type which I would then add to my ImagePathList.
I did do research on this, but i did not find anything related to what i wanted to achieve, there are a few blog posts using this but they have not explained it properly so i turned to stack overflow.
I want the functionality to be like this
This is what my camera_screen looks like
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:firebase_ml_vision/firebase_ml_vision.dart';
import 'package:flutter/services.dart';
import 'package:npgroups/npgroups.dart';
import 'package:society_app/screens/result_screen.dart';
import 'package:society_app/widgets/common_drawer.dart';
import 'package:camera/camera.dart';
import 'dart:async';
import 'package:numeric_keyboard/numeric_keyboard.dart';
class CameraScreen extends StatefulWidget {
final CameraDescription camera;
static String id = 'camera_screen';
CameraScreen({required this.camera});
#override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<CameraScreen> {
Widget buildButton(String buttonText){
return Container(
height: MediaQuery.of(context).size.height * 0.1 * 0.85,
color: Colors.blueAccent,
child: FlatButton(
onPressed: () {},
child: Text(
buttonText,
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.normal,
color: Colors.white
),
)
),
);
}
late CameraController _controller;
late Future<void> _initializeControllerFuture;
late Npgroups _npgroups;
List imagePathList = [];
List<String?> detectedWordList = [];
static const MethodChannel _channel = const MethodChannel('tflite');
String? resultText;
late int imageHeight;
late int imageWidth;
bool? get isPaused => null;
#override
void initState() {
// TODO: implement initState
super.initState();
_controller = CameraController(
// Get a specific camera from the list of available cameras.
widget.camera,
// Define the resolution to use.
ResolutionPreset.medium,
);
_initializeControllerFuture = _controller.initialize();
initPlatformState();
}
Future<void> initPlatformState() async {
_npgroups = Npgroups(listenToNumplate);
await _npgroups.startListening();
}
#override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
Future getNumberPlate(image) async {
FirebaseVisionImage mlImage = FirebaseVisionImage.fromFile(image);
TextRecognizer recognizeText = FirebaseVision.instance.textRecognizer();
VisionText readText = await recognizeText.processImage(mlImage);
for (TextBlock block in readText.blocks) {
for (TextLine line in block.lines) {
for (TextElement word in line.elements) {
resultText = word.text;
_npgroups.processNumberplate(resultText!);
}
}
}
if (resultText == null) {
print('null');
} else {
detectedWordList.add(resultText);
}
}
listenToNumplate(String numplate) {
//Consume the numplate
}
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: CommonDrawer(),
appBar: AppBar(
title: Text(
'Camera'
),
),
body: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
children: [
AspectRatio(aspectRatio: _controller.value.aspectRatio - 0.2,
child: CameraPreview(_controller)),
Positioned(
bottom: 10,
left: 5,
child: Row(
children: [
VehicleButton(icon: Icons.motorcycle_outlined,),
SizedBox(width: 35),
VehicleButton(icon: Icons.directions_car,)
],
),
)
],
),
Row(
children: [
Container(
width: MediaQuery.of(context).size.width * .99,
child: Table(
children: [
TableRow(
children: [
buildButton('1'),
buildButton('2'),
buildButton('3')
]
),
TableRow(
children: [
buildButton('4'),
buildButton('5'),
buildButton('6')
]
),
TableRow(
children: [
buildButton('7'),
buildButton('8'),
buildButton('9')
]
),
TableRow(
children: [
buildButton('↻'),
buildButton('0'),
buildButton('⌫')
]
),
],
),
)
],
)
],
);
} else {
// Otherwise, display a loading indicator.
return const Center(child: CircularProgressIndicator());
}
},
),
);
}
}
class VehicleButton extends StatelessWidget {
final IconData icon;
VehicleButton({required this.icon});
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {},
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 17, horizontal: 50),
child: Icon(
icon,
color: Colors.white,
size: 45,
),
),
style: ButtonStyle(
shape: MaterialStateProperty.all(RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)))
),
);
}
}
Blockquote
You can do something like that
#override
void initState() {
super.initState();
controller = CameraController(widget.cameras[0], ResolutionPreset.medium,
enableAudio: false);
controller.initialize().then((_) async {
if (!mounted) {
return;
}
setState(() {});
await controller.startImageStream((CameraImage availableImage) async {
_scanText(availableImage);
});
}