import 'dart:typed_data'; import 'package:compdfkit_flutter/core/document/cpdf_document.dart'; import 'package:flutter/material.dart'; /// Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved. /// /// THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW /// AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT. /// UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES. /// This notice may not be removed from this file. class CPDFThumbnailPage extends StatefulWidget { final isDark; final CPDFDocument document; final int currentPageIndex; const CPDFThumbnailPage( {Key? key,this.isDark = false, required this.document, required this.currentPageIndex}) : super(key: key); @override State createState() => _CPDFThumbnailPageState(); } class _CPDFThumbnailPageState extends State with AutomaticKeepAliveClientMixin{ final ScrollController _scrollController = ScrollController(); final GlobalKey globalKey = GlobalKey(); @override void initState() { super.initState(); } @override void dispose() { super.dispose(); _scrollController.dispose(); } @override Widget build(BuildContext context) { return FutureBuilder( initialData: 0, future: widget.document.getPageCount(), builder: (context, snapshot) { final size = MediaQuery.of(context).size; final widgetWidth = size.width - 16; return OrientationBuilder(builder: (context, orientation) { int crossAxisCount = orientation == Orientation.portrait ? 3 : 6; return GridView.builder( padding: const EdgeInsets.symmetric(horizontal: 8), key: globalKey, controller: _scrollController, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: crossAxisCount, mainAxisSpacing: 8, crossAxisSpacing: 8, childAspectRatio: 0.62), itemCount: snapshot.data ?? 0, itemBuilder: (context, index) => Padding( padding: const EdgeInsets.only(top: 8), child: _thumbnailItem( index, ((widgetWidth - 22) / crossAxisCount)), )); }); }); } Widget _thumbnailItem(int index, double itemWidth) { double aspectRatio = 0.30; double itemHeight = itemWidth + (itemWidth * aspectRatio); bool selected = widget.currentPageIndex == index; return FutureBuilder( future: widget.document.getPageSize(index), builder: (context, snap) { if (snap.connectionState == ConnectionState.done && snap.hasData) { var size = snap.data!; var imageWidth = itemWidth; var imageHeight = (imageWidth / size[0]) * size[1]; if (imageHeight > itemHeight) { imageHeight = itemHeight; imageWidth = (imageHeight / size[1]) * size[0]; } return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ InkWell( child: FutureBuilder( future: widget.document.renderPageAtIndex( index, imageWidth.toInt(), imageHeight.toInt()), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done && !snapshot.hasError) { Uint8List? imageData = snapshot.data; if (imageData != null) { return _imageItem( Image.memory( imageData, ), selected, imageWidth, imageHeight); } else { return const Padding(padding: EdgeInsets.zero); } } else { return const Padding(padding: EdgeInsets.zero); } }), onTap: () { Navigator.pop(context, index); }, ), _pageIndicator(index, selected) ], ); } else { return const Padding(padding: EdgeInsets.zero); } }); } Widget _imageItem( Widget child, bool selected, double imageWidth, double imageHeight) { return Container( width: imageWidth, height: imageHeight, decoration: BoxDecoration( border: Border.all( color: selected ? Theme.of(context).colorScheme.primaryContainer : const Color(0xFFDDE9FF), width: 2), borderRadius: const BorderRadius.all(Radius.circular(2))), child: child, ); } Widget _pageIndicator(int index, bool selected) { return Container( margin: const EdgeInsets.only(top: 8), decoration: BoxDecoration( color: selected ? Theme.of(context).colorScheme.primaryContainer : Colors.transparent, borderRadius: const BorderRadius.all(Radius.circular(2))), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 2), child: Text( (index + 1).toString(), style: TextStyle( fontSize: 12, color: selected || widget.isDark ? Colors.white : Colors.black), ), )); } // Function to scroll to a specific item in the GridView void scrollToItem(int index) { } @override bool get wantKeepAlive => true; }