How to center a widget inside a stack and moving it programmatically? - android

I have a widget in a stack that should be centered in the stack initially. The user should be able to move the widget programmatically in the stack.
I have tried a number of things. I can center the widget by setting the alignment of Stack to center using alignment: Alignment.center of the stack. And if the no TRBL properties of the Positioned widget is not set, then the widget is centered. But Then how do you move the widget from center to 2 pixels above center or 5 pixel right?
Stack(
alignment: Alignment.center,
children: [
Positioned(
child:Container(
height: 50,
width: 50,
child: Text('Move this programmatically')
)
)
]
)

You can play with this widget. I am using LayoutBuilder.
class StackAMovement extends StatefulWidget {
const StackAMovement({super.key});
#override
State<StackAMovement> createState() => _StackAMovementState();
}
class _StackAMovementState extends State<StackAMovement> {
double shiftX = 0;
double shiftY = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
shiftY += 2;
shiftX += 5;
setState(() {});
},
),
body: LayoutBuilder(
builder: (p0, constraints) {
final centerW = constraints.maxWidth / 2;
final centerH = constraints.maxHeight / 2;
return Stack(
children: [
Positioned(
left: centerW + shiftX -25,//-25 half of container width
top: centerH + shiftY -25,//-25 half of container height
child: Container(
color: Colors.purple,
height: 50,
width: 50,
child: Text('Move this programmatically')))
],
);
},
),
);
}
}

Stack(
alignment: Alignment.center,
children: [
Positioned.fill(
child:Center(
child:Container(
height: 50,
width: 50,
child: Text('Move this programmatically')
))
)
]
)

you can use this. very easy:
Stack(
alignment: Alignment.center,
children: [
Positioned(
left:1,
right:1,
child:Container(
height: 50,
width: 50,
child: Text('Move this programmatically')
)
)
]
)

Related

How to overlap the bottom container widget to the clip path container?

This is my code,
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Example',
home: Scaffold(
backgroundColor: Colors.green.shade200,
body: Column(
children: [
ClipPath(
clipBehavior: Clip.antiAlias,
clipper: MyCustomClipper(),
child: Container(
width: 600,
height: 300,
color: Colors.green.shade300,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(Icons.shopping_cart_outlined, color: Colors.black87, size: 30,),
Text('Example', style: TextStyle(fontSize: 22, color: Colors.black87,)),
],
),
),
),
Container(
height: 360,
width: 300,
color: Colors.white,
),
],
),
),
);
}
}
this is my clipper class, its just a basic design that we see on every other flutter app,
// clipper class
class MyCustomClipper extends CustomClipper <Path> {
#override
Path getClip(Size size) {
Path path = Path();
path.lineTo(0, size.height / 2 );
path.quadraticBezierTo(size.width / 2 , size.height, size.width, size.height / 2 );
path.lineTo( size.width , 0);
return path ;
}
#override
bool shouldReclip(covariant CustomClipper <Path> oldClipper ) {
return true ;
}
}
Current Situation
i really don't know how we can achieve such things
clip-path does not have any padding and margin by default
tried stack but no luck ?
used alignment property no luck
i read on other thread that clipping should be done separately not on the whole widget what does that mean ?

How do I end up with smooth DragEnd Flutter

How do I end the drop with proper velocity to a given offset
I am trying make something similar to SlidingUpPanel, but can't figure out how to implement.
final bottom = ValueNotifier<double>(0.0);
Stack(
children: [
ValueListenableBuilder<double>(
valueListenable: bottom,
builder: (context, value, child) => Positioned(
bottom: value,
left: 0,
right: 0,
child: GestureDetector(
onVerticalDragStart: (value) {
},
onVerticalDragUpdate: (DragUpdateDetails value) {
bottom.value -= value.delta.dy;
},
onVerticalDragEnd: (value) {
const double minFlingVelocity = 365.0;
if (value.velocity.pixelsPerSecond.dy.abs() >=
minFlingVelocity) {
// bottom.value =
// MediaQuery.of(context).size.height / 2;
}
},
child: Container(
width: double.maxFinite,
height: 200,
color: Colors.green,
),
),
),
)
],
),

Flutter: how to build the logic of moving blocks when changing the orientation of a mobile device?

Using flutter, i need to place in the mobile device two blocks so that:
in vertical position block_A was on top, and block_B was on the bottom
in horizontal position block_A is on the left and block_B is on the right
image of result
I implemented this through Wrap, setting the width of the block based on the width of the current screen, and Wrap put down the block automatically. But I'm not sure if this is the right decision.
class MainPage extends StatelessWidget {
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context).size;
double mainBoxWidth = screenSize.width / 100 * (screenSize.width > screenSize.height ? 50 : 100) ;
double mainBoxHeight = screenSize.height / 100 * (screenSize.width > screenSize.height ? 100 : 50) ;
return Scaffold(
body: Center(
child: Wrap(
children: [
Container(
child: Center(
child: Text("block_A"),
),
width: mainBoxWidth,
height: mainBoxHeight,
),
Container(
child: Center(
child: Text("block_B"),
),
width: mainBoxWidth,
height: mainBoxHeight,
),
],
),
),
backgroundColor: Colors.green
);
}
}
Please tell me how to correctly implement this task. Thanks.
As with most things in Flutter, there are a few ways this could be done. Here's one way:
class MainPage extends StatelessWidget {
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context).size;
final isLandscape = screenSize.width > screenSize.height;
return Scaffold(
body: isLandscape
? Row(
children: _buildChildren(),
)
: Column(
children: _buildChildren(),
),
backgroundColor: Colors.white,
);
}
List<Widget> _buildChildren() {
return [
Expanded(
child: Container(
color: Colors.yellow,
child: Center(
child: Text("block_A"),
),
),
),
Expanded(
child: Container(
color: Colors.green,
child: Center(
child: Text("block_B"),
),
),
),
];
}
}

Emulating horizontal list of images as seen in google play app

I would like to create a widget that behaves same way as the horizontal scrolling lists (for example for recommended apps) in google play app.
An example of what I mean:
I have tried to use the Page Viewer widget but it does not quite do same thing. Some noticiable facts:
1) 3 perfectly squared images are fully seen and another one is partially shown. The second one (the greenish one) is right in the center.
2) The left most image (the blue one) is perfectly aligned with the Caption "Recommended for you"
3) All 4 squared images have rounded corners.
4) It supports item snapping
This is the best I have been able to mimic this behaviour with the PageView widget:
Red is the background color of the container containing the pageview.
Green is the color for even items and Blue for odd items
Inside every item an image of 100x100 is added.
This is the code:
return Container(
width: double.infinity,
color: Colors.red,
height: 100,
child:
PageView(
pageSnapping: true,
controller:
PageController(initialPage: 1, viewportFraction: 0.315),
children: List<Widget>.generate(10, (index) {
return Container(
color: index%2 ==0 ? Colors.green : Colors.blue,
child:Image.network("http://via.placeholder.com/100x100",
fit: BoxFit.fitHeight)
);
})));
Width my code there are 2 things that won't work:
1) I can't make appear a partially seen item from the right side keeping the 3 fully visible items and the second perfectly centered as in the original image form google play, just by using viewportFraction.
2) I can't apply rounded corners to the item images because as you see the container is not squared but the image is. So when I apply ClipRRect it is not applied correctly. I have tried to add another container forcing its size to 100x100 and apply ClipRRect on the image inside this container but when it is inside a PageView it seems the width/height given have no effect. They seem controlled internally by PageView.
So, Could anybody help on this problems to get something with the same behaviour as the google play horizontal scrollable list?
Cheers!
class SO extends StatelessWidget {
#override
Widget build(BuildContext context) {
double edge = 120.0;
double padding = edge / 10.0;
return Scaffold(
appBar: AppBar(),
body: Container(
color: Colors.red,
padding: const EdgeInsets.symmetric(vertical: 8),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
for (int i = 0; i < 10; i++)
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.all(padding),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(edge * .2)),
child: Container(
width: edge,
height: edge,
color: Colors.blue,
child: Image.network("http://via.placeholder.com/${edge.round()}x${edge.round()}", fit: BoxFit.fitHeight),
),
),
),
Container(
width: edge + padding,
padding: EdgeInsets.only(left: padding),
child: Text(
'foo app bar baz app apk',
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
Padding(
padding: EdgeInsets.only(left: padding),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('4.2'),
Icon(
Icons.star,
size: 16,
)
],
),
),
],
)
],
),
),
),
);
}
}
which gives
You can modify PageScrollPhysics to create the snapping effect.
This what I did,
import 'package:flutter/material.dart';
Future<void> main() async {
runApp(
MaterialApp(
home: new Main(),
),
);
}
class Main extends StatefulWidget {
#override
_MainState createState() => _MainState();
}
class _MainState extends State<Main> {
static const _scrollPhysics =
const ExtentScrollPhysics(itemExtent: 80, separatorSpacing: 10);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Recommended for you",
style: const TextStyle(fontWeight: FontWeight.bold),
),
IconButton(
icon: Icon(Icons.arrow_forward),
onPressed: () {},
)
],
),
SizedBox.fromSize(
size: Size.fromHeight(130),
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: 30,
physics: _scrollPhysics,
separatorBuilder: (context, _) =>
SizedBox(width: _scrollPhysics.dividerSpacing),
itemBuilder: (context, index) {
return SizedBox(
width: _scrollPhysics.itemExtent, // set height for vertical
child: CardItem(),
);
},
),
),
],
),
),
);
}
}
class CardItem extends StatefulWidget {
#override
_CardItemState createState() => _CardItemState();
}
class _CardItemState extends State<CardItem> {
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
AspectRatio(
aspectRatio: 1,
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(20.0),
),
),
),
const SizedBox(height: 8.0),
Text(
"Tile Name",
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: const TextStyle(fontSize: 12.0),
),
Text(
"1 MB",
style: const TextStyle(
fontSize: 12.0,
color: Colors.black54,
),
),
],
);
}
}
class ExtentScrollPhysics extends ScrollPhysics {
final double itemExtent;
final double dividerSpacing;
const ExtentScrollPhysics(
{ScrollPhysics parent, this.itemExtent, double separatorSpacing})
: assert(itemExtent != null && itemExtent > 0),
dividerSpacing = separatorSpacing ?? 0,
super(parent: parent);
#override
ExtentScrollPhysics applyTo(ScrollPhysics ancestor) {
return ExtentScrollPhysics(
parent: buildParent(ancestor),
itemExtent: itemExtent,
separatorSpacing: dividerSpacing,
);
}
double _getItem(ScrollPosition position) {
return position.pixels / (itemExtent + dividerSpacing);
}
double _getPixels(ScrollPosition position, double item) {
return item * (itemExtent + dividerSpacing);
}
double _getTargetPixels(
ScrollPosition position, Tolerance tolerance, double velocity) {
double page = _getItem(position);
if (velocity < -tolerance.velocity)
page -= 0.5;
else if (velocity > tolerance.velocity) page += 0.5;
return _getPixels(position, page.roundToDouble());
}
#override
Simulation createBallisticSimulation(
ScrollMetrics position, double velocity) {
// If we're out of range and not headed back in range, defer to the parent
// ballistics, which should put us back in range at a page boundary.
if ((velocity <= 0.0 && position.pixels <= position.minScrollExtent) ||
(velocity >= 0.0 && position.pixels >= position.maxScrollExtent))
return super.createBallisticSimulation(position, velocity);
final Tolerance tolerance = this.tolerance;
final double target = _getTargetPixels(position, tolerance, velocity);
if (target != position.pixels)
return ScrollSpringSimulation(spring, position.pixels, target, velocity,
tolerance: tolerance);
return null;
}
#override
bool get allowImplicitScrolling => false;
}

How to make an IMAGE show FULL VIEW on image Slider / Carousel in FLUTTER and how to make a table over the image slider?

I have an Image Slider / Carousel, but it won't show a large / full image as I want. It only shows a half image and its contain a shadow border in it...
Here is what I've done:
Here is the view that I hope I can make:
I've 2 dart files.
here are the one who calls it:
final List<String> imgList = [
'images/Polo 01.png',
'images/Polo 02.png',
'images/Polo 03.png',
'images/Polo 04.png',
'images/Polo 05.png',
];
final List child = map<Widget>(
imgList,
(index, i) {
return Container(
margin: EdgeInsets.all(5.0),
child: ClipRRect(
child: Stack(children: <Widget>[
Image.asset(i, fit: BoxFit.cover, width: 1000.0),
Positioned(
bottom: 0.0,
left: 0.0,
right: 0.0,
child: Container(
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
),
),
]),
),
);
},
).toList();
List<T> map<T>(List list, Function handler) {
List<T> result = [];
for (var i = 0; i < list.length; i++) {
result.add(handler(i, list[i]));
}
return result;
}
class CarouselWithIndicator extends StatefulWidget {
#override
_CarouselWithIndicatorState createState() => _CarouselWithIndicatorState();
}
class _CarouselWithIndicatorState extends State<CarouselWithIndicator> {
int _current = 0;
#override
Widget build(BuildContext context) {
return Column(children: [
CarouselSlider(
items: child,
autoPlay: true,
enlargeCenterPage: false,
aspectRatio: 2.0,
onPageChanged: (index) {
setState(() {
_current = index;
});
},
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: map<Widget>(
imgList,
(index, url) {
return Container(
width: 8.0,
height: 8.0,
margin: EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0),
);
},
),
),
]);
}
}
and here to show the view:
body: ListView (
children: <Widget>[
new Align
(
alignment: Alignment.topCenter,
child: Container(
padding: const EdgeInsets.all(5.0),
child: Text('Nama Produk', style: TextStyle(color: Colors.black)),
)
Padding( //I M A G E - S L I D E R
padding: EdgeInsets.symmetric(vertical: 15.0),
child: Column(children: [
CarouselWithIndicator(),
])
),
I've 3 questions.
how to make full image like no. 3 ?
how to create a table like no. 2 ?
how to make a different background color / give a background at table like no.1 ?
Your map method is unnecessary you can do that easier like this:
final List<Color> colorList = [
Colors.blue,
Colors.red,
Colors.green,
Colors.deepPurple,
Colors.yellow,
];
final List<Widget> colorBackgrounds = colorList
.map((color) => Container(
margin: EdgeInsets.all(5.0),
child: Container(
width: 500,
height: 500,
color: color,
child: Text("Hello"),
),
))
.toList();
The above code should tell you how to set a background color.
In terms of showing a "full image" you should look at the CarouselSlider's aspectRatio property. Here's a hint width/height.
For the table consider creating a widget tree like this:
Column
Row
Text
Expanded
Text
Row
...
Alternatively look into Table, TableRow and TableCell.

Categories

Resources