We have a problem about our delivery system with progress indicator. Does anyone can suggest a library of progress indicator for flutter. The progress has a shape design. The sample image below.
Progress indicator image sample
You can achieve this using a Row, Containers and CustomClipper class. I've created a library for this purpose. You can use the library from here: progress_stepper.
The following code creates a stepper:
ProgressStepper(
width: 300,
height: 15,
stepCount: 5,
builder: (index) {
double widthOfStep = 300 / 5;
if (index == 1) {
return ProgressStepWithArrow(
width: widthOfStep,
defaultColor: Color(0xFFCECECF),
progressColor: Color(0xFFFBB040),
wasCompleted: true,
);
}
return ProgressStepWithChevron(
width: widthOfStep,
defaultColor: Color(0xFFCECECF),
progressColor: Color(0xFFFBB040),
wasCompleted: false,
);
},
)
It will create a Stepper like the following image:
You can copy paste run full code below
You can use package https://pub.dev/packages/clippy_flutter and https://pub.dev/packages/step_progress_indicator
When step index == 0 return Point else return Chevron
code snippet
StepProgressIndicator(
totalSteps: 3,
currentStep: 2,
size: 20,
selectedColor: Colors.orangeAccent,
unselectedColor: Colors.grey,
customStep: (index, color, _) => index == 0
? Point(
triangleHeight: 20.0,
edge: Edge.RIGHT,
child: Container(
color: color,
child: Center(child: Text('')),
))
: Chevron(
triangleHeight: 20.0,
edge: Edge.RIGHT,
child: Container(
color: color,
child: Center(child: Text('')),
)),
),
working demo
full code
import 'package:flutter/material.dart';
import 'package:clippy_flutter/clippy_flutter.dart';
import 'package:step_progress_indicator/step_progress_indicator.dart';
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: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
StepProgressIndicator(
totalSteps: 3,
currentStep: 2,
size: 20,
selectedColor: Colors.orangeAccent,
unselectedColor: Colors.grey,
customStep: (index, color, _) => index == 0
? Point(
triangleHeight: 20.0,
edge: Edge.RIGHT,
child: Container(
color: color,
child: Center(child: Text('')),
))
: Chevron(
triangleHeight: 20.0,
edge: Edge.RIGHT,
child: Container(
color: color,
child: Center(child: Text('')),
)),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
Related
so in my assignment i have to make this screen in flutter i did this so far but we havent learned much they said search for answers and i cant find everything
import 'package:flutter/material.dart';
import 'package:cupertino_icons/cupertino_icons.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Chat App',
debugShowCheckedModeBanner: false,
theme: ThemeData(
appBarTheme: const AppBarTheme(color: Color.fromRGBO(0, 0, 0, 1.0)),
),
home: const MyHomePage(title: 'Person'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => 0,
),
title: Text(widget.title),
),
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(image: AssetImage('images/background.png'))),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'',
),
Text(
'',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: const Color.fromRGBO(0, 0, 0, 1.0),
onPressed: () => 0,
tooltip: 'Record',
child: const Icon(Icons.mic),
),
);
}
}
I did try to do it but I cannot get to know how to add the icons in the appbar and the texts and text field so if anyone could help that would be amazing
answering your question quickly!
in AppBar use ListTile as a Widget in the title property and add leading and title inside ListTile.
To achieve action buttons, need to use action property in appbar then you can add IconButton.
Also take a look at widget catelogue
You can use Row on title and actions for right buttons.
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => 0,
),
title: Row(
children: [
CircleAvatar(),
Text(widget.title),
],
),
actions: [
IconButton(
onPressed: () {},
icon: Icon(Icons.more_vert),
),
],
),
Find more about AppBar
I have a simple Slider widget and I want to add multiple containers inside the track at different points.
Needed Outcome Image
Current Code
Slider(
max: 500,
value: _playerValue,
onChanged: (double value){
setState(() {
_playerValue = value;
});
},
),
I do not think this is possible only by using the SliderThemeData; or at least, no way that I am aware of. However, you can achieve this behaviour using Stack, with the markers shown behind a translucent track of the slider. Demo snippet below.
One thing to note is to make sure the container that has the stack of markers has horizontal margin that is same as the slider's overlay radius; otherwise, the marker container becomes wider than the track.
IMPORTANT: I put this snippet together rapidly only to demonstrate the possibility of showing markers behind a slider's track. The dimensions of the track and the markers are hard-coded, which is very likely not what you want. I do not recommend using it as is, but only as a guide.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Slider with Markers',
theme: ThemeData(
primarySwatch: Colors.blue,
brightness: Brightness.dark,
),
home: Home(),
);
}
}
class Home extends StatefulWidget {
Home({Key? key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
double sliderValue = 50;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("Slider With Markers"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SliderTheme(
data: SliderTheme.of(context).copyWith(
activeTrackColor: Colors.white60,
inactiveTrackColor: Colors.white30,
thumbColor: Colors.white,
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 10),
overlayShape: RoundSliderOverlayShape(overlayRadius: 12),
trackHeight: 12,
),
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: double.infinity,
margin: const EdgeInsets.symmetric(horizontal: 12),
child: Stack(
alignment: Alignment.centerLeft,
children: <Widget>[
marker(left: 15, width: 30),
marker(left: 150, width: 50),
marker(left: 300, width: 100),
],
),
),
Slider(
value: sliderValue,
min: 0,
max: 100,
onChanged: ((value) {
setState(() {
sliderValue = value;
});
}),
),
],
),
)
],
),
),
);
}
Widget marker({required double left, required double width}) {
return Container(
height: 12,
width: width,
margin: EdgeInsets.only(left: left),
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(18),
),
);
}
}
Trying to use FabCircularMenu package and I am trying to display icons inside the FAB using a List. However, the button is showing nothing.
List _fabBarIcons = [
FaIcon(FontAwesomeIcons.search),
FaIcon(FontAwesomeIcons.briefcase),
FaIcon(FontAwesomeIcons.users),
FaIcon(FontAwesomeIcons.calendar),
FaIcon(FontAwesomeIcons.cog),
];
...List.generate(
_fabBarIcons.length,
(index) {
Ink(
decoration: const ShapeDecoration(
color: Colors.cyan,
shape: CircleBorder(),
),
child: IconButton(
icon: _fabBarIcons[index],
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
),
);
return Container(
height: 0,
);
},
),
I've tried to add colors to make it appear or other stuffs. I get zero error on the debug console. I have no clue why these IconButtons are not showing up here.
You cannot see anything because you are returning a Container from List.generate. Instead you should be returning the Ink widget. Please see the code below :
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Test(),
),
),
);
}
}
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
bool changeColor = false;
List _fabBarIcons = [
Icon(Icons.ac_unit),
Icon(Icons.access_time),
Icon(Icons.accessible),
Icon(Icons.ad_units),
Icon(Icons.search),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(
_fabBarIcons.length,
(index) {
return Ink(
decoration: const ShapeDecoration(
color: Colors.cyan,
shape: CircleBorder(),
),
child: IconButton(
onPressed: () {},
icon: _fabBarIcons[index],
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
),
);
},
),
),
);
}
}
I want to display a "Close keyboard" button above the keyboard when it is visible.
I know that the resizeToAvoidBottomInset can impact how the keyboard interact with the rest of the application, however it doesn't do exactly what I want.
I have a background image and others widgets (not shown in the sample below) which should not be resized and not moved when the keyboards is shown. This is an ok behavior when the resizeToAvoidBottomInset attribute is set to false.
However, I would like to add a button which should appear above the keyboard.
How can I do that? I only want one widget floating above the keyboard, not all the app.
Here is a sample code :
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
var home = MyHomePage(title: 'Flutter Demo Home Page');
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: home,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(widget.title),
),
body: _getBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _getBody() {
return Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/sample.jpg"), fit: BoxFit.fitWidth)),
// color: Color.fromARGB(50, 200, 50, 20),
child: Column(
children: <Widget>[TextField()],
),
),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 50,
child: Text("Aboveeeeee"),
decoration: BoxDecoration(color: Colors.pink),
),
),
]);
}
}
Your Positioned widget has a bottom of 0, replacing with an appropriate value should do the job.
MediaQuery.of(context).viewInsets.bottom will give you the value of the height covered by the system UI(in this case the keyboard).
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
var home = MyHomePage(title: 'Flutter Demo Home Page');
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: home,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Text(widget.title),
),
body: _getBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _getBody() {
return Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/sample.jpg"), fit: BoxFit.fitWidth)),
// color: Color.fromARGB(50, 200, 50, 20),
child: Column(
children: <Widget>[TextField()],
),
),
Positioned(
bottom: MediaQuery.of(context).viewInsets.bottom,
left: 0,
right: 0,
child: Container(
height: 50,
child: Text("Aboveeeeee"),
decoration: BoxDecoration(color: Colors.pink),
),
),
]);
}
}
2022 Update
A PR was merged that provides platform-synchronized animations for closing/opening the keyboard. See the PR in effect here.
Detailed Answer
To achieve keyboard-visibility-based animated padding, here are a few modifications over #10101010's great answer:
If you want the bottom change when keyboard changes visibility to be animated AND you want extra padding under your floating child then:
1- Use keyboard_visibility flutter pub
To listen when keyboard is appearing/disappearing, like so:
bool isKeyboardVisible = false;
#override
void initState() {
super.initState();
KeyboardVisibilityNotification().addNewListener(
onChange: (bool visible) {
isKeyboardVisible = visible;
},
);
}
Optionally you can write your own native plugins, but it's already there you can check the pub's git repo.
2- Consume visibility flag in your AnimatedPostioned:
For fine-tuned animated padding, like so:
Widget _getBody() {
double bottomPadding = 0;
if (isKeyboardVisible) {
// when keyboard is shown, our floating widget is above the keyboard and its accessories by `16`
bottomPadding = MediaQuery.of(context).viewInsets.bottom + 16;
} else {
// when keyboard is hidden, we should have default spacing
bottomPadding = 48; // MediaQuery.of(context).size.height * 0.15;
}
return Stack(children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/sample.jpg"), fit: BoxFit.fitWidth)),
// color: Color.fromARGB(50, 200, 50, 20),
child: Column(
children: <Widget>[TextField()],
),
),
AnimatedPositioned(
duration: Duration(milliseconds: 500),
bottom: bottomPadding,
left: 0,
right: 0,
child: Container(
height: 50,
child: Text("Aboveeeeee"),
decoration: BoxDecoration(color: Colors.pink),
),
),
]);
}
3- Keyboard-specific animation curve and duration for synchronized animation
For now this is still an known ongoing issue
You can use the bottomSheet of a Scaffold widget.
Example:
return Scaffold(
appBar: AppBar(
title: const Text("New Game"),
),
bottomSheet: Container(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
color: Colors.blue,
child: const SizedBox(
width: double.infinity,
height: 20,
child: Text("Above Keyboard"),
))
...
)
You can use bottomSheet parameter of the Scaffold, which keep a persistent bottom sheet. See below code.
class InputScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Close')),
bottomSheet: Container(
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
color: Colors.black,
child: const SizedBox(width: double.infinity, height: 10)),
body: Column(
children: [
const TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter your input here',
),
),
ElevatedButton(
onPressed: () {},
child: const Text('Submit'),
),
],
),
);
}
}
check this package, it can show a dismiss button above the keyboard.
I was looking at the properties for the different dialog classes and didn't see anything that would change it's shape. Is there a way to change a dialogs shape?
You can create a variety of shaped dialogs using Container in combination with existing clipping widgets (Painting and Effect Widgets) or by extending CustomClipper. The below will give you a diamond-shaped dialog. There are existing widgets like ClipOval that work out of the box without any customization (see screenshot below). If you want to try out ClipOval, simply replace ClipPath with ClipOval and comment out clipper:. Check out the painting.dart class to learn about creating custom paths.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Shaped Dialog Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
dialogBackgroundColor: Colors.transparent,
),
home: MyHomePage(title: 'Flutter Shaped Dialog Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
_showShapedDialog();
}),
);
}
_showShapedDialog() {
showDialog(
context: context,
builder: (context) {
return Padding(
padding: const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0),
child: ClipPath(
child: Material(
color: Colors.white,
child: Center(
child: Container(
alignment: FractionalOffset.center,
height: MediaQuery.of(context).size.width / 2.0,
width: MediaQuery.of(context).size.width / 2.0,
decoration: BoxDecoration(
border: Border.all(),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: Text(
'Clipping to a path is expensive. Certain shapes have more optimized widgets.',
textAlign: TextAlign.center,
),
),
FlatButton(
child: Text(
'OK',
style: TextStyle(color: Colors.blue),
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
),
),
clipper: _MyClipper(), // Comment this out if you want to replace ClipPath with ClipOval
),
);
},
);
}
}
class _MyClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
final path = Path();
path.lineTo(size.width / 2.0, 0.0);
path.lineTo(0.0, size.height / 2.0);
path.lineTo(size.width / 2.0, size.height);
path.lineTo(size.width, size.height / 2.0);
path.lineTo(size.width / 2.0, 0.0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Like that
Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
child: Text('Dialog'),
);
AlertDialog(
shape: RoundedRectangleBorder(borderRadius:
BorderRadius.all(Radius.circular(15))),
title: Text('Your title!'),
content: Container(),
);