GestureDetector fires all containers...how to fire just one? - flutter

I have a gesture detector that fires all containers and I just want to fire one at a time. How would I go about doing that? Right now they are all turning green and I just want to turn one of them green.
Is it the fact that I'm calling it multiple times in the same way in my _HomePageState class?
I thought the new keyword would have taken care of that so I tried that.
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new HomePage()
);
}
}
class HomePage extends StatefulWidget {
#override
State createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.all(20),
),
Container(
height: MediaQuery.of(context).size.height * 0.3,
width: MediaQuery.of(context).size.width * 0.95,
color: Theme.of(context).primaryColorLight,
),
Padding(
padding: EdgeInsets.all(5),
),
Container(
width: MediaQuery.of(context).size.width * .97,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
heroes(context),
heroes(context),
heroes(context),
heroes(context),
heroes(context),
heroes(context),
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.56,
width: MediaQuery.of(context).size.width * .97,
child: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
list(context),
list(context),
list(context),
list(context),
list(context),
list(context),
list(context),
],
),
),
]
),
)
);
}
Color _color = Colors.blue;
Widget heroes(BuildContext context) {
return new GestureDetector(
onTap: () {
setState( () {
_color = Colors.green;
});
},
child: new Container(
height: MediaQuery.of(context).size.height * 0.05,
width: MediaQuery.of(context).size.width * 0.12,
color: _color,
)
);
}
Widget list(BuildContext context) {
return Padding(
padding: EdgeInsets.all(5),
child: Container(
height: MediaQuery.of(context).size.height * 0.07,
width: MediaQuery.of(context).size.width * (0.12*8),
color: Theme.of(context).primaryColorDark
)
);
}
}

Read the comments to understand how it works. It is really simple.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new HomePage()
);
}
}
class HomePage extends StatefulWidget {
#override
State createState() => new _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.all(20),
),
Container(
height: MediaQuery.of(context).size.height * 0.3,
width: MediaQuery.of(context).size.width * 0.95,
color: Theme.of(context).primaryColorLight,
),
Padding(
padding: EdgeInsets.all(5),
),
Container(
width: MediaQuery.of(context).size.width * .97,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
// 1) Give each widget a number
heroes(context, 0),
heroes(context, 1),
heroes(context, 2),
heroes(context, 3),
heroes(context, 4),
heroes(context, 5),
],
),
),
Container(
height: MediaQuery.of(context).size.height * 0.56,
width: MediaQuery.of(context).size.width * .97,
child: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
list(context),
list(context),
list(context),
list(context),
list(context),
list(context),
list(context),
],
),
),
]
),
)
);
}
// 2) This is important. It saves the current index.
var selectedIndex;
// 3) Add `index` as a parameter
Widget heroes(BuildContext context, index) {
return new GestureDetector(
onTap: () {
setState( () {
// 4) After each tap the index of the widget is saved as `selectedIndex`
selectedIndex = index;
});
},
child: new Container(
height: MediaQuery.of(context).size.height * 0.05,
width: MediaQuery.of(context).size.width * 0.12,
// 5) It compares the current selectedIndex with the index of the widget. If both have the same number, the color will be green. Otherwise it will be blue.
color: selectedIndex == index? Colors.green : Colors.blue,
)
);
}
Widget list(BuildContext context) {
return Padding(
padding: EdgeInsets.all(5),
child: Container(
height: MediaQuery.of(context).size.height * 0.07,
width: MediaQuery.of(context).size.width * (0.12*8),
color: Theme.of(context).primaryColorDark
)
);
}
}

Related

How to add 3 columns in flutter?

I want to achieve this:
For now, I got this:
this is my code:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:snippet_coder_utils/ProgressHUD.dart';
class LogIn extends StatefulWidget {
const LogIn({Key? key}) : super(key: key);
#override
State<LogIn> createState() => _LogInState();
}
class _LogInState extends State<LogIn> {
bool isAPIcallProcess = false;
bool hidePassword = true;
GlobalKey<FormState> globalFormKey = GlobalKey<FormState>();
String? username;
String? password;
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Color(0xffF24004),
body: Center(
child: Stack(
children: [
Positioned(
left: 20,
right: 20,
top: 100,
child: Image.asset(
"lib/img/pomodoro.png",
width: 250,
height: 250,))
],
),
),
),
);
}
}
So, how can I achieve the 3 columns? I tried to make another stful widget but I don't know why but it doesn't work, I think is because the main design is in this MaterialApp widget.
I think it would be better if you separate material-app context in further use case. Also try using Align widget for dynamic placement.
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xffF24004),
body: LayoutBuilder(
builder: (context, constraints) => Stack(
children: [
Align(
alignment: const Alignment(0, -.75),
child: Container(
width: constraints.maxWidth * .8, //image size
height: constraints.maxWidth * .8,
color: Colors.green,
),
// Image.asset(
// "lib/img/pomodoro.png",
// width: 250,
// height: 250,
// ),
),
Align(
alignment: Alignment.bottomCenter,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
...List.generate(
3,
(index) => Container(
width: constraints.maxWidth,
height: constraints.maxHeight * .1,
color: index.isEven ? Colors.deepPurple : Colors.amber,
),
)
],
),
)
],
),
),
);
}
More about Stack

Flutter set widget position exactly center of the screen

I want to put a container widget in the middle of the device screen. However, since I used the SizedBox() and SvgPicture.asset() widgets before that, the container does not come right in the middle of the device. How can I do this?
This is my code:
class CenterWidget extends StatefulWidget {
const CenterWidget({Key? key}) : super(key: key);
#override
_CenterWidgetState createState() => _CenterWidgetState();
}
class _CenterWidgetState extends State<CenterWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
const SizedBox(height: 56),
SvgPicture.asset(ImageConstants.instance.logoSvg,
width: (MediaQuery.of(context).size.width - 60) / 2),
Expanded(
child: Center(
child: Container(
color: Colors.red,
width: 100,
height: 100,
),
),
),
],
),
),
),
);
}
}
Use a top center aligned stack, and put the widget you want to be centered within a Positioned.fill widget. You can put the spacer and logo in their own column to keep them arranged vertically:
class _CenterWidgetState extends State<CenterWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Stack(
alignment: Alignment.topCenter,
children: [
Column(
children: [
const SizedBox(height: 56),
SvgPicture.asset(ImageConstants.instance.logoSvg,
width: (MediaQuery.of(context).size.width - 60) / 2),
],
),
Positioned.fill(
child: Center(
child: Container(
color: Colors.red,
width: 100,
height: 100,
),
),
),
],
),
),
),
);
}
}

transition between pages using indicators in the flutter

I have 2 pages, on one of them I have placed the code which displays indexers, I want to swipe on indexes to pass between pages. I can't figure out how to set it up. I will be grateful for your help.
Container(
child: SmoothPageIndicator(
controller: _pageController,
count: _pages.length,
effect: JumpingDotEffect(
dotHeight: 16,
dotWidth: 16,
jumpScale: .7,
verticalOffset: 15,
),
onDotClicked: _onchanged
),
),
List of pages:
List<Widget> _pages = [
Form_scan(),
Form_ttn()
];
Image indecators
I will be grateful if someone helps me to go from the first page to the second (swipe right) with these indicators
Try out below code:-
import 'dart:async';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:sizer/sizer.dart';
import 'package:livekeeping/Common/Constant.dart';
import 'package:livekeeping/Common/IconNames.dart';
import 'package:livekeeping/Common/Reusable.dart';
import 'package:livekeeping/Controller/Authentication/LoginWithOtpScreen.dart';
import 'package:lottie/lottie.dart';
class Onboarding extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return OnboardingState();
}
}
class OnboardingState extends State<Onboarding> {
int _current = 0;
Widget widgetChange = firstWidget();
var i = 0;
#override
void initState() {
super.initState();
}
#override
void dispose() {
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: double.maxFinite,
width: double.maxFinite,
child: Stack(
children: <Widget>[
PageView.builder(
onPageChanged: (pageIndex) {
setState(() {
_current = pageIndex;
});
},
itemCount: 4,
itemBuilder: (context, index) {
if (index == 0) {
return firstWidget();
} else if (index == 1) {
return secondWidget();
} else if (index == 2) {
return thirdWidget();
} else {
return fourthWidget();
}
},
),
Positioned(
bottom: 120,
left: 0,
right: 0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [1, 2, 3, 4].map((url) {
int index = [1, 2, 3, 4].indexOf(url);
return Container(
width: 8.0,
height: 8.0,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _current == index
? Color.fromRGBO(0, 0, 0, 0.9)
: Color.fromRGBO(0, 0, 0, 0.4),
),
);
}).toList(),
),
),
Padding(
padding: const EdgeInsets.only(bottom: 30.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ButtonTheme(
height: 45,
minWidth: 150,
child: new Center(
child: RaisedButton(
color: AppTextStyle.mainThemeColor(),
onPressed: () {
Navigator.of(context).pushAndRemoveUntil(
CupertinoPageRoute(
builder: (context) => Login()),
(route) => false);
},
child: new Text(
"Get Started".toUpperCase(),
style: GoogleFonts.openSans(
color: Colors.white,
fontSize: 15,
fontWeight: FontWeight.w500,
),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50)),
)),
),
],
),
)
],
),
),
);
}
}
class firstWidget extends StatefulWidget {
#override
_firstWidgetState createState() => _firstWidgetState();
}
class _firstWidgetState extends State<firstWidget>{
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
height: double.maxFinite,
width: double.maxFinite,
child: Image.asset(
SplashBG, // You can put your Background image as well
fit: BoxFit.cover,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 45.0.h,
width: 75.0.w,
child: Image.asset(Icon1),
),
],
),
],
),
],
);
}
}
class secondWidget extends StatefulWidget {
#override
_secondWidgetState createState() => _secondWidgetState();
}
class _secondWidgetState extends State<secondWidget>{
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
height: double.maxFinite,
width: double.maxFinite,
child: Image.asset(
SplashBG, // You can put your Background image as well
fit: BoxFit.cover,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 45.0.h,
width: 75.0.w,
child: Image.asset(Icon2),
),
],
),
],
),
],
);
}
}
class thirdWidget extends StatefulWidget {
#override
_thirdWidgetState createState() => _thirdWidgetState();
}
class _thirdWidgetState extends State<thirdWidget> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
height: double.maxFinite,
width: double.maxFinite,
child: Image.asset(
SplashBG, // You can put your Background image as well
fit: BoxFit.cover,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 45.0.h,
width: 75.0.w,
child: Image.asset(Icon3),
),
],
),
],
),
],
);
}
}
class fourthWidget extends StatefulWidget {
#override
_fourthWidgetState createState() => _fourthWidgetState();
}
class _fourthWidgetState extends State<fourthWidget> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
height: double.maxFinite,
width: double.maxFinite,
child: Image.asset(
SplashBG, // You can put your Background image as well
fit: BoxFit.cover,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 45.0.h,
width: 75.0.w,
child: Image.asset(Iconn4),
),
],
),
],
),
],
);
}
}
use PageView, :
PageView(
controller: _pageController,
children: [
Form_scan(),
Form_ttn()
],
),
make a PageController :
final PageController _pageController = PageController();
onDotClicked: _onchanged
void _onchanged(){
_pageController.animateToPage(
indexHalaman,
duration: Duration(milliseconds: 500),
curve: Curves.fastOutSlowIn
);
}
indexHalaman = page index, if you have 2 widget on pageView children then first page index = 0, next index page = 1, if you use stateful widget, dont forget to use setState, or maybe you can use bloc pattern for this

Achieving this layout in flutter

I am trying to achieve something like this in flutter. I have a horizontal scrollable which has these rounded containers. I want the width of these containers to shrink if the elements in the scrollable is more than 3 and it should expand as per the image if the elements are less than 2. What i want is exactly like this image, i have been reading about flexible widget but when i wrap it inside a scrollable row it gives layout specific issues. Any workaround to achieve this?
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SingleChildScrollView(
padding: EdgeInsets.zero,
scrollDirection: Axis.horizontal,
child: Row(
children: [
...List.generate(
9,
(index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.green,
),
height: 100,
width: 100,
),
),
)
],
)),
SizedBox(
height: 20,
),
Row(
children: [
...List.generate(
2,
(index) => Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 100,
width: 180,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(20))),
))
],
),
SizedBox(
height: 20,
),
Row(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 100,
width: 350,
decoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.circular(20))),
),
],
)
],
),
),
);
}
The above build method produces the following result.(The values here are hardcoded and is just for demonstration). The list values are going to be dynamic and the desired result should be like the one in the video. How do i proceed with this?
https://streamable.com/w142je
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(debugShowCheckedModeBanner: false, home: MyHomePage());
}
}
class MyHomePage extends StatefulWidget {
final String hintText = 'hing';
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
#override
Widget build(BuildContext context) {
var list1 = List.filled(2, '2');
var list2 = List.filled(4, '4');
var list3 = List.filled(1, '1');
return SafeArea(
child: Scaffold(
body: Column(
children: [
_getList(context, list1),
_getList(context, list2),
_getList(context, list3),
],
),
),
);
}
Widget _getList(BuildContext context, List<String> list) {
bool ownSize = list.length == 2;
if (ownSize) {
return SingleChildScrollView(
padding: EdgeInsets.zero,
scrollDirection: Axis.horizontal,
child: Row(
children: list.map((t) => rowItem(t, 250)).toList(),
),
);
} else {
return Row(
children: list
.map(
(t) => Expanded(child: rowItem(t)),
)
.toList(),
);
}
}
Widget rowItem(String text, [double? width]) {
return Container(
margin: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.green,
),
height: 100,
width: width,
alignment: Alignment.center,
child: Text(text),
);
}
}

Using Flow widget instead of BottomNavigationBar in Flutter

I'm trying to use Flow widget instead of BottomNavigationBar.
this is my code.
#override
Widget build(BuildContext context) {
final delegate = S.of(context);
return SafeArea(
child: Scaffold(
drawer: DrawerWidget(),
body: Stack(
children: [
_pages[_selectedPageIndex]['page'],
Positioned(
child: Container(
child: Flow(
delegate: FlowMenuDelegate(menuAnimation: menuAnimation),
children: menuItems
.map<Widget>((IconData icon) => flowMenuItem(icon))
.toList(),
),
),
),
]),
}
But after adding left, right, bottom, or top properties to the Positioned widget, the Flow widget gon.
You can copy paste run full code below
You can use ConstrainedBox and set Stack fit and Positioned with Container
SafeArea(
child: Scaffold(
body: ConstrainedBox(
constraints: BoxConstraints.expand(),
child: Stack(
alignment: Alignment.topLeft,
fit: StackFit.expand,
children: [
...
Positioned(
left: 0,
top: 0,
child: Container(
alignment: Alignment.topLeft,
width: MediaQuery.of(context).size.width,
height: 65,
child: FlowMenu()))
]),
),
),
);
working demo
full code
import 'package:flutter/cupertino.dart';
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: FlowTest(),
);
}
}
class FlowTest extends StatefulWidget {
#override
_FlowTestState createState() => _FlowTestState();
}
class _FlowTestState extends State<FlowTest> {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: ConstrainedBox(
constraints: BoxConstraints.expand(),
child: Stack(
alignment: Alignment.topLeft,
fit: StackFit.expand,
children: [
ListView(
shrinkWrap: true,
children: <Widget>[
Column(
children: <Widget>[
SizedBox(height: 20.0),
ListView.builder(
shrinkWrap: true,
itemCount: 5,
physics: PageScrollPhysics(),
itemBuilder: (context, index) {
return Column(
children: <Widget>[
Container(
height: 50.0,
color: Colors.green,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.format_list_numbered,
color: Colors.white),
Padding(
padding: const EdgeInsets.only(right: 5.0)),
Text(index.toString(),
style: TextStyle(
fontSize: 20.0, color: Colors.white)),
],
),
),
Container(
child: GridView.count(
crossAxisCount: 3,
shrinkWrap: true,
physics: PageScrollPhysics(),
childAspectRatio: 1.2,
children: List.generate(
8,
(index) {
return Container(
child: Card(
color: Colors.blue,
),
);
},
),
),
),
SizedBox(height: 20.0),
],
);
},
),
],
),
],
),
Positioned(
left: 0,
top: 0,
child: Container(
alignment: Alignment.topLeft,
width: MediaQuery.of(context).size.width,
height: 65,
child: FlowMenu()))
]),
),
),
);
}
}
class FlowMenu extends StatefulWidget {
#override
_FlowMenuState createState() => _FlowMenuState();
}
class _FlowMenuState extends State<FlowMenu>
with SingleTickerProviderStateMixin {
AnimationController menuAnimation;
IconData lastTapped = Icons.notifications;
final List<IconData> menuItems = <IconData>[
Icons.home,
Icons.new_releases,
Icons.notifications,
Icons.settings,
Icons.menu,
];
void _updateMenu(IconData icon) {
if (icon != Icons.menu) setState(() => lastTapped = icon);
}
#override
void initState() {
super.initState();
menuAnimation = AnimationController(
duration: const Duration(milliseconds: 250),
vsync: this,
);
}
Widget flowMenuItem(IconData icon) {
final double buttonDiameter =
MediaQuery.of(context).size.width / menuItems.length;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: RawMaterialButton(
fillColor: lastTapped == icon ? Colors.amber[700] : Colors.blue,
splashColor: Colors.amber[100],
shape: CircleBorder(),
constraints: BoxConstraints.tight(Size(buttonDiameter, buttonDiameter)),
onPressed: () {
_updateMenu(icon);
menuAnimation.status == AnimationStatus.completed
? menuAnimation.reverse()
: menuAnimation.forward();
},
child: Icon(
icon,
color: Colors.white,
size: 45.0,
),
),
);
}
#override
Widget build(BuildContext context) {
return Container(
child: Flow(
delegate: FlowMenuDelegate(menuAnimation: menuAnimation),
children: menuItems
.map<Widget>((IconData icon) => flowMenuItem(icon))
.toList(),
),
);
}
}
class FlowMenuDelegate extends FlowDelegate {
FlowMenuDelegate({this.menuAnimation}) : super(repaint: menuAnimation);
final Animation<double> menuAnimation;
#override
bool shouldRepaint(FlowMenuDelegate oldDelegate) {
return menuAnimation != oldDelegate.menuAnimation;
}
#override
void paintChildren(FlowPaintingContext context) {
double dx = 0.0;
for (int i = 0; i < context.childCount; ++i) {
dx = context.getChildSize(i).width * i;
context.paintChild(
i,
transform: Matrix4.translationValues(
dx * menuAnimation.value,
0,
0,
),
);
}
}
}