import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:logging/logging.dart'; import 'package:photos/models/file.dart'; import 'package:photos/ui/huge_listview/place_holder_widget.dart'; import 'package:photos/ui/thumbnail_widget.dart'; import 'package:photos/utils/date_time_util.dart'; import 'package:visibility_detector/visibility_detector.dart'; class LazyLoadingGallery extends StatelessWidget { static const kSubGalleryItemLimit = 80; static final _logger = Logger("LazyLoadingDayGallery"); final files; final selectedFiles; final tag; LazyLoadingGallery(this.files, this.selectedFiles, this.tag, {Key key}) : super(key: key); @override Widget build(BuildContext context) { return Column( children: [ getDayWidget(files[0].creationTime), _getGallery(files), ], ); } Widget _getGallery(List files) { List childGalleries = []; for (int index = 0; index < files.length; index += kSubGalleryItemLimit) { childGalleries.add(LazyLoadingGridView( tag, files.sublist(index, min(index + kSubGalleryItemLimit, files.length)), selectedFiles, )); } return Padding( padding: const EdgeInsets.only(bottom: 12), child: Column( children: childGalleries, ), ); } } class LazyLoadingGridView extends StatefulWidget { final tag; final files; final selectedFiles; LazyLoadingGridView(this.tag, this.files, this.selectedFiles, {Key key}) : super(key: key); @override _LazyLoadingGridViewState createState() => _LazyLoadingGridViewState(); } class _LazyLoadingGridViewState extends State { bool _isVisible = false; @override Widget build(BuildContext context) { if (!_isVisible) { return VisibilityDetector( key: Key(widget.tag + widget.files[0].creationTime.toString()), onVisibilityChanged: (visibility) { if (visibility.visibleFraction > 0 && !_isVisible) { setState(() { _isVisible = true; }); } }, child: PlaceHolderWidget(widget.files.length), ); } else { return GridView.builder( shrinkWrap: true, physics: NeverScrollableScrollPhysics(), // to disable GridView's scrolling itemBuilder: (context, index) { return _buildFile(context, widget.files[index]); }, itemCount: widget.files.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 4, ), ); } } Widget _buildFile(BuildContext context, File file) { return GestureDetector( onTap: () { if (widget.selectedFiles.files.isNotEmpty) { _selectFile(file); } else { _routeToDetailPage(file, context); } }, onLongPress: () { HapticFeedback.lightImpact(); _selectFile(file); }, child: Container( margin: const EdgeInsets.all(2.0), decoration: BoxDecoration( border: widget.selectedFiles.files.contains(file) ? Border.all( width: 4.0, color: Theme.of(context).accentColor, ) : null, ), child: Hero( tag: widget.tag + file.tag(), child: ThumbnailWidget(file), ), ), ); } void _selectFile(File file) { widget.selectedFiles.toggleSelection(file); } void _routeToDetailPage(File file, BuildContext context) { // TODO // final page = DetailPage( // _files, // _files.indexOf(file), // widget.tagPrefix, // ); // Navigator.of(context).push( // MaterialPageRoute( // builder: (BuildContext context) { // return page; // }, // ), // ); } }