Add New Widget on button click with a finction that returns a widget - flutter

Hello i am new to Flutter and I want to know if there is a way to add new Widgets with a button click.
I looked into many stack overflow similar Questions. but due to my poor knowledge most of them seems complex to me and hard to grasp. All i need to do is add some containers below old build containers
class MedPreC extends StatefulWidget {
#override
_MedPreCState createState() => _MedPreCState();
}
Widget returnWidget() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: double.infinity,
height: 40,
color: Colors.red,
),
);
}
class _MedPreCState extends State<MedPreC> {
var child2 = Column(
children: [
returnWidget(),
],
);
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
Expanded(
child: Container(
color: Colors.yellow,
height: 400,
width: double.infinity,
child: child2,
),
),
RaisedButton(
child: Text("Add"),
onPressed: () {
setState(() {
//
child2.children.add(returnWidget());
//
});
},
)
],
),
);
}
}
This is the code i have made so far. This whole code will be called inside another class with scafold and stuffs
returnWidget() Returns a red container
child2 is a Column called inside a yellow Container with one red container as one of its children
i need to add more redcontainers on button press
Thank you thats all

Try this
class AddWidget extends StatefulWidget {
#override
_AddWidgetState createState() => _AddWidgetState();
}
class _AddWidgetState extends State<AddWidget> {
List<Widget> containerList = [];
Widget returnWidget() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: double.infinity,
height: 40,
color: Colors.red,
),
);
}
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
Expanded(
child: Container(
color: Colors.yellow,
height: 400,
width: double.infinity,
child: Column(children: containerList),
),
),
RaisedButton(
child: Text("Add"),
onPressed: () {
setState(() {
containerList.add(returnWidget());
});
},
)
],
),
);
}
}

For this you need also check the overflow of widget. So you can check the below code.
import 'package:flutter/material.dart';
class MedPreC extends StatefulWidget {
#override
_MedPreCState createState() => _MedPreCState ();
}
class _MedPreCState extends State<MedPreC > {
List<Widget> data = [];
Widget CustomWidget() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: double.infinity,
height: 40,
color: Colors.red,
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Container(
color: Colors.yellow,
height: MediaQuery.of(context).size.height - 60,
width: double.infinity,
child: SingleChildScrollView(child: Column(children: data)),
),
],
),
bottomNavigationBar: Container(
height: 60,
width: MediaQuery.of(context).size.width,
color: Colors.white,
child: InkWell(
child: Center(
child: Container(
color: Colors.red,
width: 100,
height: 40,
child: Center(child: Text("Add"))),
),
onTap: () {
setState(() {
data.add(CustomWidget());
});
},
),
),
);
}
}

Related

Create another Widget when OnTap() is triggered

Does anyone know how to generate a new widget in Flutter when OnTap() is triggered?
In my case, I want to create a new column inside a container, when the column icon is pressed.
The icon is wrapped with an InkWell().
InkWell(
onTap: () {
print("Create Column in another Container");
},
child: Column(
children: const [
Icon(
Icons.view_agenda,
color: iconGreyColor,
size: 20.0,
),
],
),
),
The Goal shut look like this.
Container(child: Column(children:[]),)
Main part:
...widget.widgets -> spread operator .whenever ontap pressed.the array will get new element and set state will update the widget.
InkWell(
onTap: () {
setState(() {
widget.widgets.add(Container(
height: 49,
child: new Column(
children: [
Text(
"hi",
style: TextStyle(fontSize: 40),
)
],
),
));
});
print("Create Column in another Container");
},
child: Column(
children: const [
Icon(
Icons.view_agenda,
size: 20.0,
),
],
),
)
Container(
margin: EdgeInsets.only(
left: 10.0,
right: 10.0,
),
height: MediaQuery.of(context).size.height - 150,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [...widget.widgets],
),
)
sample code
void main() => runApp(MyHomePage());
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Page0(),
);
}
}
class Page0 extends StatefulWidget {
final widgets = [];
#override
_Page0State createState() => _Page0State();
}
class _Page0State extends State<Page0> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
SizedBox(
height: 25.0,
),
Center(
child: Text(
"macintosh_app",
style: TextStyle(fontSize: 48),
)),
SizedBox(
height: 50.0,
),
Center(
child: InkWell(
onTap: () {
setState(() {
widget.widgets.add(Container(
height: 49,
child: new Column(
children: [
Text(
"hi",
style: TextStyle(fontSize: 40),
)
],
),
));
});
print("Create Column in another Container");
},
child: Column(
children: const [
Icon(
Icons.view_agenda,
size: 20.0,
),
],
),
),
),
SizedBox(
height: 25.0,
),
Container(
margin: EdgeInsets.only(
left: 10.0,
right: 10.0,
),
height: MediaQuery.of(context).size.height - 150,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [...widget.widgets],
),
),
],
),
);
}
}
You can implement this using StatefulWidget(). Create a List<Widget> outside your build of StatefulWidget() and inside your InkWell() append new Widget() you want to add and call setState((){})
class YellowBird extends StatefulWidget {
const YellowBird({Key? key}) : super(key: key);
#override
State<YellowBird> createState() => _YellowBirdState();
}
class _YellowBirdState extends State<YellowBird> {
List<Widget> myWidgetList = [
Text("hello"),
];
#override
Widget build(BuildContext context) {
return Column(
children: [
InkWell(
onTap: () {
print("Create Column in another Container");
myWidgetList.add(Text("hello 2"));
setState(() {});
},
child: Column(
children: const [
Icon(
Icons.view_agenda,
size: 20.0,
),
],
),
),
Column(
children: myWidgetList,
),
],
);
}
}
You can run same code here Link
Inside OnTap(), you can pass a function that can create a Widget.
e.g.
Widget buildContainer(){ return Container(child: Text("Stack Overflow"))}
Insert this function before your build method and then call it during the OnTap() event. You can, of course, modify the Container according to your exact requirements.
The important thing to understand here is that you can create functions with any permissible return type, even a specific Widget, this is especially useful when you want to create multiple identical widgets, as it reduces redundant code.

How to make Flutter Draggable feedback widget look the same like its child widget?

I would like to obtain the effect of having the same Draggable for both child and feedback composed widgets. Look at _getDraggablePaperSheets().
But I get totally different text size for the feedback widget. Why is that?
code disclaimer: every PaperSheet has its rotation and color kept inside Controller and is based on questionNumber, so it should look the same.
class Phase3Screen extends StatelessWidget {
static const ROUTE = '/oneoften/phase3';
final QuestionsController controller = Get.put(QuestionsController());
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: Stack(
children: [
DragTarget<int>(
builder: (
BuildContext context,
List<dynamic> accepted,
List<dynamic> rejected,
) {
return Container(
height: double.infinity,
width: double.infinity,
child: Align(
alignment: Alignment.bottomCenter,
child: Obx(() {
return Text('Question number: ${controller.getQuestionNumber}');
}),
),
);
},
onAccept: (int draggableData) {
debugPrint('draggable onAccept');
controller.nextQuestion();
},
onWillAccept: (item) {
debugPrint('draggable is on the target $item');
return true;
},
onLeave: (item) {
debugPrint('draggable has left the target $item');
},
),
Center(
child: Obx(
() {
return Stack(
children: _getDraggablePaperSheets(controller.getQuestionsStackSize),
);
},
),
),
],
),
),
),
);
}
List<Widget> _getDraggablePaperSheets(int currentQuestionsStackSize) {
List<Widget> sheets = [];
int i = 0;
logger.d("currentQuestionsStackSize = $currentQuestionsStackSize");
for (i = 1; i < currentQuestionsStackSize; i++) {
sheets.add(
Draggable(
maxSimultaneousDrags: 1,
data: i,
child: PaperSheet(questionNumber: i),
feedback: PaperSheet(questionNumber: i)
),
);
}
return sheets;
}
}
class PaperSheet extends GetView<QuestionsController> {
PaperSheet({
required this.questionNumber,
Key? key,
}) : super(key: key);
final questionNumber;
#override
Widget build(BuildContext context) {
return Container(
transform: Matrix4.rotationZ(controller.assignedRotationZ(questionNumber)),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
child: Container(
width: 250,
height: 420,
color: controller.assignedBackgroundColor(questionNumber),
child: Column(children: [
Expanded(
child: Container(
padding: const EdgeInsets.all(12.0),
alignment: Alignment.center,
child: Obx(
() {
return Text(
'Question: ${controller.currentQuestionText}',
style: TextStyle(
color: controller.assignedTextColor(questionNumber),
),
);
},
),
),
),
Expanded(
child: Container(
padding: const EdgeInsets.all(12.0),
child: Obx(() {
return Center(
child: Text(
'Answer: ${controller.currentQuestionAnswer}',
style: TextStyle(
color: controller.assignedTextColor(questionNumber),
),
),
);
}),
),
),
]),
),
),
);
}
}
Try to wrap with Material widget

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),
);
}
}

Anyone knows how to show landscape and potrait using these code below?

I'm trying to add potrait and landscape in my app, any idea why it doesn't show the build2 which I design for landscape?
Hope anyone can solve me problem!
import 'package:flutter/material.dart';
class Screen2 extends StatefulWidget {
const Screen2({Key? key}) : super(key: key);
#override
_Screen2State createState() => _Screen2State();
}
class _Screen2State extends State<Screen2> {
bool isShow = true;
void SimpleVoid() {
setState(() {
if (isShow) {
isShow = false;
} else {
isShow = true;
}
});
}
Widget buildColumn(context) {
if (MediaQuery.of(context).size.height > MediaQuery.of(context).size.width) {
return build(context);
} else {
return build2(context);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(45.0),
child: Column(
children: [
Stack(
children: <Widget>[
Container(
height: 700.0,
width: 600.0,
color: Colors.red,
),
Column(
children: [
if (isShow)
Container(
height: 700.0,
width: 600.0,
color: Colors.blue,
),
],
),
],
),
],
),
),
],
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.shopping_cart),
onPressed: () {
SimpleVoid();
},
),
);
}
Widget build2(BuildContext context) {
return Scaffold(
body: Row(
children: [
Padding(
padding: const EdgeInsets.all(45.0),
child: Row(
children: [
Container(
height: 300.0,
width: 200.0,
color: Colors.red,
),
Row(
children: [
Container(
height: 300.0,
width: 200.0,
color: Colors.blue,
),
],
),
],
),
),
],
),
);
}
}