Flutter: How to drag points on a plot - flutter

I am still relatively new to flutter and building a app that can allow user to drag points on a xy plane by holding the point and dragging it.( e.g dragging a point at (1 ,1) to (2,3) )
Did not come across any libraries/packages that can do this function. So was wondering if this would be possible ? Much thanks!

Seems like you are looking for Draggable.
Example from doc
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;
});
},
),
],
);
}
}

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

How do i disable Container childs to expand?

So i got a Container in a Scaffold (Material). But if i add a ElevatedButton as a child of this Container the ElevatedButton the Button Expands to the full size of the parent Container. How can i avoid it?
I don't know whether it's the fault of flutter installation or if it's on me.
Here's the code.
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
String status = "Status: OK";
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.teal,
appBar: AppBar(
backgroundColor: Colors.teal,
elevation: 0,
centerTitle: true,
automaticallyImplyLeading: false,
title: Text(status),
),
body: Center(
child: Column(
children: [
SubmitContainer(),
],
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
),
),
);
}
}
class InputContainer extends StatelessWidget {
const InputContainer({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: TextField(),
width: 200,
height: 200,
color: Colors.yellow,
);
}
}
class SubmitContainer extends StatelessWidget {
const SubmitContainer({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: SizedBox(
child: ElevatedButton(
child: Text("GO"),
onPressed: () {},
),
width: 300,
height: 50,
),
width: MediaQuery.of(context).size.width,
);
}
}
And the endresult looks like this:
When we use FittedBox it occupies the content width. Use FittedBox for Button.
Container(
child: SizedBox(
child: FittedBox(
child: ElevatedButton(
child: Text("GO"),
onPressed: () {},
),
),
width: 300,
height: 50,
),
width: MediaQuery.of(context).size.width,
);
Try wrapping your Container widget's child with a Center widget
This way even if the Container itself is wide, the content will have automatic width
Container(
child: Center(
child: //...
),
)
Check out this page from the documentation for more information
https://docs.flutter.dev/development/ui/layout/constraints#example-3
You did a mistake. Inside your container widget in SubmitContainer, you defined width: MediaQuery.of(context).size.width, that is why the elevated button stretched to match the full screen width. Just use do the following:
SizedBox(
child: ElevatedButton(
child: Text("GO"),
onPressed: () {},
),
width: 150,
height: 50,
);

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

Space this evenly according to the circles, ignoring the space taken up by the text

I have this widge in flutter
I am using a Progress Bar because eventually there will be progress, this is an example
class MyWidget extends StatelessWidget {
const MyWidget({
Key key,
}) : super(key: key);
final double containersWidth = 510;
#override
Widget build(BuildContext context) {
return Container(
alignment: Alignment.center,
width: containersWidth,
padding: EdgeInsets.only(top: 12.0),
child: Stack(
children: [
Positioned(
top: 14.0,
width: containersWidth,
child: LinearProgressIndicator(
value: 0,
backgroundColor: Colors.amberAccent,
minHeight: 3,
valueColor: new AlwaysStoppedAnimation<Color>(Colors.redAccent),
),
),
Container(
width: containersWidth,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_Circle(),
_Circle(),
_Circle(),
_Circle(),
_Circle(),
_Circle(),
],
),
),
],
),
);
}
}
class _Circle extends StatelessWidget {
const _Circle({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
width: 30.0,
height: 30.0,
decoration: new BoxDecoration(
color: Colors.amberAccent,
shape: BoxShape.circle,
),
),
],
);
}
}
This produces a layout like this one, which is fine
Now, I need to add a label under each circle, but keep the space the same as the image, but when I do this,
class _Circle extends StatelessWidget {
const _Circle({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(
width: 30.0,
height: 30.0,
decoration: new BoxDecoration(
color: Colors.amberAccent,
shape: BoxShape.circle,
),
),
Text('example')
],
);
}
}
the width of the container increases, and since the space is counted from the center of the container, I obtain something like this
I need the circles placed as in the first image, and the labels under the circles, centered, but not being counted as part of the width of the container.
I tried to used Positioned to wrap the labels but it didn't work because the overflow is hidden and also I was not able to position the text centered from the circle. Any help is greatly appreciated.
Edit:
this is how it looks when using Positioned
with the following code
class _Circle extends StatelessWidget {
const _Circle({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Stack(
children: [
Container(
width: 30.0,
height: 30.0,
decoration: new BoxDecoration(
color: Colors.amberAccent,
shape: BoxShape.circle,
),
),
Positioned(
top: 14,
child: Text('example')
)
],
);
}
}
The overflow is hidden, and besides, I don' know how to center the text relative to the Stack ( and the circle)
I am thinking I have to use SizedOverflow box, I will see if I can figure it out
I was able to solve it like this
class MyWidget extends StatelessWidget {
const MyWidget({Key key}) : super(key: key);
final double containersWidth = 510;
#override
Widget build(BuildContext context) {
return Container(
height: 30,
alignment: Alignment.center,
width: containersWidth,
padding: EdgeInsets.only(top: 12.0),
child: Stack(
//mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LinearProgressIndicator(
value: 0,
backgroundColor: Colors.yellowAccent,
minHeight: 3,
valueColor: new AlwaysStoppedAnimation<Color>(Colors.yellowAccent),
),
Container(
// color: Colors.redAccent.withAlpha(100),
width: containersWidth,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_Circle(),
_Circle(),
_Circle(),
_Circle(),
_Circle(),
_Circle(),
],
),
),
],
),
);
}
}
class _Circle extends StatelessWidget {
const _Circle({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return SizedOverflowBox(
size: Size(30, 47.3),
child: Column(
children: [
Container(
width: 30.0,
height: 30.0,
decoration: new BoxDecoration(
color: Colors.yellowAccent,
shape: BoxShape.circle,
),
),
SizedBox(height: 4.3,),
Text("example"),
],
),
);
}
}
If there is something wrong with my code, please let me know
This is the result

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

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