I have a CircularProgressIndicator that is meant to display progress when the user presses a button. However, when I open the screen that uses this class it shows a loading animation and I'm not sure why. When the screen opens, it shouldn't show the animation until the user presses the button.
When the screen opens you see something similar to the animation on this page: https://www.c-sharpcorner.com/article/create-chrome-like-loading-animation/
class _MsgInputState extends State<MsgInput> with TickerProviderStateMixin {
AnimationController? controller;
#override
void initState() {
super.initState();
initialize();
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
void initialize() async {
controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 3),
)..addListener(() {
setState(() {});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Align(
alignment: Alignment.bottomLeft,
child: Column(
children: [
Row(
children: [
GestureDetector(
onTap: () async {
controller?.forward();
},
onLongPressDown: (details) async {
controller?.forward();
},
onLongPressUp: () async {
controller?.stop();
controller?.reset();
},
child: Text('Record'),
),
],
),
Row(
children: <Widget>[
SizedBox(width: 100),
CircularProgressIndicator(
value: controller?.value,
semanticsLabel: 'Linear progress indicator',
),
],
),
],
),
)
);
}
If the value provided to a CircularProgressIndicator is null it just defaults to a spinnging animation.
In the beginnin controller?.value probably returns null. Change it to value: controller?.value ?? 0 so that while it's null 0 is used as a value.
EDIT:
change
CircularProgressIndicator(
value: controller?.value,
semanticsLabel: 'Linear progress indicator',
),
to
CircularProgressIndicator(
value: controller?.value ?? 0,
semanticsLabel: 'Linear progress indicator',
),
Here is a quick examples on how the provided example could be achieved:
class StateProgress extends StatelessWidget {
const StateProgress({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const Center(
child: SizedBox(
height: 50,
width: 50,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(Colors.blueAccent /*Should be the color of the indicator*/),
backgroundColor: Colors.white, // Could be made to match the color of the background the indicator is on
),
),
);
}
}
Related
I'm using animated icon for open and closing side menu into my app. I need to change the closing icon color Red and opening icon color will be white.
AnimatedIcon(
progress: _animationController.view,
icon: menuClose,
color: menuIconColor, >need to apply condition here
size: 25.sp,
)
Full code of the button are given below
Align(
alignment: Alignment(0, .99),
child: GestureDetector(
onTap: () {
onIconPressed();
},
child: ClipRRect(
borderRadius: BorderRadius.circular(80),
child: Container(
width: 50.w,
height: 45.h,
color: colorAnimatedButton,
alignment: Alignment.center,
child: AnimatedIcon(
progress: _animationController.view,
icon: menuClose,
color: iconColor,
size: 25.sp,
),
),
),
),
)
Try with this code i used null safety sdk.
class AnimIconTest extends StatefulWidget {
const AnimIconTest({Key? key}) : super(key: key);
#override
_AnimIconTestState createState() => _AnimIconTestState();
}
class _AnimIconTestState extends State<AnimIconTest>
with TickerProviderStateMixin {
late AnimationController _animationController;
#override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 400),
);
}
Color iconColor = Colors.white;
#override
void dispose() {
_animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Colors.blueAccent,
body: Center(
child: InkWell(
onTap: () {
if (_animationController.status == AnimationStatus.completed) {
_animationController.reverse();
setState(() {
iconColor = Colors.white;
});
} else {
_animationController.animateTo(1.0);
setState(() {
iconColor = Colors.red;
});
}
},
child: AnimatedIcon(
progress: _animationController,
icon: AnimatedIcons.menu_close,
color: iconColor,
),
),
),
),
);
}
}
Hello i have been stock here trying to figure out what am doing wrong, the male and female reuseable cards are surpose to change color when tapped but after placing the GestureDetector inside my card Class it stopped working. The color refuse to change when tapped, take a look at the code below.
import 'package:bmi_calculator/card_icon.dart';
import 'package:bmi_calculator/cards.dart';
import 'package:flutter/material.dart';
Color activeCardColor = const Color(0XFF1D1E33);
Color inactiveCardColor = const Color(0XFF111328);
Color buttomContainerColor = const Color(0xffeb1555);
const double buttomContainerHeight = 70.0;
enum Gender {
male,
female,
}
class InputPage extends StatefulWidget {
const InputPage({Key? key}) : super(key: key);
#override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
Gender? selectedGender;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BMI CALCULATOR'),
),
body: Column(
children: [
Expanded(
child: Row(
children: [
Expanded(
child: ReuseableCard(
ontapped: () {
setState(() {
selectedGender = Gender.male;
});
},
colour: selectedGender == Gender.male
? activeCardColor
: inactiveCardColor,
cardChild: const CardIcon(Icons.male, 'Male'),
),
),
Expanded(
child: ReuseableCard(
ontapped: () {
setState(() {
selectedGender = Gender.female;
});
},
colour: selectedGender == Gender.female
? activeCardColor
: inactiveCardColor,
cardChild: const CardIcon(Icons.male, 'Female'),
),
)
],
),
),
Expanded(
child: ReuseableCard(
colour: activeCardColor,
),
),
Expanded(
child: Row(
children: [
Expanded(
child: ReuseableCard(
colour: activeCardColor,
),
),
Expanded(
child: ReuseableCard(
colour: activeCardColor,
),
)
],
),
),
Container(
margin: const EdgeInsets.only(top: 10.0),
color: buttomContainerColor,
height: buttomContainerHeight,
width: double.infinity,
)
],
));
}
}
And here is my Card Class
import 'package:flutter/material.dart';
class ReuseableCard extends StatelessWidget {
final Color? colour;
final Widget? cardChild;
final void Function()? ontapped;
const ReuseableCard({this.colour, this.cardChild, this.ontapped});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
ontapped;
print('Button Pressed');
},
child: Container(
child: cardChild,
margin: const EdgeInsets.all(10),
width: double.infinity,
decoration: BoxDecoration(
color: colour,
borderRadius: BorderRadius.circular(10.0),
),
),
);
}
}
add brackets to the function call
onTap: () {
ontapped(); // here
print('Button Pressed');
},
The problem is in passing the ontapped function. When you simply place ontapped without Parenthesis () the function will not be called so you need to change that in following ways. When using Lambda function you have options to pass function
For multiple functions
onTap: () {
ontapped(); // here
},
For single function
onTap: ontapped, // here
I have a request function and I want to show a progress bar before loading data but idk how to do that. can someone show me an example?
This code calls your function after running the linear progress indicator for a specified time.
The script makes use of no external libraries
import 'dart:async';
import 'package:flutter/material.dart';
class ProgressBarCall extends StatefulWidget {
const ProgressBarCall({ Key? key }) : super(key: key);
#override
_ProgressBarCallState createState() => _ProgressBarCallState();
}
class _ProgressBarCallState extends State<ProgressBarCall> {
double _value = 0;
#override
Widget build(BuildContext context) {
checkIndicator(delay: 2);
return Scaffold(
body: Column(
children: [
LinearProgressIndicator(
backgroundColor: Colors.grey,
color: Colors.green,
minHeight: 5,
value: _value,
),
Expanded(
child: Container(child: Text("Perform function after loading"),),
),
],
),
);
}
void checkIndicator({delay = 2}){
new Timer.periodic(
Duration(milliseconds: delay*100),
(Timer timer){
setState(() {
if(_value == 1) {
timer.cancel();
performFunction();
}
else {
_value = _value + 0.1;
}
});
}
);
}
void performFunction(){
//call your function after the loading
}
}
The performFunction() method can be used to load your data Set the duration of the linear progress indicator by setting the delay in the checkIndicator() method.
You can implement flutter_easyloading package, https://pub.dev/packages/flutter_easyloading
for the progress widget is self you can use [CircularProgressIndicator] https://api.flutter.dev/flutter/material/CircularProgressIndicator-class.html)
for managing the state show loading -> then the actual data -> in case of failure show the error message and stop loading
this can be achieved throw many different ways
1- the easies one FutureBuilder
FutureBuilder<String>(
future: _calculation, // a previously-obtained Future<String> or null
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
List<Widget> children;
if (snapshot.hasData) {
children = <Widget>[
const Icon(
Icons.check_circle_outline,
color: Colors.green,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Result: ${snapshot.data}'),
)
];
} else if (snapshot.hasError) {
children = <Widget>[
const Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
children = const <Widget>[
SizedBox(
child: CircularProgressIndicator(),
width: 60,
height: 60,
),
Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
)
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: children,
),
);
},
);
or you can use any state management you want
bloc (example)[https://bloclibrary.dev/#/flutterweathertutorial]
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);
});
}
I have a quantity that needs to be updated in the parent widget. Quantity needs to be updated when pressing + or - Icon in the child widget. I passed the callback function the the child stateless widget, but it is not working. Instead I get an error saying setstate() or markneedsbuild() called during build.
This is the parent widget
class Wash extends StatefulWidget {
#override
_WashState createState() => _WashState();
}
class _WashState extends State<Wash> {
int quantity = 0;
void updateQuantity(command) {
if (command == 'add') {
setState(() {
quantity++;
});
} else {
setState(() {
quantity--;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: OrderTile(
imgPath: 'shorts',
itemType: 'Shorts',
quantityCallBack: updateQuantity,
),
);
}
This is the child widget
class OrderTile extends StatelessWidget {
OrderTile({this.itemType, this.imgPath, this.quantityCallBack});
final String imgPath;
final String itemType;
final Function quantityCallBack;
#override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(12.0),
child: Row(
children: <Widget>[
Expanded(
flex: 1,
child: CircleAvatar(
backgroundImage: AssetImage('images/${imgPath}.jpg'),
radius: 30.0,
),
),
Expanded(
flex: 3,
child: _Description(
title: itemType,
),
),
GestureDetector(
onTap: quantityCallBack('add'),
child: Icon(
Icons.add,
size: 24.0,
),
),
SizedBox(
width: 14,
),
Text('1'),
SizedBox(
width: 14,
),
GestureDetector(
onTap: quantityCallBack('remove'),
child: Icon(
Icons.remove,
size: 24.0,
),
),
],
),
);
}
}
Am I doing the right thing for the function call back implementation?
You're calling your callback function in the wrong way inside your onTap callback. Change:
onTap: quantityCallBack('add'),
for
onTap: () => quantityCallBack('add'),
You can only pass a function the way you passed if they have the same type. In this case the onTap is void function() it doesn't have any arguments.
Also, your not passing the updated quantity value to your Text Widget