Flutter- how to get currentValue out of FlutterSlider (flutter_xlider) - flutter

I am using the flutterSilder dependency since it gives me the possibility to use "FluterSliderSteps", making a non linear increase of the value possible (exponential).
Now I got the problem that I don't know how to get the current value out of the slider, in order to use it to display the value as text elsewhere or to save/use it.
Underneath I put some basic code, displaying the foundations. There is a padding field class with a text field on the top that saying "myFeedbackText" which should display the value instead. Does anybody have an Idea? Thank you! https://pub.dev/packages/flutter_xlider
class flutterSlider extends StatefulWidget {
#override
_flutterSliderState createState() => _flutterSliderState();
}
class _flutterSliderState extends State<flutterSlider> {
RangeValues range = RangeValues(1, 100);
double slide = 2;
#override
Widget build(BuildContext context) {
return new Scaffold(
body: Container(
color: Color(0xffE5E5E5),
child: Center(
child: Container(
child: Align(
child: Material(
color: Colors.white,
elevation: 14.0,
borderRadius: BorderRadius.circular(24.0),
shadowColor: Color(0x802196F3),
child: Container(
width: 350.0,
height: 400.0,
child: Column(
children: <Widget>[
SizedBox(height: 30,),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Text(
"myFeedbackText", // should display currentValue
style: TextStyle(
color: Colors.black, fontSize: 22.0),
)),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Builder( //Needed to find Scaffold.of(context) and display the snackbar
builder: (BuildContext context) {
return FlutterSlider(
values: [300],
max: 500,
min: 0,
onDragging: (handlerIndex, lowerValue, upperValue) {
setState(() {});
},
step: FlutterSliderStep(
step: 1, // default
isPercentRange: true, // ranges are percents, 0% to 20% and so on... . default is true
rangeList: [
FlutterSliderRangeStep(from: 0, to: 100, step: 1),
FlutterSliderRangeStep(from: 100, to: 300, step: 5),
FlutterSliderRangeStep(from: 300, to: 500, step: 10),
]
),
);
}
),
),
),
],
)),
),
),
),
),
),
);
}
}

You can copy paste run full code below
You can define a variable _lowerValue and update it with onDragging and onDragCompleted
code snippet
double _lowerValue = 300;
...
Container(
child: Text(
"$_lowerValue",
...
FlutterSlider(
values: [_lowerValue],
max: 500,
min: 0,
onDragging:
(handlerIndex, lowerValue, upperValue) {
setState(() {
_lowerValue = lowerValue;
});
},
onDragCompleted:
(handlerIndex, lowerValue, upperValue) {
setState(() {
_lowerValue = lowerValue;
});
},
working demo
full code
import 'package:flutter/material.dart';
import 'package:flutter_xlider/flutter_xlider.dart';
class flutterSlider extends StatefulWidget {
#override
_flutterSliderState createState() => _flutterSliderState();
}
class _flutterSliderState extends State<flutterSlider> {
RangeValues range = RangeValues(1, 100);
double slide = 2;
double _lowerValue = 300;
#override
Widget build(BuildContext context) {
return new Scaffold(
body: Container(
color: Color(0xffE5E5E5),
child: Center(
child: Container(
child: Align(
child: Material(
color: Colors.white,
elevation: 14.0,
borderRadius: BorderRadius.circular(24.0),
shadowColor: Color(0x802196F3),
child: Container(
width: 350.0,
height: 400.0,
child: Column(
children: <Widget>[
SizedBox(
height: 30,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Text(
"$_lowerValue", // should display currentValue
style:
TextStyle(color: Colors.black, fontSize: 22.0),
)),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
child: Builder(
//Needed to find Scaffold.of(context) and display the snackbar
builder: (BuildContext context) {
return FlutterSlider(
values: [_lowerValue],
max: 500,
min: 0,
onDragging:
(handlerIndex, lowerValue, upperValue) {
setState(() {
_lowerValue = lowerValue;
});
},
onDragCompleted:
(handlerIndex, lowerValue, upperValue) {
setState(() {
_lowerValue = lowerValue;
});
},
step: FlutterSliderStep(
step: 1, // default
isPercentRange:
true, // ranges are percents, 0% to 20% and so on... . default is true
rangeList: [
FlutterSliderRangeStep(
from: 0, to: 100, step: 1),
FlutterSliderRangeStep(
from: 100, to: 300, step: 5),
FlutterSliderRangeStep(
from: 300, to: 500, step: 10),
]),
);
}),
),
),
],
)),
),
),
),
),
),
);
}
}
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: flutterSlider(),
);
}
}
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>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Related

Why isn't the BottomAppBar showing up?

I'm following this tutorial on youtube (https://www.youtube.com/watch?v=MW-KVmnXuiE) and at 01:27, when I tried to reload my emulator, the BottomAppBar didn't show up. There weren't any errors occurred though.
This is my main.dart file
import 'package:flutter/material.dart';
import 'package:secondlife_mobile/screens/home.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Perspective PageView',
theme: ThemeData(
useMaterial3: true,
),
home: const MyHomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomAppBar(
child: Row(
children: [
IconButton(onPressed: () {}, icon: const Icon(Icons.home)),
IconButton(onPressed: () {}, icon: const Icon(Icons.home)),
],
),
),
);
}
}
And this is my home.dart file
import 'package:flutter/material.dart';
import 'package:secondlife_mobile/PageViewHolder.dart';
import 'package:provider/provider.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final PageStorageBucket bucket = PageStorageBucket();
late PageViewHolder holder;
late PageController _controller;
double fraction =
0.57; // By using this fraction, we're telling the PageView to show the 50% of the previous and the next page area along with the main page
#override
void initState() {
super.initState();
holder = PageViewHolder(value: 2.0);
_controller = PageController(initialPage: 2, viewportFraction: fraction);
_controller.addListener(() {
holder.setValue(_controller.page);
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('AppBar'),
leading: IconButton(
onPressed: () {},
icon: const Icon(Icons.search_outlined),
),
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.more_vert),
),
],
),
body: SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 92.5,
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Playlist for you',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w400,
),
),
),
const SizedBox(height: 35),
Container(
child: Center(
child: AspectRatio(
aspectRatio: 1,
child: ChangeNotifierProvider<PageViewHolder>.value(
value: holder,
child: PageView.builder(
controller: _controller,
itemCount: 4,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return MyPage(
number: index.toDouble(),
fraction: fraction,
);
}),
),
),
),
),
const SizedBox(height: 2.0),
////Your Playlist of the week text
const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Playlist of the week',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
),
),
);
}
}
class MyPage extends StatelessWidget {
final number;
final double? fraction;
const MyPage({super.key, this.number, this.fraction});
#override
Widget build(BuildContext context) {
double? value = Provider.of<PageViewHolder>(context).value;
double diff = (number - value);
// diff is negative = left page
// diff is 0 = current page
// diff is positive = next page
//Matrix for Elements
final Matrix4 pvMatrix = Matrix4.identity()
..setEntry(3, 2, 1 / 0.9) //Increasing Scale by 90%
..setEntry(1, 1, fraction!) //Changing Scale Along Y Axis
..setEntry(3, 0, 0.004 * -diff); //Changing Perspective Along X Axis
final Matrix4 shadowMatrix = Matrix4.identity()
..setEntry(3, 3, 1 / 1.6) //Increasing Scale by 60%
..setEntry(3, 1, -0.004) //Changing Scale Along Y Axis
..setEntry(3, 0, 0.002 * diff) //Changing Perspective along X Axis
..rotateX(1.309); //Rotating Shadow along X Axis
return Stack(
fit: StackFit.expand,
alignment: FractionalOffset.center,
children: [
Transform.translate(
offset: const Offset(0.0, -47.5),
child: Transform(
transform: pvMatrix,
alignment: FractionalOffset.center,
child: Container(
decoration: BoxDecoration(boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
blurRadius: 11.0,
spreadRadius: 4.0,
offset: const Offset(
13.0, 35.0), // shadow direction: bottom right
)
]),
child: Image.asset(
"assets/images/image_${number.toInt() + 1}.jpg",
fit: BoxFit.fill),
),
),
),
],
);
}
}
And this is how my emulator looked like when I reloaded it.
As you can see, the BottomAppBar isn't showing up.
As far as I read your code, the HomePage class didn't get called.
Update the Scaffold inside your MyHomePage class with the BottomAppBar from your HomePage class.
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
bottomNavigationBar: BottomAppBar(
child: Row(
children: [
IconButton(onPressed: () {}, icon: const Icon(Icons.home)),
IconButton(onPressed: () {}, icon: const Icon(Icons.home)),
],
),
),
appBar: AppBar(
centerTitle: true,
title: const Text('AppBar'),
leading: IconButton(
onPressed: () {},
icon: const Icon(Icons.search_outlined),
),
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.more_vert),
),
],
),
body: SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 92.5,
),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Playlist for you',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w400,
),
),
),
const SizedBox(height: 35),
Container(
child: Center(
child: AspectRatio(
aspectRatio: 1,
child: ChangeNotifierProvider<PageViewHolder>.value(
value: holder,
child: PageView.builder(
controller: _controller,
itemCount: 4,
physics: const BouncingScrollPhysics(),
itemBuilder: (context, index) {
return MyPage(
number: index.toDouble(),
fraction: fraction,
);
}),
),
),
),
),
const SizedBox(height: 2.0),
////Your Playlist of the week text
const Padding(
padding: EdgeInsets.symmetric(horizontal: 35),
child: Text(
'Playlist of the week',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
),
),
);
}
}
It's because your are not using the widget HomePage anywhere.
You can add the MyHomePage widget as the body of the scaffold widget in the HomePage, like so:
class HomePage extends StatelessWidget {
const HomePage({super.key});
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomAppBar(
child: Row(
children: [
IconButton(onPressed: () {}, icon: const Icon(Icons.home)),
IconButton(onPressed: () {}, icon: const Icon(Icons.home)),
],
),
),
body: MyHomePage(),
);
}
}
And then your App widget would look like:
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Perspective PageView',
theme: ThemeData(
useMaterial3: true,
),
home: const HomePage(),
);
}
}

Flutter - How to insert the ad in every nth row (every 4th row) in listview.separated

I am using Listview.separated and I am using google_mobile_ads as the package to integrate the ads. I followed the example here but dint get the exact what I needed.
I called the banner ad in separatorBuilder but that either gives the divider or the ad after every nth row.
I need insert the after every 4th row in the listview.separated.
ListView.separated(
scrollDirection: Axis.vertical,
shrinkWrap: true,
controller: _scrollController,
itemCount: articleslist.length + 1,
itemBuilder: (BuildContext context, int index) {
if (index == articleslist.length) {
_loading = true;
return Center(
child: Row(
children: [
Container(
padding: EdgeInsets.all(5),
child: CircularProgressIndicator(
color: Colors.deepOrange[800],
),
),
SizedBox(
width: 15,
),
Text(
'Articles are being loaded...',
style: TextStyle(color: Colors.deepOrange[800]),
)
],
),
);
} else {
Text(
'No data to load',
style: TextStyle(color: Colors.deepOrange[800]),
);
}
if (articleslist.length == 0) {
return Container(
child: Center(
child: Text('Loading...',
style: TextStyle(color: Colors.deepOrange))));
} else {
var imgUrl = articleslist[index].img.toString();
imgUrl = BaseUrl + imgUrl.toString();
var title = articleslist[index].title;
title = title.replaceAll(RegExp(r'<[^>]*>'), '');
var body = articleslist[index].body;
body = body.replaceAll(RegExp(r'<[^>]*>'), '');
return InkWell(
onTap: () {
print('Tapped : ${articleslist[index].nid}');
print(index);
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => DetailPage(
articleslist[index].title,
articleslist[index].img,
articleslist[index].nid,
articleslist[index].uid,
articleslist[index].created,
)));
},
child: Container(
padding: EdgeInsets.fromLTRB(8.0, 6.0, 8.0, 0.0),
child: Row(
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
width: 120,
height: 75,
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: imgUrl == 'No img'
? Image.asset('images/placeholder.png',
height: 220, fit: BoxFit.cover)
: FadeInImage.assetNetwork(
placeholder: 'images/placeholder.png',
image: imgUrl,
height: 220,
fit: BoxFit.cover,
),
),
),
const SizedBox(
width: 20,
),
Expanded(
child: Column(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
title,
style: TextStyle(
color: Colors.black, fontSize: 16),
),
const SizedBox(
height: 10,
),
Text(
'author : $uid',
style: TextStyle(
fontSize: 10,
),
),
const SizedBox(
height: 5,
),
Text(
created,
style: TextStyle(
fontSize: 10,
),
)
],
),
),
],
),
),
);
}
},
separatorBuilder: (context, index) => Divider(),
),
You can add a item nth place using ListView.separated and '%' operator.
You just change from number '4' after '%' operator to what you want to add to nth place.
...
if ((index + 1) % 4 == 0) {
...
import 'package:flutter/material.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> {
FocusNode focusNode = FocusNode();
#override
void initState() {
super.initState();
focusNode.addListener(() {
print('1: ${focusNode.hasFocus}');
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
);
}
Widget _buildBody() {
return ListView.separated(
itemCount: 20,
separatorBuilder: (context, index) {
if ((index + 1) % 4 == 0) {
return Container(
height: 100,
color: Colors.yellow,
child: Text('it is ads'),
);
} else {
return Container();
}
},
itemBuilder: (context, index) {
return Container(
height: 100,
color: Colors.blue,
child: Text('item index: $index'),
);
},
);
}
}

How to move Scaffold's body along with bottomSheet on Flutter?

I'm trying to achieve a particular behavior for my Scaffold when showing a BottomSheet. I want the Scaffold's body to move along with the bottom sheet. That is, when the Bottomheet comes out, the body of the Scaffold should go up with it. Like the image at the right. I'm not sure if my approach is the correct one. Maybe there are other better options to make this behavior possible.
The code with which I'm currently working is here:
Scaffold(
backgroundColor: Colors.purple[100],
resizeToAvoidBottomInset: true,
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Container(
height: 900,
child: Builder(
builder: (context) => Container(
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
FocusScope.of(context).requestFocus(_focusNode);
if (bottomSheetIsOpen) {
bottomSheetIsOpen = false;
Navigator.of(context).pop();
}
},
child: Container(
width: double.infinity,
height: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(height: 50),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
),
width: 300,
child: TextField(
cursorWidth: 3,
cursorColor: Colors.purple,
onTap: () {
bottomSheetIsOpen = true;
showBottomSheet(
clipBehavior: Clip.hardEdge,
context: context,
builder: (context) => Container(
child: Container(
height: 200,
color: Colors.red,
),
),
);
},
controller: _controller,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
style: TextStyle(fontSize: 24),
showCursor: true,
readOnly: _readOnly,
),
),
Container(
height: 300,
width: 300,
color: Colors.yellow,
),
Container(
height: 250,
width: 300,
color: Colors.orange,
),
],
),
),
),
),
),
),
),
);
You could achieve this with a Stack and two AnimatedPositioned widget:
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Bottomsheet Demo',
debugShowCheckedModeBanner: false,
home: MyHomePage(),
);
}
}
class MyHomePage extends HookWidget {
#override
Widget build(BuildContext context) {
final _isOpenBottomSheet = useState(false);
return Scaffold(
appBar: AppBar(title: Text('Bottomsheet Demo')),
body: LayoutWithBottomSheet(
children: List.generate(
10,
(index) => Container(
height: 100,
color: Colors.red.withGreen(index * 25),
child: Center(
child: Text(
index.toString(),
style: TextStyle(fontSize: 24.0),
),
),
),
).toList(),
bottomSheetChild: Container(color: Colors.yellow),
bottomSheetHeight: 400,
animationSpeed: Duration(milliseconds: 300),
animationCurve: Curves.easeInOutQuad,
isOpenBottomSheet: _isOpenBottomSheet.value,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_isOpenBottomSheet.value = !_isOpenBottomSheet.value;
},
child: Icon(_isOpenBottomSheet.value
? Icons.arrow_downward
: Icons.arrow_upward),
),
);
}
}
class LayoutWithBottomSheet extends HookWidget {
final List<Widget> children;
final Widget bottomSheetChild;
final Duration animationSpeed;
final Curve animationCurve;
final double bottomSheetHeight;
final bool isOpenBottomSheet;
const LayoutWithBottomSheet({
Key key,
this.children,
this.bottomSheetChild,
this.animationSpeed,
this.animationCurve,
this.bottomSheetHeight,
this.isOpenBottomSheet,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final _scrollController = useScrollController();
final childrenBottom = useState<double>();
final bottomSheetBottom = useState<double>();
useEffect(() {
if (isOpenBottomSheet) {
childrenBottom.value = bottomSheetHeight;
bottomSheetBottom.value = 0;
if (_scrollController.hasClients) {
Future.microtask(
() => _scrollController.animateTo(
_scrollController.offset + bottomSheetHeight,
duration: animationSpeed,
curve: animationCurve,
),
);
}
} else {
childrenBottom.value = 0;
bottomSheetBottom.value = -bottomSheetHeight;
if (_scrollController.hasClients) {
_scrollController.animateTo(
_scrollController.offset - bottomSheetHeight,
duration: animationSpeed,
curve: animationCurve,
);
}
}
return;
}, [isOpenBottomSheet]);
return Stack(
children: [
AnimatedPositioned(
duration: animationSpeed,
curve: animationCurve,
left: 0,
right: 0,
top: 0,
bottom: childrenBottom.value,
child: ListView(
controller: _scrollController,
children: children,
),
),
AnimatedPositioned(
duration: animationSpeed,
curve: animationCurve,
left: 0,
right: 0,
bottom: bottomSheetBottom.value,
height: bottomSheetHeight,
child: bottomSheetChild,
),
],
);
}
}
Instead of showing a bottom sheet, you can add a new widget to a Column
reserve:true is the key parameter for navigating to bottom
like:
return Scaffold(
body: SingleChildScrollView(
reserve: true,
child: Column(
children: [
YourWidget(),
if (isOpenBottomSheet)
YourBottomSheet()
],
),
),
);
the complete example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
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> {
bool isOpenBottomSheet = false;
final _controller = ScrollController();
void _incrementCounter() {
setState(() {
isOpenBottomSheet = !isOpenBottomSheet;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
controller: _controller,
reverse: true,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// your widget
Container(
height: MediaQuery.of(context).size.height,
color: Colors.black),
// your bottom sheet
if (isOpenBottomSheet) Container(height: 400, color: Colors.yellow),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
you can use sliding_up_panel with parallax effect:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SlidingUpPanelExample"),
),
body: SlidingUpPanel(
parallaxEnabled: true,
parallaxOffset: 0.4
panel: Center(
child: Text("This is the sliding Widget"),
),
body: Center(
child: Text("This is the Widget behind the sliding panel"),
),
),
);
}

How can I align the icon according to the percentage of the progress bar?

I am using the percent indicator library and I need the icon to be aligned according to the percentage of the progress bar.
You can copy paste run full code below
You can remove Wrap and provide width , height and value to ProgressBarView
and use Transform.rotate to rotate icon
code snippet
Container(width: 400, height: 40, child: ProgressBarView(value: .9,)),
Divider(),
Container(width: 300, height: 40, child: ProgressBarView(value: .7,)),
Divider(),
Container(width: 100, height: 40, child: ProgressBarView(value: .4,)),
...
class ProgressBarView extends StatelessWidget {
ProgressBarView({this.value});
...
return Container(
color: Color(0Xffe6e6e6),
padding: EdgeInsets.only(left: 2, right: 2),
child: Stack(fit: StackFit.loose, children: [
LinearProgressIndicator(
value: value,
valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
backgroundColor: Colors.grey,
minHeight: 40),
working demo
full code
import 'package:flutter/material.dart';
import 'dart:math' as math;
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>[
Container(width: 400, height: 40, child: ProgressBarView(value: .9,)),
Divider(),
Container(width: 300, height: 40, child: ProgressBarView(value: .7,)),
Divider(),
Container(width: 100, height: 40, child: ProgressBarView(value: .4,)),
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class ProgressBarView extends StatelessWidget {
ProgressBarView({this.value});
final value;
final _iconSize = 30;
#override
Widget build(BuildContext context) {
return Container(
color: Color(0Xffe6e6e6),
padding: EdgeInsets.only(left: 2, right: 2),
child: Stack(fit: StackFit.loose, children: [
LinearProgressIndicator(
value: value,
valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
backgroundColor: Colors.grey,
minHeight: 40),
LayoutBuilder(builder: (context, constrains) {
//5 is just the right padding
print(constrains.maxWidth);
var leftPadding = constrains.maxWidth * value - _iconSize;
var topPadding = (constrains.maxHeight - _iconSize) / 2;
return Padding(
padding: EdgeInsets.only(left: leftPadding, top: topPadding),
child: Transform.rotate(
angle: math.pi / 2,
child: Icon(Icons.airplanemode_active,
size: _iconSize.toDouble())),
);
})
]),
);
}
}
Not sure how are you placing the icon on top of the progress bar, but in case you are using a Stack this might help
Stack(
children: [
LinearProgressIndicator(
value: _value,
valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
backgroundColor: Colors.grey,
minHeight: 40
),
LayoutBuilder(
builder: (context, constrains) {
//5 is just the right padding
var leftPadding = constrains.maxWidth * _value - _iconSize - 5;
var topPadding = (constrains.maxHeight - _iconSize) / 2;
return Padding(
padding: EdgeInsets.only(left: leftPadding, top: topPadding),
child: Icon(
Icons.airplanemode_active,
size: _iconSize.toDouble()
),
);
}
)
]
),
Take a look at this codepen https://codepen.io/fcontreras-the-bashful/pen/GRZpRyg

Extend multiple classes Flutter

I have a bottom navigation bar that redirects me to this classes:
final List pages = [
Home(),
Busca(),
Pedidos(),
Perfil(),
];
But i have multiple classes in each of these pages and it only shows the one it is being redirect to.
How can i show all the classes that i have in each file?
That is my file that represents the "Busca" page:
class Busca extends StatefulWidget {
#override
_BuscaState createState() => _BuscaState();
}
class _BuscaState extends State<Busca> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: SearchBar<Post>(
searchBarStyle: SearchBarStyle(
backgroundColor: Colors.tealAccent.withOpacity(0.7),
padding: EdgeInsets.all(5),
borderRadius: BorderRadius.circular(10),),
onSearch: search,
loader: Center(
child: Text("Buscando..."),
),
cancellationText: Text("Cancelar"),
crossAxisCount: 2,
indexedScaledTileBuilder: (int index) => ScaledTile.count(
index % 3 == 0 ? 2 : 2,
1,
),
hintText: "Busque Pratos ou Restaurantes",
hintStyle: TextStyle(
color: Colors.grey,
),
textStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
iconActiveColor: Colors.black,
mainAxisSpacing: 20,
crossAxisSpacing: 20,
onItemFound: (Post post, int index) {
return Container(
color: Colors.tealAccent,
child: ListTile(
title: Text(post.title),
isThreeLine: true,
subtitle: Text(post.description),
)
);
},
),
),
),
);
}
}
class Categorias extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
// Row 1
Row(
children: <Widget>[
Container(
color: Colors.blue, height: 40, width: 40, child: Text('1')),
Container(
color: Colors.blue, height: 40, width: 40, child: Text('2')),
Container(
color: Colors.red, height: 40, width: 40, child: Text('3')),
],
),
]
);
}
}
When i click the button that redirects me to "Busca" the class "Categorias" does not appear below it.
How can i make it appear as well by just redirecting to "Busca"?
You can copy paste run full code below
You can use Column and Expaneded flex
code snippet
Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
children: [
Expanded(
flex: 1,
child: SearchBar<Post>(
...
),
Expanded(flex: 1, child: Categorias())
],
working demo
full code
import 'dart:math';
import 'package:flappy_search_bar/scaled_tile.dart';
import 'package:flappy_search_bar/search_bar_style.dart';
import 'package:flutter/material.dart';
import 'package:flappy_search_bar/flappy_search_bar.dart';
class Post {
final String title;
final String body;
final String description;
Post(this.title, this.body, this.description);
}
class Busca extends StatefulWidget {
#override
_BuscaState createState() => _BuscaState();
}
class _BuscaState extends State<Busca> {
bool isReplay = false;
Future<List<Post>> search(String text) async {
await Future.delayed(Duration(seconds: text.length == 4 ? 10 : 1));
if (isReplay) return [Post("Replaying !", "Replaying body", "desc")];
if (text.length == 5) throw Error();
if (text.length == 6) return [];
List<Post> posts = [];
var random = new Random();
for (int i = 0; i < 10; i++) {
posts.add(Post(
"$text $i", "body random number : ${random.nextInt(100)}", "desc"));
}
return posts;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
children: [
Expanded(
flex: 1,
child: SearchBar<Post>(
searchBarStyle: SearchBarStyle(
backgroundColor: Colors.tealAccent.withOpacity(0.7),
padding: EdgeInsets.all(5),
borderRadius: BorderRadius.circular(10),
),
onSearch: search,
loader: Center(
child: Text("Buscando..."),
),
//cancellationText: Text("Cancelar"),
crossAxisCount: 2,
indexedScaledTileBuilder: (int index) => ScaledTile.count(
index % 3 == 0 ? 2 : 2,
1,
),
hintText: "Busque Pratos ou Restaurantes",
hintStyle: TextStyle(
color: Colors.grey,
),
textStyle: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
iconActiveColor: Colors.black,
mainAxisSpacing: 20,
crossAxisSpacing: 20,
onItemFound: (Post post, int index) {
return Container(
color: Colors.tealAccent,
child: ListTile(
title: Text(post.title),
isThreeLine: true,
subtitle: Text(post.description),
));
},
),
),
Expanded(flex: 1, child: Categorias())
],
),
),
),
);
}
}
class Categorias extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
// Row 1
Row(
children: <Widget>[
Container(
color: Colors.blue, height: 40, width: 40, child: Text('1')),
Container(
color: Colors.blue, height: 40, width: 40, child: Text('2')),
Container(
color: Colors.red, height: 40, width: 40, child: Text('3')),
],
),
]);
}
}
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: Busca(),
);
}
}
call Categoria within the Buca class. How you do this will depend on which type of layout you are aiming for. What you could go is place everything you have in Buca within the children of a column, the next child within children could be categoria.
This Would effectively allow whatever you have in Categoria to be rendered right after Buca.
I don't want to confuse you since you are a beginner, all you need to do is find the right widget container that can hold multiple widgets ie. something with the children attribute. Column, ListView, GridView or Row should do Just fine.
body: Column(children:[SafeArea........
, Categorias()
]'''