Adding a toggled button/icon to App in flutter - flutter

Looking for a way to implement a button that can be toggled back and forth between favorites and history. Is there a way to do this in flutter.

You can try using a custom widget like this one below:
toggle_button.dart
import 'package:flutter/material.dart';
class ToggleButton extends StatefulWidget {
final double width;
final double height;
final String leftDescription;
final String rightDescription;
final Color toggleColor;
final Color toggleBackgroundColor;
final Color toggleBorderColor;
final Color inactiveTextColor;
final Color activeTextColor;
final double _leftToggleAlign = -1;
final double _rightToggleAlign = 1;
final VoidCallback onLeftToggleActive;
final VoidCallback onRightToggleActive;
const ToggleButton(
{Key? key,
required this.width,
required this.height,
required this.toggleBackgroundColor,
required this.toggleBorderColor,
required this.toggleColor,
required this.activeTextColor,
required this.inactiveTextColor,
required this.leftDescription,
required this.rightDescription,
required this.onLeftToggleActive,
required this.onRightToggleActive})
: super(key: key);
#override
_ToggleButtonState createState() => _ToggleButtonState();
}
class _ToggleButtonState extends State<ToggleButton> {
double _toggleXAlign = -1;
late Color _leftDescriptionColor;
late Color _rightDescriptionColor;
#override
void initState() {
super.initState();
_leftDescriptionColor = widget.activeTextColor;
_rightDescriptionColor = widget.inactiveTextColor;
}
#override
Widget build(BuildContext context) {
return Container(
width: widget.width,
height: widget.height,
decoration: BoxDecoration(
color: widget.toggleBackgroundColor,
borderRadius: BorderRadius.all(
Radius.circular(50.0),
),
border: Border.all(color: widget.toggleBorderColor),
),
child: Stack(
children: [
AnimatedAlign(
alignment: Alignment(_toggleXAlign, 0),
duration: Duration(milliseconds: 300),
child: Container(
width: widget.width * 0.5,
height: widget.height,
decoration: BoxDecoration(
color: widget.toggleColor,
borderRadius: BorderRadius.all(
Radius.circular(50.0),
),
),
),
),
GestureDetector(
onTap: () {
setState(
() {
_toggleXAlign = widget._rightToggleAlign;
_leftDescriptionColor = widget.inactiveTextColor;
_rightDescriptionColor = widget.activeTextColor;
},
);
widget.onRightToggleActive();
},
child: Align(
alignment: Alignment(-1, 0),
child: Container(
width: widget.width * 0.5,
color: Colors.transparent,
alignment: Alignment.center,
child: Text(
widget.leftDescription,
style: TextStyle(
color: _leftDescriptionColor,
fontWeight: FontWeight.bold),
),
),
),
),
GestureDetector(
onTap: () {
setState(
() {
_toggleXAlign = widget._leftToggleAlign;
_leftDescriptionColor = widget.activeTextColor;
_rightDescriptionColor = widget.inactiveTextColor;
},
);
widget.onLeftToggleActive();
},
child: Align(
alignment: Alignment(1, 0),
child: Container(
width: widget.width * 0.5,
color: Colors.transparent,
alignment: Alignment.center,
child: Text(
widget.rightDescription,
style: TextStyle(
color: _rightDescriptionColor,
fontWeight: FontWeight.bold),
),
),
),
),
],
),
);
}
}
main.dart
import 'package:flutter/material.dart';
import 'package:stackovfl_70777885/toggle_button.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
padding: EdgeInsets.all(10.0),
child: ToggleButton(
width: 300.0,
height: 60.0,
toggleBackgroundColor: Colors.white,
toggleBorderColor: (Colors.grey[350])!,
toggleColor: (Colors.indigo[900])!,
activeTextColor: Colors.white,
inactiveTextColor: Colors.grey,
leftDescription: 'FAVORITES',
rightDescription: 'HISTORY',
onLeftToggleActive: () {
print('left toggle activated');
},
onRightToggleActive: () {
print('right toggle activated');
},
),
),
);
}
}
This should result in the following:
The onLeftToggleActive(): () {} and onRightToggleActive() {} in main are triggered depending on where the slider moves.

Related

When dynamically creating DropDownButton - it doesn't work

When creating a DropDownButton through a class, the dropdown list itself does not open. Tell me, what is my mistake?
The button is in the "inactive" state. That is, when I click on it, I do not have a list with data
Yes, I'm sure the data is there.
I would not create a class for the button, but I have about 10 of them, and in order not to have a lot of repetitive code, I need to use the class
I can provide button code -
class DropDownButtons extends StatelessWidget {
final dynamic valueDropDown;
final String hintDropDown;
final List<DropdownMenuItem<dynamic>>? itemsDropDown;
final void Function(dynamic)? saveState;
const DropDownButtons({
Key? key,
required this.valueDropDown,
required this.hintDropDown,
required this.itemsDropDown,
required this.saveState
}) : super (key: key);
#override
Widget build(BuildContext context) {
return Container(
width: 270,
margin: EdgeInsets.only(top: 7),
child: Align(
alignment: Alignment.center,
child: DropdownButtonFormField(
hint: Text('hintDropDown'),
value: valueDropDown,
icon: const Icon(Icons.keyboard_arrow_down),
items: itemsDropDown,
onChanged: saveState,
)
)
);
}
}
And also, the display code -
DropDownButtons(valueDropDown: LoginClass.countryValue, hintDropDown: 'Text', itemsDropDown: LoginClass.countryDropDown, saveState: saveStateCountry()),
And of course, saving the stat -
saveStateCountry() {
(dynamic newValue) {
setState(() {
LoginClass.countryValue = newValue!;
print(LoginClass.countryValue);
});
};
}
minimum reproductive code -
class CreatedApplications extends StatelessWidget {
const CreatedApplications({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
saveStateCountry() {
(dynamic newValue) {
setState(() {
LoginClass.countryValue = newValue!;
print(LoginClass.countryValue);
});
};
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
padding: EdgeInsets.all(15),
child: Column(children: [
Column(
children: <Widget>[
Align(
alignment: Alignment.center,
child: FractionallySizedBox(
widthFactor: 1,
alignment: Alignment.centerLeft,
child: Text('${now}'))),
],
),
SizedBox(
height: 12,
),
// const DropDown(),
DropDownButtons(valueDropDown: LoginClass.countryValue, hintDropDown: 'Выберите страну', itemsDropDown: LoginClass.countryDropDown, saveState: saveStateCountry()),
],
),
),
]
)
)
);
}
}
class DropDownButtons extends StatelessWidget {
final dynamic valueDropDown;
final String hintDropDown;
final List<DropdownMenuItem<dynamic>>? itemsDropDown;
final Function saveState;
const DropDownButtons({
Key? key,
required this.valueDropDown,
required this.hintDropDown,
required this.itemsDropDown,
required this.saveState
}) : super (key: key);
#override
Widget build(BuildContext context) {
return Container(
width: 270,
margin: EdgeInsets.only(top: 7),
child: Align(
alignment: Alignment.center,
child: DropdownButtonFormField(
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: const BorderRadius.all(
const Radius.circular(25.0),
),
),
fillColor: Colors.lightBlueAccent.withOpacity(0.2),
filled: true
),
hint: Text(hintDropDown),
value: valueDropDown,
icon: const Icon(Icons.keyboard_arrow_down),
items: itemsDropDown,
onChanged: (dynamic newValue) {
saveState;
}
)
)
);
}
}

How to create interactive flowchart in flutter

I want to create a flutter UI where there are some shapes like square, rectangle, circle, arrow. And I must be able to drag and drop them at the centre and add text to it and connect them. I have just started with flutter so I am not sure how to do this. Can anyone please help me?
Use Draggable class
Example:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: Scaffold(
appBar: AppBar(title: const Text(_title)),
body: const MyStatefulWidget(),
),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
#override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int acceptedData = 0;
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Draggable<int>(
// Data is the value this Draggable stores.
data: 10,
feedback: Container(
color: Colors.deepOrange,
height: 100,
width: 100,
child: const Icon(Icons.directions_run),
),
childWhenDragging: Container(
height: 100.0,
width: 100.0,
color: Colors.pinkAccent,
child: const Center(
child: Text('Child When Dragging'),
),
),
child: Container(
height: 100.0,
width: 100.0,
color: Colors.lightGreenAccent,
child: const Center(
child: Text('Draggable'),
),
),
),
DragTarget<int>(
builder: (
BuildContext context,
List<dynamic> accepted,
List<dynamic> rejected,
) {
return Container(
height: 100.0,
width: 100.0,
color: Colors.cyan,
child: Center(
child: Text('Value is updated to: $acceptedData'),
),
);
},
onAccept: (int data) {
setState(() {
acceptedData += data;
});
},
),
],
);
}
}

Flutter SingleChildScrollView is not stopping in the middle but bouncing to the edge

In demo, even if I don't use drawer or appBar it doesn't matter. Any scrollview is not stopping in the middle. Even if it's a ListView or column in a SingleChildScrollView, it doesn't matter. I can't scroll normally. It suddenly bounces to the other edge.
The reason I use option + shift is to show when I release mouse.
https://www.youtube.com/watch?v=GqlQL_rl3Xc
Test Demo:
import 'xxxx/widgets/app-bar.dart';
import 'xxxx/widgets/drawer.dart';
import 'package:flutter/material.dart';
class PageHome extends StatefulWidget {
PageHome({Key? key}) : super(key: key);
#override
_PageHomeState createState() => _PageHomeState();
}
class _PageHomeState extends State<PageHome> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: IAppBar(
title: "Home",
),
drawer: AppDrawer(
index: AppDrawer.DRAWER_INDEX_HOME,
),
body: SingleChildScrollView(
controller: ScrollController(),
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.yellow,
Colors.teal,
Colors.purple,
Colors.blue,
Colors.red
])),
child: Column(
children: [
Container(height: 3000),
],
),
),
),
);
} f
}
Main dart:
class MyApp extends StatefulWidget {
MyApp();
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'CT',
theme: ThemeData(
brightness: Brightness.light,
backgroundColor: backgroundColor,
primaryColor: primaryColor,
accentColor: accentColor,
textTheme: GoogleFonts.ubuntuTextTheme().copyWith(
headline1: GoogleFonts.ubuntuTextTheme().headline1?.copyWith(
fontSize: 24,
fontWeight: FontWeight.w900,
color: Colors.black)),
),
onGenerateRoute: ARouter.generateRoute);
}
}
class Splash extends StatefulWidget {
const Splash({Key? key}) : super(key: key);
#override
_SplashState createState() => _SplashState();
}
class _SplashState extends State<Splash> {
#override
void initState() {
super.initState();
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) async {
if ((!await FlutterSecureStorage().containsKey(key: "intro"))) {
Navigator.pushReplacementNamed(context, ARouter.routeIntro);
return;
}
if (await getJWT() == null) {
Navigator.pushReplacementNamed(context, ARouter.routeAuth);
return;
}
if (await validateToken())
Navigator.pushReplacementNamed(context, ARouter.routeHome);
else
Navigator.pushReplacementNamed(context, ARouter.routeAuth);
});
}
#override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
child: Stack(
children: [
Image.asset("assets/images/bg.png"),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(
strokeWidth: 6,
),
Container(height: 24),
Center(
child: Text(
"Loading",
style: TextStyle(
fontSize: 24,
color: Colors.black,
decoration: TextDecoration.none),
)),
],
),
],
),
);
}
}

Flutter: How to use animated icon in the AppBar - I want to use this animated icon instead of Animatedless Icon, in the appbar of flutter app

I want to use the animated icon in this AppBar, but can not be done because the animated icon have a stateful widget with "with TickerProviderStateMixin". If I move the whole scaffold to a stateful widget then the "onMenuTap" is not working. The main purpose of the Question is to use the animated icon in the Flutter AppBar.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../FreelanceTheme/AppStyleModeNotifier.dart';
class HomePage extends StatelessWidget with NavigationStates {
final Function onMenuTap;
const HomePage({Key key, this.onMenuTap}) : super(key: key);
#override
Widget build(BuildContext context) {
final appStyleMode = Provider.of<AppStyleModeNotifier>(context);
return MaterialApp(
home: Scaffold(
backgroundColor: Color(0xffE5E5E5),
appBar: AppBar(
elevation: 0,
backgroundColor: appStyleMode.appBarBackgroundColor,
actions: <Widget>[
Switch(
activeColor: Colors.orange,
value: appStyleMode.mode,
onChanged: (value) => appStyleMode.switchMode(),
),
],
leading: IconButton(
tooltip: 'App Settings',
icon: Icon(
FontAwesomeIcons.bars,
color: Colors.white,
),
onPressed: onMenuTap,
),
centerTitle: true,
title: Text(
"Home",
style: TextStyle(
color: Colors.white,
),
),
),
body: FreelancingHomePage(),
),
);
}
}
I want to replace this IconButton with the animated icon in the appbar.
leading: IconButton(
tooltip: 'App Settings',
icon: Icon(
FontAwesomeIcons.bars,
color: Colors.white,
),
onPressed: onMenuTap,
),
Following is the code for the animated icon. I want to use this animated icon in the above appBar.
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
AnimationController _animationIconController1,
bool isarrowmenu = false;
#override
void initState() {
super.initState();
_animationIconController1 = AnimationController(
vsync: this,
duration: Duration(milliseconds: 750),
reverseDuration: Duration(milliseconds: 750),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
GestureDetector(
onTap: () {
setState(() {
isarrowmenu
? _animationIconController1.reverse()
: _animationIconController1.forward();
isarrowmenu = !isarrowmenu;
});
},
child: ClipOval(
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 2.5,
color: Colors.green,
),
borderRadius: BorderRadius.all(
Radius.circular(50.0),
),
),
width: 75,
height: 75,
child: Center(
child: AnimatedIcon(
icon: AnimatedIcons.arrow_menu,
progress: _animationIconController1,
color: Colors.red,
size: 60,
),
),
),
),
),
),
);
}
You can copy paste run full code below
Step 1: You can make this animated icon with StatefulWidget that have VoidCallback onMenuTap
class CustomIcon extends StatefulWidget {
VoidCallback onMenuTap;
CustomIcon({Key key, this.onMenuTap}) : super(key: key);
#override
_CustomIconState createState() => _CustomIconState();
}
class _CustomIconState extends State<CustomIcon> with TickerProviderStateMixin {
AnimationController _animationIconController1;
Step 2: In leading, you can use CustomIcon and pass onMenuTap
home: HomePage(
onMenuTap: () {
print("hi");
},
),
...
leading: CustomIcon(
onMenuTap: () {
onMenuTap();
},
),
working demo
output of working demo
I/flutter (25195): hi
I/flutter (25195): hi
full code
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: HomePage(
onMenuTap: () {
print("hi");
},
),
);
}
}
class HomePage extends StatelessWidget {
final Function onMenuTap;
const HomePage({Key key, this.onMenuTap}) : super(key: key);
#override
Widget build(BuildContext context) {
//final appStyleMode = Provider.of<AppStyleModeNotifier>(context);
return MaterialApp(
home: Scaffold(
backgroundColor: Color(0xffE5E5E5),
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.blue,
actions: <Widget>[
/* Switch(
activeColor: Colors.orange,
value: appStyleMode.mode,
onChanged: (value) => appStyleMode.switchMode(),
),*/
],
leading: CustomIcon(
onMenuTap: () {
onMenuTap();
},
),
centerTitle: true,
title: Text(
"Home",
style: TextStyle(
color: Colors.white,
),
),
),
body: Text("FreelancingHomePage()"),
),
);
}
}
class CustomIcon extends StatefulWidget {
VoidCallback onMenuTap;
CustomIcon({Key key, this.onMenuTap}) : super(key: key);
#override
_CustomIconState createState() => _CustomIconState();
}
class _CustomIconState extends State<CustomIcon> with TickerProviderStateMixin {
AnimationController _animationIconController1;
bool isarrowmenu = false;
#override
void initState() {
super.initState();
_animationIconController1 = AnimationController(
vsync: this,
duration: Duration(milliseconds: 750),
reverseDuration: Duration(milliseconds: 750),
);
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
setState(() {
isarrowmenu
? _animationIconController1.reverse()
: _animationIconController1.forward();
isarrowmenu = !isarrowmenu;
if (widget.onMenuTap != null) {
widget.onMenuTap();
}
});
},
child: ClipOval(
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 2.5,
color: Colors.green,
),
borderRadius: BorderRadius.all(
Radius.circular(50.0),
),
),
width: 75,
height: 75,
child: Center(
child: AnimatedIcon(
icon: AnimatedIcons.arrow_menu,
progress: _animationIconController1,
color: Colors.red,
size: 60,
),
),
),
),
);
}
}

flutter Update list, setstate does not work

video:https://drive.google.com/file/d/1Nh49PxHeCak4YkaCHVec8hQCzgTN7Kr-/view?usp=sharing
The subcomponent clicks on the callback function, and the background color of the subcomponent cannot be changed by changing the value of list
I tried using deep copy and it still didn't work. How can I change the code to switch the background color?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
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> {
List<bool> tabsActive = [true,false,false,false,false];
void changeTabs(int view) {
print("view:$view");
for(int i = 0;i < tabsActive.length;i++) {
tabsActive[i] = false;
}
setState(() {
tabsActive[view-1] = true;
});
print(tabsActive);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body:Center(
child: Row(
children: <Widget>[
GameTabs("tab1",1,tabsActive[0],changeTabs),
GameTabs("tab2",2,tabsActive[1],changeTabs),
GameTabs("tab3",3,tabsActive[2],changeTabs),
GameTabs("tab4",4,tabsActive[3],changeTabs),
GameTabs("tab5",5,tabsActive[4],changeTabs),
],
),
)
);
}
}
typedef CallIntFun = void Function(int);
class GameTabs extends StatefulWidget {
final String title;
final int view;
final bool active;
CallIntFun changeTabs;
GameTabs(this.title,this.view,this.active,this.changeTabs);
#override
_GameTabsState createState() => _GameTabsState(title,view,active,changeTabs);
}
class _GameTabsState extends State<GameTabs> with SingleTickerProviderStateMixin {
AnimationController _controller;
final String title;
final int view;
final bool active;
Color bgColor;
CallIntFun changeTabs;
_GameTabsState(this.title,this.view,this.active,this.changeTabs);
#override
Widget build(BuildContext context) {
if (active) {
return ActiveGameTabs(title);
}
return Expanded(
child: GestureDetector(
onTap: (){
changeTabs(view);
},
child: Container(
height: 56,
padding: EdgeInsets.fromLTRB(0, 6, 0, 0),
decoration: BoxDecoration(
color: Color.fromRGBO(235, 235, 235, 1),
border: Border.all(
color: Colors.green,
width: 3.0,
style: BorderStyle.none
),
),
child: Text(
title,
textAlign: TextAlign.center,
),
),
)
);
}
}
class ActiveGameTabs extends StatelessWidget {
final String title;
ActiveGameTabs(this.title);
#override
Widget build(BuildContext context) {
return Expanded(
child: Container(
height: 56,
padding: EdgeInsets.fromLTRB(0, 6, 0, 0),
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Colors.green,
width: 3.0,
style: BorderStyle.none
),
),
child: Text(
title,
textAlign: TextAlign.center,
),
)
);
}
}
You are passing the values from widget to state when the state is created for the first time. So it won't change when there is a change in any of those property (Because state won't gets created each time). You want to change your GameTab implementation like this:
class GameTabs extends StatefulWidget {
final String title;
final int view;
final bool active;
CallIntFun changeTabs;
GameTabs(this.title,this.view,this.active,this.changeTabs);
#override
_GameTabsState createState() => _GameTabsState();
}
class _GameTabsState extends State<GameTabs> with SingleTickerProviderStateMixin {
AnimationController _controller;
#override
Widget build(BuildContext context) {
if (widget.active) {
return ActiveGameTabs(widget.title);
}
return Expanded(
child: GestureDetector(
onTap: (){
widget.changeTabs(widget.view);
},
child: Container(
height: 56,
padding: EdgeInsets.fromLTRB(0, 6, 0, 0),
decoration: BoxDecoration(
color: Color.fromRGBO(235, 235, 235, 1),
border: Border.all(
color: Colors.green,
width: 3.0,
style: BorderStyle.none
),
),
child: Text(
widget.title,
textAlign: TextAlign.center,
),
),
)
);
}
}