|
@@ -1,4 +1,6 @@
|
|
|
-import 'package:flutter/cupertino.dart';
|
|
|
+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.
|
|
@@ -8,12 +10,163 @@ import 'package:flutter/material.dart';
|
|
|
/// UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
|
|
|
/// This notice may not be removed from this file.
|
|
|
|
|
|
-class CPDFThumbnailPage extends StatelessWidget {
|
|
|
+class CPDFThumbnailPage extends StatefulWidget {
|
|
|
+ final CPDFDocument document;
|
|
|
+ final int currentPageIndex;
|
|
|
+
|
|
|
+ const CPDFThumbnailPage(
|
|
|
+ {Key? key, required this.document, required this.currentPageIndex})
|
|
|
+ : super(key: key);
|
|
|
+
|
|
|
+ @override
|
|
|
+ State<CPDFThumbnailPage> createState() => _CPDFThumbnailPageState();
|
|
|
+}
|
|
|
+
|
|
|
+class _CPDFThumbnailPageState extends State<CPDFThumbnailPage> {
|
|
|
+ final ScrollController _scrollController = ScrollController();
|
|
|
+
|
|
|
+ final GlobalKey globalKey = GlobalKey();
|
|
|
+
|
|
|
+ @override
|
|
|
+ void initState() {
|
|
|
+ super.initState();
|
|
|
+ // WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
|
+ // scrollToItem(widget.currentPageIndex);
|
|
|
+ // });
|
|
|
+ }
|
|
|
|
|
|
- const CPDFThumbnailPage({Key? key}) : super(key: key);
|
|
|
+ @override
|
|
|
+ void dispose() {
|
|
|
+ super.dispose();
|
|
|
+ _scrollController.dispose();
|
|
|
+ }
|
|
|
|
|
|
@override
|
|
|
Widget build(BuildContext context) {
|
|
|
- return Placeholder();
|
|
|
+ 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 ? Colors.white : Colors.black),
|
|
|
+ ),
|
|
|
+ ));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Function to scroll to a specific item in the GridView
|
|
|
+ void scrollToItem(int index) {
|
|
|
+ // _scrollController.animateTo(
|
|
|
+ // offset,
|
|
|
+ // duration: const Duration(milliseconds: 500),
|
|
|
+ // curve: Curves.fastOutSlowIn,
|
|
|
+ // );
|
|
|
}
|
|
|
}
|