detail_page.dart 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import 'dart:typed_data';
  2. import 'package:flutter/material.dart';
  3. import 'package:logger/logger.dart';
  4. import 'package:myapp/core/lru_map.dart';
  5. import 'package:myapp/models/photo.dart';
  6. import 'package:photo_view/photo_view.dart';
  7. import 'extents_page_view.dart';
  8. import 'loading_widget.dart';
  9. import 'package:myapp/utils/share_util.dart';
  10. class DetailPage extends StatefulWidget {
  11. final List<Photo> photos;
  12. final int selectedIndex;
  13. DetailPage(this.photos, this.selectedIndex, {Key key}) : super(key: key);
  14. @override
  15. _DetailPageState createState() => _DetailPageState();
  16. }
  17. class _DetailPageState extends State<DetailPage> {
  18. bool _shouldDisableScroll = false;
  19. int _selectedIndex = 0;
  20. final _cachedImages = LRUMap<int, ZoomableImage>(5);
  21. @override
  22. Widget build(BuildContext context) {
  23. _selectedIndex = widget.selectedIndex;
  24. Logger().i("Loading " + widget.photos[_selectedIndex].toString());
  25. var pageController = PageController(initialPage: _selectedIndex);
  26. return Scaffold(
  27. appBar: _buildAppBar(),
  28. body: Center(
  29. child: Container(
  30. child: ExtentsPageView.extents(
  31. itemBuilder: (context, index) {
  32. if (_cachedImages.get(index) != null) {
  33. return _cachedImages.get(index);
  34. }
  35. final image = ZoomableImage(
  36. photo: widget.photos[index],
  37. shouldDisableScroll: (value) {
  38. setState(() {
  39. _shouldDisableScroll = value;
  40. });
  41. },
  42. );
  43. _cachedImages.put(index, image);
  44. return image;
  45. },
  46. onPageChanged: (int index) {
  47. _selectedIndex = index;
  48. },
  49. physics: _shouldDisableScroll
  50. ? NeverScrollableScrollPhysics()
  51. : PageScrollPhysics(),
  52. controller: pageController,
  53. itemCount: widget.photos.length,
  54. ),
  55. ),
  56. ),
  57. );
  58. }
  59. AppBar _buildAppBar() {
  60. return AppBar(
  61. actions: <Widget>[
  62. IconButton(
  63. icon: Icon(Icons.share),
  64. onPressed: () async {
  65. share(widget.photos[_selectedIndex]);
  66. },
  67. )
  68. ],
  69. );
  70. }
  71. }
  72. class ZoomableImage extends StatelessWidget {
  73. final Function(bool) shouldDisableScroll;
  74. const ZoomableImage({
  75. Key key,
  76. @required this.photo,
  77. this.shouldDisableScroll,
  78. }) : super(key: key);
  79. final Photo photo;
  80. @override
  81. Widget build(BuildContext context) {
  82. Logger().i("Building " + photo.toString());
  83. if (ImageLruCache.getData(photo.generatedId) != null) {
  84. return _buildPhotoView(ImageLruCache.getData(photo.generatedId));
  85. }
  86. return FutureBuilder<Uint8List>(
  87. future: photo.getBytes(),
  88. builder: (_, snapshot) {
  89. if (snapshot.hasData) {
  90. return _buildPhotoView(snapshot.data);
  91. } else if (snapshot.hasError) {
  92. return Text(snapshot.error.toString());
  93. } else {
  94. return loadWidget;
  95. }
  96. },
  97. );
  98. }
  99. Widget _buildPhotoView(Uint8List imageData) {
  100. ValueChanged<PhotoViewScaleState> scaleStateChangedCallback = (value) {
  101. if (shouldDisableScroll != null) {
  102. shouldDisableScroll(value != PhotoViewScaleState.initial);
  103. }
  104. };
  105. return PhotoView(
  106. imageProvider: Image.memory(imageData).image,
  107. scaleStateChangedCallback: scaleStateChangedCallback,
  108. minScale: PhotoViewComputedScale.contained,
  109. );
  110. }
  111. }