I'm trying to show the full image that has been clicked on from my drawer.
I have a liste of images that I display in my drawer and What I want is that when I click on a specific image, it closes my drawer and show the image on my screen in a kind of an image slider where I can switch images directly from the opened image.
here is my code where I extract my list of images from my asset folder :
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class GetImages extends StatefulWidget {
const GetImages({super.key});
#override
State<GetImages> createState() => _GetImagesState();
}
class _GetImagesState extends State<GetImages> {
List<String> imagePaths = [];
#override
void initState() {
_initImages();
super.initState();
}
Future _initImages() async {
final Map<String, dynamic> assets =
jsonDecode(await rootBundle.loadString('AssetManifest.json'));
setState(() {
imagePaths = assets.keys
.where((String key) => key.contains('photos/'))
.where((String key) => key.contains('.JPG'))
.toList();
});
}
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return GridView.count(
crossAxisCount: constraints.maxWidth > 700 ? 4 : 2,
children: imagePaths
.map(
(path) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 17),
child: Image.asset(path),
),
)
.toList(),
);
});
}
}
And here is my code for my drawer :
import 'package:flutter/material.dart';
import 'package:myapp/widgets/get_images.dart';
import 'package:image_viewer/image_viewer.dart';
class SideBar extends StatelessWidget {
const SideBar({super.key, required this.title});
final String title;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(title)),
body: const Center(
child: Text('My Page!'),
),
drawer: Drawer(
child: InkWell(
child: GetImages(),
onTap: () {
//ImageViewer.showImageSlider(images: ["assets/photos/IMG_4100.JPG"]);
// montre la photo et ferme la sidebar
Navigator.pop(context);
},
),
),
);
}
}
Thanks in advance for your help :)
You could try this package that i've used before https://pub.dev/packages/lightbox seems like it does exactly what you are looking for.
Related
I have the following code to build a listview from local JSON file and it works perfectly fine. However, when I try to add a method such as onTap: (){} to the ExpansionTile in the _buildList Widget I got the following error
Error: No named parameter with the name 'onTap'. onTap: (){}, ^^^^^ /C:/src/flutter/packages/flutter/lib/src/material/expansion_tile.dart:51:9: Context: Found this candidate, but the arguments don't match. const ExpansionTile({ ^^^^^^^^^^^^^
The code in Main.dart is
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'datamodel.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future<List<Menu>> ReadJsonData() async {
//read json file
final jsondata = await rootBundle.loadString('assets/data0.json');
//decode json data as list
final list = json.decode(jsondata) as List<dynamic>;
//map json and initialize using Model
return list.map((e) => Menu.fromJson(e)).toList();
}
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home:Scaffold(
appBar: AppBar(
title: const Text('My Title'),
),
body: FutureBuilder(
future: ReadJsonData(),
builder: (context,data){
if(data.hasError){
return Center(child: Text("${data.error}"));
}else if(data.hasData){
var items =data.data as List<Menu>;
return ListView.builder(
itemCount: items.length,
itemBuilder: (BuildContext context, int index) =>
_buildList(items[index]),
);
}else{
return Center(child: CircularProgressIndicator(),);
}
},
)
)
);
}
Widget _buildList(Menu list) {
return ExpansionTile(
leading: Icon(list.icon),
// line causing error
onTap: (){},
title: Text(
list.name!,// I added !
style: TextStyle(fontSize: list.font?.toDouble(), fontWeight: FontWeight.bold),
),
children: list.subMenu!.map(_buildList).toList(),// I added !
);
}
}
So is there any way to add the Method for each Expansion tile?
Thank you in advance!
ExpansionTile does not have an onTap property. This is because it has a default behaviour on tapping, expands or collapses.
If you'd like to execute some specific logic on expanded or collapsed, you can use onExpansionChanged:
return ExpansionTile(
onExpansionChanged: (bool expanded) {
// do what you want
},
);
I am having trouble where a Slidable does not get removed when I pressed delete action as shown in an image below.
The problem is in class NotificationInputPage where onDismissed got triggered, but notificationList.removedAt(index); does not seems to work.
If you spot something isn't right, please let me know. Thank you so much.
return SlidableWidget(child: notification, onDismissed: (context) {
setState(() {
notificationList.removeAt(index);
print('deleted..');
});
});
Here is my code
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_slidable/flutter_slidable.dart';
class SlidableWidget extends StatelessWidget {
final Widget child;
final void Function(BuildContext context) onDismissed;
const SlidableWidget({required this.child, required this.onDismissed , Key? key}) : super(key: key);
#override
Widget build(BuildContext context) => Slidable(
child: child,
endActionPane: ActionPane(motion: ScrollMotion(), children: [
SlidableAction(
flex: 1,
onPressed: onDismissed,
backgroundColor: Colors.red,
foregroundColor: Colors.white,
icon: Icons.delete,
label: 'delete',
),
],
extentRatio: 0.2,),
);
}
import 'package:carwashqueue/constants/constants.dart';
import 'package:carwashqueue/constants/enumerations.dart';
import 'package:carwashqueue/models/carwash_notification.dart';
import 'package:carwashqueue/widget/slidable_widget.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class NotificationInputPage extends StatefulWidget {
const NotificationInputPage({Key? key}) : super(key: key);
#override
_NotificationInputPageState createState() => _NotificationInputPageState();
}
class _NotificationInputPageState extends State<NotificationInputPage> {
DateTime thirtyDaysAgo = DateTime.now().subtract(const Duration(days: 30));
final _auth = FirebaseAuth.instance;
final _fireStore = FirebaseFirestore.instance;
#override
Widget build(BuildContext context) {
Stream<List<CarWashNotification>> readNotification() => _fireStore
.collection('notifications')
.orderBy('notification_date', descending: false)
.where('notification_date',
isGreaterThanOrEqualTo: thirtyDaysAgo)
.snapshots()
.map((snapshot) => snapshot.docs.map((doc) => CarWashNotification.fromJson(doc.data(), doc)).toList());
return Scaffold(
body: StreamBuilder<List<CarWashNotification>>(
stream: readNotification(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('There is an error. Please try again.');
} else if (snapshot.hasData) {
final notifications = snapshot.data!;
List<Widget> notificationList = notifications.map((e) => buildListTile(e)).toList();
// return ListView(children: notificationList,);
return ListView.separated(
itemBuilder: (context, index) {
final notification = notificationList[index];
return SlidableWidget(child: notification, onDismissed: (context) {
setState(() {
notificationList.removeAt(index);
print('deleted..');
});
});
},
separatorBuilder: (context, index) => Divider(),
itemCount: notificationList.length);
} else {
return Center(
child: Text('There is no notification at the moment.'));
}
}),
);
}
Widget buildListTile(CarWashNotification item) {
return ListTile(
leading: FaIcon(
FontAwesomeIcons.bullhorn,
size: 30.0,
color: mainColour1,
),
title: Text(item.title),
subtitle: Text(item.message.length > textLimit
? item.message.substring(0, textLimit) + '...'
: item.message),
onTap: () {
print('onTap');
},
);
}
You should use dissmissible widget for this.
Dissmissible Widget
Dissmissible Widget Swiping
Now I understand why item didn't get removed from the list.
Actually it did get removed but when setState function runs, it reruns the build method so all the items are retrieved from firebase and reassigned to the list. That's why the item looks like it's never been removed from the list.
So What I will need to do is to really delete selected item from firebase or I will need to use a different mechanism.
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
class SearchView extends StatefulWidget {
#override
_SearchViewState createState() => _SearchViewState();
}
class _SearchViewState extends State<SearchView> {
List data = [];
Future<String> getData() async {
http.Response res = await http
.get(Uri.parse("https://gcse.doky.space/api/schedule/buildings"));
this.setState(() {
data = jsonDecode(res.body)["result"];
});
return "success";
}
#override
void initState() {
super.initState();
this.getData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('건물 선택')),
body: new ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, int index) {
return new Card(
child: new Text(data[index]),
);
},
),
);
}
}
I am making lecture room reservation system.
But each listview block is too small so it's hard to click.
How to make text and block larger?
also where should I put onTap to make listview touchable?
Might I suggest you use a ListTile instead of a Text?
ListTile(
onTap: _itemtapped,
title: Text(myText)
)
void _itemtapped() {
// do you thing here
}
Use InkWell widget. It will give you a nice tap effect.
InkWell(
child: Text(data[index]),
onTap: _onTap,
)
And implement on tap:
void _onTap() {}
I am getting my data through Hive to ListView, here is my code where I am showing ListView.
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:secret_keeper/Database/Hive/PasswordModel.dart';
import 'package:secret_keeper/screens/home_screen/passwords/ShowData.dart';
class PasswordsNavigation extends StatefulWidget {
#override
_PasswordsNavigationState createState() => _PasswordsNavigationState();
}
class _PasswordsNavigationState extends State<PasswordsNavigation> {
var passwordBox = Hive.box<PasswordModel>('passwordBox');
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: _buildListView(),
)
],
));
}
Widget _buildListView() {
return WatchBoxBuilder(
box: passwordBox,
builder: (context, box) {
Map<dynamic, dynamic> raw = box.toMap();
List list = raw.values.toList();
return ListView.builder(
shrinkWrap: true,
itemCount: list.length,
itemBuilder: (context, index) {
PasswordModel passwordModel = list[index];
return ListTile(
title: Text(passwordModel.websiteName),
subtitle: Text(passwordModel.websiteAddress),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.delete),
onPressed: (){
passwordBox.deleteAt(index);
},
)
],
),
);
},
);
},
);
}
}
I have created a new .dart file named ShowData.dart When I click on any item then how to open this activity? I don't know how to navigate to new screen when i click on list item also i want data like list index n all with navigator.
You should probably create a new widget for the page, like this:
class DetailsPage extends StatelessWidget {
DetailsPage({Key key, required this.id}) : super(key: key);
final int id;
Widget build(BuildContext context) {
// Show details for the item with the given id.
...
}
}
Note that it also takes an id parameter in the constructor.
Then, in the ListTile's onTap method, you can navigate to the new page, passing along the id:
ListTile(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => DetailsPage(id: /* id of the item at the current index */),
));
},
...
),
I'm working on an app for scanning barcode, and i want to scanning multiple barcodes and still see what i'm scanning at the same time. please there a way this can be achieved in flutter?
This would only be achievable by using an inline QR scan widget.
This is available, but uses embedded native widgets, which is an experimental feature.
Have a look at this library: https://pub.dev/packages/qr_code_scanner
The example included should be able to help you. It divides the screen in 4/5 for the camera widget and 1/5 for the rest. You can change this by changing the flex value in the example below.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
void main() => runApp(MaterialApp(home: QRViewExample()));
class QRViewExample extends StatefulWidget {
const QRViewExample({
Key key,
}) : super(key: key);
#override
State<StatefulWidget> createState() => _QRViewExampleState();
}
class _QRViewExampleState extends State<QRViewExample> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
var qrText = "";
QRViewController controller;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
flex: 4,
),
Expanded(
child: Column(children:
<Widget>[
Text("This is the result of scan: $qrText"),
RaisedButton(
onPressed: (){
if(controller != null){
controller.flipCamera();
}
},
child: Text(
'Flip',
style: TextStyle(fontSize: 20)
),
)
],
),
flex: 1,
)
],
),
);
}
void _onQRViewCreated(QRViewController controller) {
final channel = controller.channel;
controller.init(qrKey);
this.controller = controller;
channel.setMethodCallHandler((MethodCall call) async {
switch (call.method) {
case "onRecognizeQR":
dynamic arguments = call.arguments;
setState(() {
qrText = arguments.toString();
});
}
});
}
}