How to make a card widget touchable in Flutter? - dart

I am currently making an app with lists of a Card widgets. This is a code snippet:
new GestureDetector(
onLongPress: () {
showAlert();
//pops up an AlertDialog
},
child: new Card(child: new Text("Hello"))
)
Is it possible to make the Card widget touchable, so the user can feel/see that the card is (long)tapped? I am searching for an 'InkWell-something result'.
Edit: I want to have a splash effect on my Card widgets when I longpress them.
An example of the splash effect that I mean is given in the following GIF:

Use this
return Card(
child: InkWell(
onTap: () {},
onLongPress: () {}
child: Container(),
));

Related

Why does WillPopScope always disable swipe backwards?

When pushing on a new screen and wanting to disable the ability to swipe backwards I found the WillPopScope widget.
WillPopScope(
onWillPop: () async => false,
child: <some child>
however, it prevents the swipe gesture regardless of whether or not I return true of false.
Is it possible to tell this widget that it can pop back on certain screen states?
So effectively I would have:
WillPopScope(
onWillPop: () async => widget._canSwipeBack,
child: <some child>
Right now I have add/not-add the widget based on the screen state which seems quite odd.
Please refer to the below code
Without wrapping the widget with WillPopScope usually its performs Navigator.pop(context);
// disables swiping back
WillPopScope(
// disables swiping back or navigating back
onWillPop: () {},
child: Scaffold(
body: Container(),
),
);
WillPopScope(
onWillPop: () {
// whenever you want to navigate back to specific route
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondRoute()),
);
},
child: Scaffold(
body: Container(),
),
);
WillPopScope(
onWillPop: () {
// pop back
Navigator.pop(context);
},
child: Scaffold(
body: Container(),
),
);

Draggable FloatingActionButton in Flutter

I want to make a draggable floating button and if possible to print the drag position in the console.
Due to the ability to compose Flutter widgets in whatever way you want to, you can simply do it like this:
Draggable(
feedback: FloatingActionButton(child: Icon(Icons.drag_handle), onPressed: () {}),
child: FloatingActionButton(child: Icon(Icons.drag_handle), onPressed: () {}),
childWhenDragging: Container(),
onDragEnd: (details) => print(details.offset))
This Draggable can be passed as the floatingActionButton argument to a Scaffold.
The feedback parameter controls how the widget that is dragged about in the end will look like and child specifies how the stationary Draggable should look like. As you probably only want to see one FloatingActionButton at a time, you can pass an empty Container to childWhenDragging.
The Offset (position) of the drag will be printed to the console when releasing the drag.
I needed to add a positioned widget to set the position of my button
class _MyHomePageState extends State<MyHomePage> {
Offset position =Offset(20.0, 20.0);
#override
Widget build(BuildContext context) {
return new Scaffold(
body: Stack(
children: <Widget>[
Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("data_repo/img/bg1.jpg"),
fit: BoxFit.cover,
),
),
),
Positioned(
left : position.dx,
top : position.dy ,
child : Draggable(
feedback: Container(
child : FloatingActionButton(child: Icon(Icons.add), onPressed: () {})
),
child: Container(
child : FloatingActionButton(child: Icon(Icons.add), onPressed: () {}),
),
childWhenDragging: Container(),
onDragEnd: (details){
setState(() {
position = details.offset;
});
print(position);
print(position.dx);
print(position.dy);
}))
],
));
}
}
You can use the DraggableFloatingButton package: https://pub.dartlang.org/packages/draggable_floating_button

How to exit the app on back button press? [duplicate]

This question already has an answer here:
How To Override the “Back” button in Flutter? [duplicate]
(1 answer)
Closed 4 years ago.
I have an app that needs move from screen 1 to screen two ....now when the user presses the back button..it should show a dialog box...if the user presses yes it has to exit...any help?the upper solutions don't work
It seems like you can use WillPopScope. You also need to pass a callback function which will indicate what will happen on pressing the back button.
In your case, you can add the code to show an AlertDialog which will ask for exit confirmation from the user.
You can simply wrap your Scaffold inside a WillPopScope.
Example:
Widget build(BuildContext context) {
return WillPopScope(
child: /*Your scaffold widget*/
onWillPop: () {
return showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Confirm Exit"),
content: Text("Are you sure you want to exit?"),
actions: <Widget>[
FlatButton(
child: Text("YES"),
onPressed: () {
SystemNavigator.pop();
},
),
FlatButton(
child: Text("NO"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
}
);
return Future.value(true);
},

ListView does not refresh whereas attached list does (Flutter)

I'm trying to get familiar with flutter and I'm facing some weird case. I want to build a dynamic ListView where a + button allows to add elements. I wrote the following State code:
class MyWidgetListState extends State<MyWidgetList> {
List<Widget> _objectList = <Widget>[
new Text('test'),
new Text('test')
];
void _addOne() {
setState(() {
_objectList.add(new Text('test'));
});
}
void _removeOne() {
setState(() {
_objectList.removeLast();
});
}
#override
Widget build(BuildContext context) {
return new Column(
children: <Widget>[
new ListView(
shrinkWrap: true,
children: _objectList
),
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new IconButton(
icon: new Icon(Icons.remove_circle),
iconSize: 36.0,
tooltip: 'Remove',
onPressed: _objectList.length > 2 ? _removeOne : null,
),
new IconButton(
icon: new Icon(Icons.add_circle),
iconSize: 36.0,
tooltip: 'Add',
onPressed: _addOne,
)
],
),
new Text(_objectList.length.toString())
],
);
}
}
My problem here is that the ListView is visually stuck with the 2 elements I initialized it with.
Internally the _objectList is well managed. For testing purpose I added a simple Text widget at the bottom that shows the size of the list. This one works fine when I click the Add/Remove buttons and it gets properly refreshed. Am I missing something?
Flutter is based around immutable data. Meaning that if the reference to an object didn't change, the content didn't either.
The problem is, in your case you always send to ListView the same array, and instead mutate its content. But this leads to ListView assuming the list didn't change and therefore prevent useless render.
You can change your setState to keep that in mind :
setState(() {
_objectList = List.from(_objectList)
..add(Text("foo"));
});
Another Solution!!
Replace ListView with ListView.builder
Code:
ListView.builder(
itemBuilder: (ctx, item) {
return _objectList[item];
},
shrinkWrap: true,
itemCount: _objectList.length,
),
Output:

How to use multiple navigators

I currently have a MaterialApp in my flutter application which makes the use of the Navigator extremely easy, which is great. But, I'm now trying to figure out how to create more navigators for particular views/widgets. For example I've got a custom tab bar with another widget/view in. I'd now like that widget/view to have it's own navigation stack. So the goal is to keep the tab bar at the top while I navigate to other pages from within my widget/view.
This question is almost exactly this: Permanent view with navigation bar in Flutter but in that code, there is no MaterialApp yet. Nesting MaterialApps give funky results and I don't believe that that would be a solution.
Any ideas?
You can create new Navigator for each page. As a reference check CupertinoTabView
Or simple example:
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
Navigator _getNavigator(BuildContext context) {
return new Navigator(
onGenerateRoute: (RouteSettings settings) {
return new MaterialPageRoute(builder: (context) {
return new Center(
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Text(settings.name),
new FlatButton(
onPressed: () =>
Navigator.pushNamed(context, "${settings.name}/next"),
child: new Text('Next'),
),
new FlatButton(
onPressed: () =>
Navigator.pop(context),
child: new Text('Back'),
),
],
),
);
});
},
);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Column(
children: <Widget>[
new Expanded(
child: _getNavigator(context),
),
new Expanded(
child: _getNavigator(context),
),
],
),
);
}
}
void main() {
runApp(new MaterialApp(
home: new Home(),
));
}
you could give first material app's context to secondary material app;
and in secondary material app ,when you need to go back first material app,
you could check whether the secondary app can pop, with this line:
Navigator.of(secondaryContext).canPop()
if true, then you could keep using,else use first material app's context,
like this:
Navigator.of(parentContext).pop();
otherwise

Resources