Working in flutter and having issues getting my code to work. it was working previously and it was getting a parent widget error and unbounded errors. I had some formatting issues i was working through with the appbar I was working through. currently I have the app bar working as I want it, but nothing will render below, and I am getting an error telling me i cant be null, but i cant figure out why not? and what i need to do to get it to work.
My code:
main:
import 'package:flutter/material.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'widgets/alertsfeeddata.dart';
import 'widgets/bullbearindicator.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: Scaffold(
appBar: AppBar(
title: Padding(
padding: const EdgeInsets.all(75),
child: Image.asset('assets/logos/1.png'),
),
bottom: PreferredSize(
preferredSize: const Size.fromHeight(5),
child: Container(
color: Colors.black,
height: 5,
child: Container(
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(width: 5, color: Colors.green),
),
),
),
),
),
),
backgroundColor: Colors.black,
body: Column(
children: <Widget>[
const BullBearIndicator(
key: null,
),
Align(
child: Expanded(
child: ListView(children: <Widget>[
Container(
padding: const EdgeInsets.all(15.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularPercentIndicator(
radius: 45.0,
lineWidth: 4.0,
percent: 0.10,
center: const Text("10%"),
backgroundColor: Colors.red,
progressColor: Colors.green,
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
),
CircularPercentIndicator(
radius: 45.0,
lineWidth: 4.0,
percent: 0.30,
center: const Text("30%"),
progressColor: Colors.orange,
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
),
CircularPercentIndicator(
radius: 45.0,
lineWidth: 4.0,
percent: 0.60,
center: const Text("60%"),
progressColor: Colors.yellow,
),
Padding(
padding: const EdgeInsets.all(30.0),
child: WebhookDataList(),
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
),
],
),
)
]),
),
),
],
),
),
);
}
}
BullBearIndicator:
import 'package:flutter/material.dart';
import 'package:percent_indicator/percent_indicator.dart';
class BullBearIndicator extends StatelessWidget {
final double totAggr;
final double btc;
final double eth;
final double alt;
const BullBearIndicator({
required Key key,
this.totAggr = 0.88,
this.btc = 0.71,
this.eth = 0.71,
this.alt = 0.78,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return CircularPercentIndicator(
radius: 130.0,
animation: true,
animationDuration: 1200,
lineWidth: 15.0,
percent: totAggr,
center: CircularPercentIndicator(
radius: 108.0,
lineWidth: 12.5,
animation: true,
percent: btc,
center: CircularPercentIndicator(
radius: 90.0,
lineWidth: 12.5,
animation: true,
percent: eth,
center: CircularPercentIndicator(
radius: 72,
lineWidth: 12.5,
percent: alt,
center: totAggr > 0.51
? Image.asset('assets/logos/bull.png')
: Image.asset('assets/logos/bear.png'),
backgroundColor: Colors.red,
progressColor: Colors.green,
),
circularStrokeCap: CircularStrokeCap.butt,
backgroundColor: Colors.red,
progressColor: Colors.green,
),
circularStrokeCap: CircularStrokeCap.butt,
backgroundColor: Colors.red,
progressColor: Colors.green,
),
footer: const Text(
"BULL/BEAR",
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 17.0),
),
circularStrokeCap: CircularStrokeCap.round,
backgroundColor: Colors.red,
progressColor: Colors.green,
);
}
}
Try the following code:
const BullBearIndicator(),
Also, you need to change your code to:
const BullBearIndicator({
this.totAggr = 0.88,
this.btc = 0.71,
this.eth = 0.71,
this.alt = 0.78,
super.key,
})
or
const BullBearIndicator({
Key? key,
this.totAggr = 0.88,
this.btc = 0.71,
this.eth = 0.71,
this.alt = 0.78,
}) : super(key: key);
Related
I want to create a progress bar in flutter which is like this
I get the data of week from backend but I have to create it this way.
and the icon on weeks or survey should be touchable.
thanks in advance.
Still a lot of things to change, but i thing it should be enough for the beginning
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
#override
Widget build(BuildContext context) {
List<String> points = [
'Survey',
'Week 1',
'Week 2',
'Week 3',
'Week 4',
];
var lineWidth =
MediaQuery.of(context).size.width - 16.0; // screen width - 2 * padding
var space = lineWidth / points.length; //space between dots
var currentSteps = 3; // <---- change this one
return Scaffold(
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: SizedBox(
height: 60.0,
child: Stack(
children: [
//grey line
Positioned(
top: 15,
left: 0,
right: 0,
child: Container(
height: 2.0,
width: double.infinity,
color: Colors.grey,
),
),
//red line
Positioned(
top: 15,
left: 0,
child: Container(
height: 2.0,
width: space * (currentSteps - 1) + space / 2,
color: Colors.orange,
),
),
//circles
Row(
children: points
.asMap()
.map((i, point) => MapEntry(
i,
SizedBox(
width: space,
child: Column(
children: [
Stack(
children: [
Container(
height: 30.0,
width: 30.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
width: 1.5,
color: i == currentSteps - 1
? Colors.orange
: Colors.transparent,
),
),
child: Center(
child: Container(
height: 20.0,
width: 20.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: i < currentSteps
? Colors.orange
: Colors.grey,
),
),
),
),
if (i < currentSteps - 1)
const SizedBox(
height: 30.0,
width: 30.0,
child: Center(
child: Icon(
Icons.check,
size: 16.0,
color: Colors.white,
),
),
),
],
),
const SizedBox(height: 4.0),
Text(
point,
textAlign: TextAlign.left,
style: TextStyle(
color: i < currentSteps
? Colors.orange
: Colors.grey,
),
),
],
),
),
))
.values
.toList(),
),
],
),
),
),
),
);
}
}
You can try basic Stepper widget with type: StepperType.horizontal. As for the UI you like im_stepper package. If it fails to satisfy you can create custom widget with Stack and Row.
Try basic Stepper widget of flutter. if its not working properly then you need to create custom widget.
im using sliding_up_panel package i want to add my location button above the panel so i build it like this, the problem is there is a shadow after i set my sliding_up_panel color to Colors.transparent and i cannot get rid of it, or if there is any good approach to build this common map things my location and sliding panel because i don't know any method to build it
this is my panel code
SlidingUpPanel(
controller: _panelC,
minHeight: MediaQuery.of(context).size.height * 0.15,
maxHeight: MediaQuery.of(context).size.height * 0.8,
panelSnapping: true,
snapPoint: 0.4,
color: Colors.transparent,
backdropOpacity: 0,
backdropColor: Colors.transparent,
backdropEnabled: false,
parallaxEnabled: true,
parallaxOffset: 0.5,
defaultPanelState: PanelState.CLOSED,
panelBuilder: (controller) {
return _buildPanel(controller);
},
body: _buildMap(),
),
this is my panel content
Widget _buildPanel(controller) {
return Column(
children: [
Align(
alignment: Alignment.centerRight,
child: ElevatedButton(
child: Icon(
Icons.my_location,
color: Colors.white,
),
onPressed: () {},
style: ElevatedButton.styleFrom(
fixedSize: const Size(48, 48),
shape: const CircleBorder(),
),
),
),
SizedBox(height: 16),
Expanded(
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(
top: Radius.circular(16),
),
),
child: Column(
children: [
// list of place to go
Expanded(
child: ListView(
controller: controller,
children: List.generate(
3,
(index) => _buildListTile(),
),
),
),
],
),
),
),
],
);
}
Let's just create a custom BoxShadow that takes the BlurStyle as parameter.
class CustomBoxShadow extends BoxShadow {
final BlurStyle blurStyle;
const CustomBoxShadow({
Color color = const Color(0xFF000000),
Offset offset = Offset.zero,
double blurRadius = 0.0,
this.blurStyle = BlurStyle.normal,
}) : super(color: color, offset: offset, blurRadius: blurRadius);
#override
Paint toPaint() {
final Paint result = Paint()
..color = color
..maskFilter = MaskFilter.blur(this.blurStyle, blurSigma);
assert(() {
if (debugDisableShadows)
result.maskFilter = null;
return true;
}());
return result;
}
}
Now we can use it like this :
import 'package:flutter/material.dart';
import 'package:sliding_up_panel/sliding_up_panel.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
body: SlidingUpPanel(
boxShadow: [
new CustomBoxShadow(
color: Colors.black,
offset: new Offset(10.0, 10.0),
blurRadius: 0.0,
blurStyle: BlurStyle.outer
)
],
panel: const Center(
child: Text('my slide content'),
),
body: const Center(
child: Text('my body'),
),
)
),
),
);
}
Play around with blurStye, blurRadius, offset to meet your need
I have a SliverAppBar looks like this is normal state which is what I want:
but when scrolling down the app bar doesn't respect the top safe area on its floating state:
here is my build method code
return Scaffold(
body: CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverSafeArea(
bottom: false,
sliver: SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 5),
sliver: SliverAppBar(
primary: false,
centerTitle: true,
actions: actions,
floating: true,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
title: const Text('title'),
),
),
),
SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
margin: const EdgeInsets.all(20),
color: Colors.amber,
);
},
childCount: 130,
),
),
],
),
);
I think you need a custom app bar for your purpose.
something like this
class FloatingAppBar extends StatelessWidget {
const FloatingAppBar(
this.title, {
this.actions = const <Widget>[],
Key? key,
this.leading = const BackButton(),
this.height = 48,
}) : super(key: key);
final String? title;
final List<Widget> actions;
final Widget leading;
final double height;
#override
Widget build(BuildContext context) {
//final Color bgColor = isDark(context) ? Colors.grey.shade800 : Colors.white;
return Center(
child: Container(
height: height,
width: MediaQuery.of(context).size.width - 20,
constraints: const BoxConstraints(maxWidth: 600),
decoration: BoxDecoration(
color: isDark(context) ? Colors.grey.shade800 : Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: <BoxShadow>[
BoxShadow(
color: isDark(context) ? Colors.black54 : Colors.grey.shade500,
blurRadius: 1,
spreadRadius: 0.1,
offset: const Offset(0, 0.7),
),
],
),
padding: const EdgeInsets.all(0),
margin: const EdgeInsets.only(top: 5),
child: Row(
children: <Widget>[
leading,
Expanded(
child: Center(
child: Text(
title ?? '',
textDirection: getTextDirection(title ?? ''),
style: const TextStyle(
fontWeight: FontWeight.bold,
//color: Colors.black87,
),
),
),
),
if (actions.isEmpty)
const IconButton(
padding: EdgeInsets.all(0),
iconSize: 20,
icon: Icon(iconArrowLeft, color: Colors.transparent),
onPressed: null,
),
//
...actions
],
),
),
);
}
}
I want to achieve have a round icon for the profile image like in this example:
But is not working for me, this is what I achieved so far:
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
ClipPath(
clipper: _AppBarProfileClipper(childHeight),
child: Container(
padding: const EdgeInsets.only(top: 48.0),
color: TheBaseColors.lightBlue,
height: height,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
leading,
FlatButton(
onPressed: null,
child: Text(
title,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 18.0,
color: Colors.white,
),
),
),
trailing,
],
),
),
),
Positioned(
bottom: childHeight / 2, //50
left: 0,
right: 0,
child: Align(
alignment: Alignment.bottomCenter,
child: child,
),
),
],
);
}
}
All the parameters are represented in the constructor and used in the code. But I cant figure out how to make that nice effect with the rounded icon.
Someone knows why is not working?
You can achieve given example like this:
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final double appBarHeight = 100.0;
final double spaceAroundRoundButton = 4.0;
final double roundedButtonSize = 64.0;
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return SafeArea(
child: Stack(
children: <Widget>[
Scaffold(
backgroundColor: Colors.white,
appBar: PreferredSize(
preferredSize:
Size(MediaQuery.of(context).size.width, appBarHeight),
child: ClipPath(
clipper: BottomClipper(),
child: Container(
alignment: Alignment.topLeft,
height: appBarHeight,
color: Colors.black,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
IconButton(
icon: Icon(
Icons.menu,
color: Colors.white,
),
onPressed: () {}),
Text(
'User Profile',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
),
onPressed: () {})
],
),
),
)),
body: Container(
alignment: Alignment.topCenter,
margin: EdgeInsets.only(
top:
roundedButtonSize * 0.75 + spaceAroundRoundButton + 16.0),
child: Text('Body'),
),
),
Positioned(
child: Container(
padding: EdgeInsets.all(spaceAroundRoundButton),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: RawMaterialButton(
elevation: 0,
constraints: BoxConstraints.tightFor(
width: roundedButtonSize, height: roundedButtonSize),
shape: StadiumBorder(
side: BorderSide(width: 4, color: Colors.grey)),
child: Icon(Icons.person),
onPressed: () {},
fillColor: Colors.white,
),
),
left: (size.width / 2) -
(roundedButtonSize / 2) -
spaceAroundRoundButton,
top: appBarHeight -
(roundedButtonSize * 0.25) -
spaceAroundRoundButton,
)
],
),
);
}
}
class BottomClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var path = Path();
path.lineTo(0.0, size.height * 0.75);
var firstControlPoint = Offset(size.width * 0.25, size.height);
var firstEndPoint = Offset(size.width * 0.5, size.height);
path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
firstEndPoint.dx, firstEndPoint.dy);
var secondControlPoint = Offset(size.width * 0.75, size.height);
var secondEndPoint = Offset(size.width, size.height * 0.75);
path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
secondEndPoint.dx, secondEndPoint.dy);
path.lineTo(size.width, 0.0);
path.close();
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Screenshot:
I'm rather new to Flutter/Dart so I could have made a foolish mistake. I have defined a LinearPercentIndicator in what I believe is a function inside my class _FourthRouteState. I call this function inside Widget build(BuildContext context) with 3 parameters: context, var1, var2 where var1 is a double between 0.0 and 1.0 and var2 is a text object.
The default PercentIndicator should display 75% whereas if the user presses the Confirm button, the percentage should change to 100%. It would be ideal if the animation of the LinearPercentIndicator starts over, since the value changes from 75 to 100.
The problem is that the LinearPercentIndicator is not displayed on my page and I don't receive any errors so I'm not sure what I'm doing wrong. If you could both help me with my code (I only included the relevant parts) and provide me with some relevant/useful documentation, that would be great!
import 'package:flutter/material.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:page_transition/page_transition.dart';
void main() {
runApp(MaterialApp(
theme:
ThemeData(accentColor: Colors.black87),
home: FourthRoute(),
));
}
class FourthRoute extends StatefulWidget {
final value;
FourthRoute({Key key, this.value}) : super(key: key);
#override
_FourthRouteState createState() => new _FourthRouteState();
}
class _FourthRouteState extends State<FourthRoute> {
var _textController = new TextEditingController();
var _formKey = GlobalKey<FormFieldState>();
getPercentageIndicator(context, var1,var2) {
setState(() {
LinearPercentIndicator(
width: MediaQuery
.of(context)
.size
.width - 50,
animation: true,
lineHeight: 20.0,
animationDuration: 2000,
percent: var1,
center: Text(var2),
linearStrokeCap: LinearStrokeCap.roundAll,
progressColor: Colors.green,
backgroundColor: Colors.green.withOpacity(0.2),
);
});
}
#override
Widget build(BuildContext context) {
Color foreground = Colors.green;
Color background = foreground.withOpacity(0.2);
return Scaffold(
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Color.fromRGBO(53, 73, 94, 0.9)),
),
Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 50.0),
),
Padding(
padding: EdgeInsets.fromLTRB(20.0,16.0,0.0,0.0), // left, top, right, bottom
child: getPercentageIndicator(context,0.75,"75%"),
),
],
),
Positioned(
bottom: 150.0,
right: 20.0,
child: ButtonTheme(
minWidth: 150.0,
child: RaisedButton(
padding: EdgeInsets.all(8.0),
child: Text('Confirm',
style: TextStyle(
fontSize: 24,
color: Colors.black87,
fontWeight: FontWeight.bold
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0)
),
color: Colors.white,
splashColor: Colors.blueGrey,
onPressed: () {
if (_formKey.currentState.validate()) {
getPercentageIndicator(context,1.0,"100%");
// Navigator.push(
// context,
// PageTransition(
// type: PageTransitionType.fade,
// child:HomePage(),
// duration: Duration(
// seconds: 1
// ),
// ),
// );
}
}
),
),
),
],
),
);
}
}
Why do you make instance of LinearPercentIndicator widget inside of setState in getPercentageIndicator? It makes no sense. You probably wanted just to return it:
getPercentageIndicator(context, var1,var2) {
return LinearPercentIndicator(
width: MediaQuery
.of(context)
.size
.width - 50,
animation: true,
lineHeight: 20.0,
animationDuration: 2000,
percent: var1,
center: Text(var2),
linearStrokeCap: LinearStrokeCap.roundAll,
progressColor: Colors.green,
backgroundColor: Colors.green.withOpacity(0.2),
);
}
By the way, you shouldn't use mediaquery size here. Use LayoutBuilder to change width depending on how much space your widget has:
getPercentageIndicator(context, var1,var2) {
return LayoutBuilder(
builder: (context, constraints) {
return LinearPercentIndicator(
width: constraints.maxWidth - 50,
animation: true,
lineHeight: 20.0,
animationDuration: 2000,
percent: var1,
center: Text(var2),
linearStrokeCap: LinearStrokeCap.roundAll,
progressColor: Colors.green,
backgroundColor: Colors.green.withOpacity(0.2),
);
}
);
}