mirror of
https://gitlab.com/mysocialportal/relatica
synced 2024-10-18 13:33:32 +00:00
Implementation of image carousel with carousel_slider library
This commit is contained in:
parent
8fad35ed33
commit
b23f45a180
3 changed files with 52 additions and 88 deletions
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:carousel_slider/carousel_slider.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
|
import 'package:flutter_file_dialog/flutter_file_dialog.dart';
|
||||||
|
@ -19,7 +20,7 @@ class ImageViewerScreen extends StatefulWidget {
|
||||||
const ImageViewerScreen({
|
const ImageViewerScreen({
|
||||||
super.key,
|
super.key,
|
||||||
required this.attachments,
|
required this.attachments,
|
||||||
int this.initialIndex = 0,
|
this.initialIndex = 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -27,11 +28,12 @@ class ImageViewerScreen extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ImageViewerScreenState extends State<ImageViewerScreen> {
|
class _ImageViewerScreenState extends State<ImageViewerScreen> {
|
||||||
var index = 0;
|
MediaAttachment? currentAttachment;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
index = widget.initialIndex;
|
super.initState();
|
||||||
|
currentAttachment = widget.attachments[widget.initialIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveImage(
|
Future<void> saveImage(
|
||||||
|
@ -71,109 +73,62 @@ class _ImageViewerScreenState extends State<ImageViewerScreen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
print('Index: $index');
|
final width = MediaQuery.of(context).size.width;
|
||||||
final attachment = widget.attachments[index];
|
|
||||||
final height = MediaQuery.of(context).size.height;
|
final height = MediaQuery.of(context).size.height;
|
||||||
|
final carouselHeight =
|
||||||
|
widget.attachments.length == 1 ? height * 0.9 : height * 0.8;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () => saveImage(context, attachment),
|
onPressed: currentAttachment == null
|
||||||
|
? null
|
||||||
|
: () => saveImage(context, currentAttachment!),
|
||||||
icon: const Icon(Icons.download))
|
icon: const Icon(Icons.download))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Stack(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
CarouselSlider.builder(
|
||||||
onHorizontalDragEnd: (details) {
|
itemCount: widget.attachments.length,
|
||||||
final velocity = details.primaryVelocity ?? 0.0;
|
itemBuilder: (context, index, realIndex) {
|
||||||
print('Velocity: $velocity');
|
return SizedBox(
|
||||||
if (velocity > 0 && index > 0) {
|
width: width,
|
||||||
setState(() {
|
height: carouselHeight,
|
||||||
index--;
|
child: InteractiveViewer(
|
||||||
});
|
maxScale: 10.0,
|
||||||
}
|
scaleFactor: 400,
|
||||||
|
child: CachedNetworkImage(
|
||||||
if (velocity < 0 && index < widget.attachments.length - 1) {
|
imageUrl: widget.attachments[index].uri.toString()),
|
||||||
setState(() {
|
),
|
||||||
index++;
|
);
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
child: buildCoreViewer(attachment),
|
options: CarouselOptions(
|
||||||
|
height: carouselHeight,
|
||||||
|
initialPage: widget.initialIndex,
|
||||||
|
enableInfiniteScroll: false,
|
||||||
|
enlargeCenterPage: true,
|
||||||
|
viewportFraction: 0.95,
|
||||||
|
onPageChanged: (index, reason) {
|
||||||
|
setState(() {
|
||||||
|
currentAttachment = widget.attachments[index];
|
||||||
|
});
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
if (index > 0)
|
if (currentAttachment != null) buildTextArea(currentAttachment!),
|
||||||
Positioned(
|
|
||||||
top: height / 2,
|
|
||||||
left: 0.0,
|
|
||||||
child: buildButton(
|
|
||||||
Icon(Icons.keyboard_arrow_left),
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
index--;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (index < widget.attachments.length - 1)
|
|
||||||
Positioned(
|
|
||||||
top: height / 2,
|
|
||||||
right: 0.0,
|
|
||||||
child: buildButton(
|
|
||||||
Icon(Icons.keyboard_arrow_right),
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
index++;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildCoreViewer(MediaAttachment attachment) {
|
Widget buildTextArea(MediaAttachment attachment) {
|
||||||
final width = MediaQuery.of(context).size.width;
|
return Expanded(
|
||||||
final height = MediaQuery.of(context).size.height;
|
child: SingleChildScrollView(
|
||||||
return Column(
|
child: Padding(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
padding: const EdgeInsets.all(8.0),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Text(attachment.description),
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: width,
|
|
||||||
height: 0.8 * height,
|
|
||||||
child: InteractiveViewer(
|
|
||||||
maxScale: 10.0,
|
|
||||||
scaleFactor: 400,
|
|
||||||
child: CachedNetworkImage(imageUrl: attachment.uri.toString()),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Text(attachment.description),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget buildButton(Icon icon, {required Function() onPressed}) {
|
|
||||||
return Center(
|
|
||||||
child: Ink(
|
|
||||||
decoration: ShapeDecoration(
|
|
||||||
color: Theme.of(context).focusColor,
|
|
||||||
shape: CircleBorder(),
|
|
||||||
),
|
|
||||||
child: IconButton(
|
|
||||||
icon: icon,
|
|
||||||
color: Colors.white,
|
|
||||||
onPressed: onPressed,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -137,6 +137,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.2"
|
version: "1.0.2"
|
||||||
|
carousel_slider:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: carousel_slider
|
||||||
|
sha256: "9c695cc963bf1d04a47bd6021f68befce8970bcd61d24938e1fb0918cf5d9c42"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "4.2.1"
|
||||||
characters:
|
characters:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
@ -42,6 +42,7 @@ dependencies:
|
||||||
objectbox: ^1.7.1
|
objectbox: ^1.7.1
|
||||||
objectbox_flutter_libs: ^1.7.1
|
objectbox_flutter_libs: ^1.7.1
|
||||||
path_provider: ^2.0.11
|
path_provider: ^2.0.11
|
||||||
|
carousel_slider: ^4.2.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
Loading…
Reference in a new issue