Tap is perceived as vertical drag when having hardcoded swipe gesture - dart

I have 1 Gesture Detector that wraps 10 different cards and it allows swiping them. Each card has 3 on tap Gesture Detectors(buttons basically). Swipe works as expected but first 6 cards don't trigger the tap action when tapped (Gesture Arena tells me horizontal drag is fighting vertical drag -> so the tap gesture is perceived as vertical drag).
I find it Strange that the last 4 cards trigger on tap and swipe works perfect
I've tried changing GestureDetectors to InkWell but it didn't work out.
#override
Widget build(BuildContext context) {
return GestureDetector(
onHorizontalDragStart: _onHorizontalDragStart,
onHorizontalDragUpdate: _onHorizontalDragUpdate,
onHorizontalDragEnd: _onHorizontalDragEnd,
behavior: HitTestBehavior.translucent,
child: Stack(
children: _buildCards(),
),
);
}
List<Widget> _buildCards() {
return [
_buildCard(0, 10, scrollPercent),
_buildCard(1, 10, scrollPercent),
_buildCard(2, 10, scrollPercent),
_buildCard(3, 10, scrollPercent),
_buildCard(4, 10, scrollPercent),
_buildCard(5, 10, scrollPercent),
_buildCard(6, 10, scrollPercent),
_buildCard(7, 10, scrollPercent),
_buildCard(8, 10, scrollPercent),
_buildCard(9, 10, scrollPercent),
];
}
Widget _buildCard(int cardIndex, int cardCount, double scrollPercent) {
final cardScrollPercent = scrollPercent / (1 / cardCount);
final parallax = scrollPercent - (cardIndex / cardCount);
return FractionalTranslation(
translation: Offset(cardIndex - cardScrollPercent, 0.0),
child: Transform(
transform: _buildCardProjection(cardScrollPercent - cardIndex),
child: card1(parallax, cardIndex
),
)
);
}
Card1 is appealed last and it represents the card itself..
Here is the code for the onTap property of GestureDetector of Card1
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) => CustomDialog(
title: "Title",
description:"Test",
buttonText: "Okay",
),
);
},

It sounds like you might be interested in replacing your setup with a PageView widget. It uses a PageController to manage the swipe gestures. Check out the video on it Widget of the Week - PageView

Related

ListView - Card (Flutter Layout)

Flutters!
I need to recreate this layout in Flutter to be displayed as items in a ListView.
Both layouts (Emma & Tonny) are the same.. the only difference is the colors that depend on some other data/status, something that I will decide programmatically later.
I already have the ListView.builder as follow:
ListView.builder(
itemCount: WeeklyList.contacts.length,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () => onTapMe(WeeklyList.contacts[index]),
child: TripItemCard(index, WeeklyList.contacts[index]));
})
and.... the main missing guy:
Widget TripItemCard(int index, Info info) {
return SizedBox(
height: 116,
child: Card(
//.... Card Layout.....
)
);
NOTE: I wrapped the Card with a SizedBox to be able to have a Height specified for all cards.
There are 8 widgets in total:
1- The Card
2- Picture
3- Fullname
4- Role
5- PickUp Label
6- PickUp Time
7- DropOff Label
8- DropOff Time
Lastly and Very Important Things
1- Please be advised that there are 2 TEXTs (Name and DropOff Status) who have BACKGROUND and TEXT color... and both of them... fully expanded (width). This is very important to maintain the horizontal color balance.
2- Also PickUp and DropOff are aligned to the right where the PickUp and DropOff Time/Status respectively are aligned to the left.
PLEASE.Help();
thanks.dart
The basic layout should look like this and you can add the details to it.
Row(children: [
Image.asset(name),
Column(
children: [
Container(
color: const color,
child: const Text(data),
),
Text(data),
Text(data),
Text(data),
],
),],),

How do I switch between two different widgets on the same location in flutter?

I have a card widget which has some info and a button. On button press, I want to animate the card to change to a different card at the same location. The animation will be added later.
As per my current code, I am using a bool to control which widget to display.
My card1 has the following code-
SliverFillRemaining(
child: Padding(
padding: const EdgeInsets.only(
top: 10.0, left: 6.0, right: 6.0, bottom: 6.0),
child: detailsCardIsVisible ? Card(
elevation: 2.0,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8.0))),
child: productInfoCard()) : ProductEnquiryWidget()
),
)
The ProductEnquiryWidget is the second card. It has a form with a button. What I want to do is to submit the form on button press and animate back to the first card.
How do I do that? I don't want to put the code for the second card in the same file as the first card as it will make the code too large.
I am using a boolean named detailsCardIsVisible to control which card to display. Is there a way I could manipulate that variable from button tap in the second card?
https://docs.flutter.io/flutter/widgets/AnimatedCrossFade-class.html
AnimatedCrossFade(
duration: const Duration(seconds: 3),
firstChild: FirstChild(),
secondChild: SecondChild(),
crossFadeState: _first ? CrossFadeState.showFirst : CrossFadeState.showSecond,
)
If you don't want to animate, you can use Visibility:
https://api.flutter.dev/flutter/widgets/Visibility-class.html
It takes a replacement Widget that's displayed when visible is false.

Flutter, How to make my raw material buttons large and more tightly packed together.

I have some code that creates 7 Raw Material Buttons in the shape of a circle. However I cannot seem to change the size of the circle, or position them closer together.
Page.dart
Row(
children: <Widget>[
new ThemeButton(Colors.red, () => print("red")),
new ThemeButton(Colors.orange, () => print("orange")),
new ThemeButton(Colors.yellow, () => print("yellow")),
new ThemeButton(Colors.green, () => print("green")),
new ThemeButton(Colors.blue, () => print("blue")),
new ThemeButton(Colors.indigo, () => print("pink")),
new ThemeButton(Colors.purple, () => print("purple")),
],
),
ThemeButton.dart
#override
Widget build(BuildContext context) {
return RawMaterialButton (
shape: CircleBorder(),
fillColor: _themeColour,
elevation: 0.0,
highlightElevation: 0.0,
onPressed: () => _onPressed(),
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
);
}
Display:
So the three issue I am facing are all around the size and positioning on the element.
The Circles are too small for my liking.
The space around the circles are too wide.
I can click outside the circle and it will still register the click.
I have looked at the arguments for the Raw Material Button and cannot see what I can change. Adding a padding widget and setting it to 0 doesn't help.
Changing the padding property, unfortunately, did not work for me. However, changing the constraints parameter like in this example turned out to be quite effective:
RawMaterialButton(
constraints: BoxConstraints.tight(Size(36, 36)),
onPressed: null,
child: Icon(Icons.trending_up, size: 18),
shape: new CircleBorder(),
elevation: 0.0,
fillColor: Color.fromARGB(255, 240, 240, 240),
),
Hope it helps!
According to the docs for RawMaterialButton, there should be a padding property that you can set in the constructor, which is typical for this type of component. Try updating the padding value in the constructor of the button instead of adding a new Widget. To be clear, trying setting padding to EdgeInsets.all(0.0).
For further sizing, you can start to look at the Row class properties, specifically MainAxisSize, or wrapping them in variations of the Flexible Widget family.

Position widget in stack with percent

Let's say I want to position a widget inside a Stack but with a percent of the Stack position instead of a fixed size. How to do that in flutter ?
I'd expect that the Positionned.fromRelativeRect constructor would be the thing, using floats between 0 and 1. But seems like no.
Align allows to position the widget in percent. But heightFactor and widthFactor changes the Align size instead of the child size. Which is not what I want.
You can combine a Positioned.fill and LayoutBuilder to achieve such result.
new Stack(
children: <Widget>[
new Positioned.fill(
child: new LayoutBuilder(
builder: (context, constraints) {
return new Padding(
padding: new EdgeInsets.only(top: constraints.biggest.height * .59, bottom: constraints.biggest.height * .31),
child: new Text("toto", textAlign: TextAlign.center,),
);
},
),
)
],
),
one thing that i figured out not long ago is that you can position a widget on the screen using a container its alignment parameter with the help of the Alignment.lerp(x,y,z) function
//the widget will be placed in the center of the container
alignment: Alignment.lerp(Alignment.topCenter, Alignment.bottomCenter, 0),
//the widget will be placed in the bottom of the container
alignment: Alignment.lerp(Alignment.topCenter, Alignment.bottomCenter, 1),
//the widget will be placed in the bottom quarter of the container
alignment: Alignment.lerp(Alignment.topCenter, Alignment.bottomCenter, 0.5),
//the widget will be placed in the top quarter of the container
alignment: Alignment.lerp(Alignment.topCenter, Alignment.bottomCenter, -0.5),
use FractionalOffset & FractionallySizedBox it's very simple in contrast
around no unnecessary code like Positioned.fill
no no extra calculations like Alignment
...
Container(
color: Colors.blue[200],
alignment: FractionalOffset(0.7, 0.6),
child: FractionallySizedBox(
widthFactor: 0.1,
heightFactor: 1/3,
child: Container(color: Colors.red[900])
),
),
...
If you want to use LayoutBuilder then do without Positioned.fill, like this:
you need one LayoutBuilder, no need to turn around every elements and use Transform.translate instead of Padding.
new LayoutBuilder(
builder: (context, constraints) {
return Stack(
children: <Widget>[
Transform.translate(
offset: Offset(
constraints.biggest.width * left,
constraints.biggest.height * top),
child: new Text("toto", textAlign: TextAlign.center,),
),
...
],
);
}
)

How do I rotate something 15 degrees in Flutter?

The Flutter docs show an example of rotating a "div" by 15 degrees, both for HTML/CSS and Flutter code:
The Flutter code is:
var container = new Container( // gray box
child: new Center(
child: new Transform(
child: new Text(
"Lorem ipsum",
),
alignment: FractionalOffset.center,
transform: new Matrix4.identity()
..rotateZ(15 * 3.1415927 / 180),
),
),
);
And the relevant parts are new Transform and alignment: FractionalOffset.center and transform: new Matrix4.identity()..rotateZ(15 * 3.1415927 / 180)
I'm curious, is there a simpler way to rotate a Container in Flutter? Is there a short-hand for the case of "15 degrees" ?
Thanks!
In mobile apps, I think it's kind of rare to have things start out rotated 15 degrees and just stay there forever. So that may be why Flutter's support for rotation is better if you're planning to adjust the rotation over time.
It feels like overkill, but a RotationTransition with an AlwaysStoppedAnimation would accomplish exactly what you want.
new RotationTransition(
turns: new AlwaysStoppedAnimation(15 / 360),
child: new Text("Lorem ipsum"),
)
If you want to rotate something 90, 180, or 270 degrees, you can use a RotatedBox.
new RotatedBox(
quarterTurns: 1,
child: new Text("Lorem ipsum")
)
You can use Transform.rotate to rotate your widget. I used Text and rotated it with 45˚ (π/4)
Example:
import 'dart:math' as math;
Transform.rotate(
angle: -math.pi / 4,
child: Text('Text'),
)
If you are working with a canvas (as in a CustomPaint widget), you can rotate 15 degrees like this:
import 'dart:math' as math;
class MyPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
canvas.save();
// rotate the canvas
final degrees = 15;
final radians = degrees * math.pi / 180;
canvas.rotate(radians);
// draw the text
final textStyle = TextStyle(color: Colors.black, fontSize: 30);
final textSpan = TextSpan(text: 'Hello, world.', style: textStyle);
TextPainter(text: textSpan, textDirection: TextDirection.ltr)
..layout(minWidth: 0, maxWidth: size.width)
..paint(canvas, Offset(0, 0));
canvas.restore();
}
#override
bool shouldRepaint(CustomPainter old) {
return false;
}
}
However, if you are doing something simple then I would use a RotatedBox or Transform.rotate as suggested by the other answers.
There is Two Main Flutter Widget available for this functionality, RotationTransition and Transform.rotate
another supported option is RotatedBox but this rotate widget only
supports quarter turns, which means they support vertical and only horizontal orientation.
and if you rotate already created widgets like Container so for the container by transformAlignmentyou can rotate widget.
RotationTransition: which animates the rotation of a widget, mainly we prefer when we need rotation with animation transition.https://api.flutter.dev/flutter/widgets/RotationTransition-class.html
Transform.rotate: which applies a rotation paint effect, they Create a widget that transforms its child using a rotation around the center.
RotationTransition Widget example:-
RotationTransition(
turns: AlwaysStoppedAnimation(15 / 360),
child: Text("flutter is awesome")
)
Transform.rotate Widget example :-
Transform.rotate(
angle: 15 * math.pi / 180,
child: Text("flutter is awesome")
)
Container(
decoration: BoxDecoration(borderRadius: BorderRadius.circular(50), color: Color(0xffF6F8FF),),
width: MediaQuery.of(context).size.width*0.6,
height: MediaQuery.of(context).size.height*0.4,
alignment:
new Alignment(0, 0),
transform:
new Matrix4.translationValues(MediaQuery.of(context).size.width * 0.55, -250.0, 0.0)
..rotateZ(28 * 3.1415927 / 180),
),

Resources