Flutter中实现图片预览

效果图

   

实现方式 

pubspec.yaml文件中dependencies:下引入photo_view

dependencies:
  flutter:
    sdk: flutter
  photo_view: ^0.14.0

主页代码:

import 'package:flutter/material.dart';
import 'package:flutter_demo/res/listData.dart';
import 'package:flutter_demo/routers/routers.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      //隐藏DEBUG图标
      debugShowCheckedModeBanner: false,
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const Scaffold(
        body: PhotoViewPage(),
      ),
      initialRoute: "/",
      onGenerateRoute: onGenerateRoute,
    );
  }
}

class PhotoViewPage extends StatefulWidget {
  const PhotoViewPage({super.key});

  @override
  State<PhotoViewPage> createState() => _PhotoViewPageState();
}

class _PhotoViewPageState extends State<PhotoViewPage> {
  List<Widget> _list() {
    var list = listData.map((value) {
      return GestureDetector(
        onTap: () {
          //item点击路由跳转传参
          Navigator.pushNamed(
            context,
            "/hero",
            arguments: {
              "imageUrl": value['imageUrl'],
              "initialPage": value['id'],
              "listData": listData,
            },
          );
        },
        child: Container(
          decoration: BoxDecoration(
            border: Border.all(color: Colors.black26),
          ),
          child: Column(
            children: [
              Hero(
                tag: value["imageUrl"],
                child: Image.network(value["imageUrl"]),
              ),
              const SizedBox(height: 10),
              Text(
                value["title"],
                style: const TextStyle(fontSize: 18),
              ),
            ],
          ),
        ),
      );
    });
    return list.toList();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      //GridView网格布局
      child: GridView.count(
        //一行widget数量
        crossAxisCount: 2,
        //水平子Widget之间间距
        crossAxisSpacing: 10,
        //垂直子Widget之间间距
        mainAxisSpacing: 10,
        //外边距
        padding: const EdgeInsets.all(10),
        //数据
        children: _list(),
      ),
    );
  }
}

路由跳转需要加入initialRoute和引入自定义路由配置onGenerateRoute。数据用了自定义listData数据。预览图片跳转到自定义图片预览HeroPage页面。图片显示列表用的是GridView网格布局组件。

路由配置routers.dart代码:

import 'package:flutter/material.dart';
import 'package:flutter_demo/form.dart';
import 'package:flutter_demo/hero.dart';
import 'package:flutter_demo/register2.dart';
import 'package:flutter_demo/search.dart';

//配置路由
Map routes = {
  "/search": (context) => const SearchPage(),
  "/register2": (context) => const Register2(),
  "/form": (context, {arguments}) => FormPage(arguments: arguments),
  "/hero": (context, {arguments}) => HeroPage(arguments: arguments),
};

//配置onGenerateRoute固定写法,这个方法相当于一个中间件,可以做权限判断
var onGenerateRoute = (RouteSettings settings) {
  final String? name = settings.name;
  final Function? pageContentBuilder = routes[name];
  if (pageContentBuilder != null) {
    if (settings.arguments != null) {
      final Route route = MaterialPageRoute(
        builder: (context) =>
            pageContentBuilder(context, arguments: settings.arguments),
      );
      return route;
    } else {
      final Route route = MaterialPageRoute(
        builder: (context) => pageContentBuilder(context),
      );
      return route;
    }
  }
  return null;
};

配置中添加跳转页面HeroPage的配置即可。

自定义数据listData.dart代码:

List listData = [
  {
    "id": 1,
    "title": "图一",
    "author": "程序员",
    "imageUrl": "https://www.itying.com/images/flutter/1.png",
  },
  {
    "id": 2,
    "title": "图二",
    "author": "程序员",
    "imageUrl": "https://www.itying.com/images/flutter/2.png",
  },
  {
    "id": 3,
    "title": "图三",
    "author": "程序员",
    "imageUrl": "https://www.itying.com/images/flutter/3.png",
  },
  {
    "id": 4,
    "title": "图四",
    "author": "程序员",
    "imageUrl": "https://www.itying.com/images/flutter/4.png",
  },
  {
    "id": 5,
    "title": "图五",
    "author": "程序员",
    "imageUrl": "https://www.itying.com/images/flutter/5.png",
  },
  {
    "id": 6,
    "title": "图六",
    "author": "程序员",
    "imageUrl": "https://www.itying.com/images/flutter/6.png",
  },
];

点击item跳转并传参:

Navigator.pushNamed(
  context,
  "/hero",
  arguments: {
    "imageUrl": value['imageUrl'],
    "initialPage": value['id'],
    "listData": listData,
  },
);

自定义图片预览hero.dart页面:

import 'package:flutter/material.dart';
import 'package:photo_view/photo_view_gallery.dart';

///自定义图片预览页面
class HeroPage extends StatefulWidget {
  final Map arguments;

  const HeroPage({super.key, required this.arguments});

  @override
  State<HeroPage> createState() => _HeroPageState();
}

class _HeroPageState extends State<HeroPage> {
  List listData = [];
  late int currentPage;
  late int initialPage = 0;

  @override
  void initState() {
    super.initState();
    listData = widget.arguments["listData"];
    initialPage = widget.arguments["initialPage"] - 1;
    currentPage = widget.arguments["initialPage"];
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        //点击屏幕关闭本页
        Navigator.pop(context);
      },
      child: Hero(
        tag: widget.arguments["imageUrl"],
        child: Stack(
          children: [
            Scaffold(
              backgroundColor: Colors.black,
              body: Center(
                //多图片预览
                child: PhotoViewGallery.builder(
                  itemCount: listData.length,
                  pageController: PageController(initialPage: initialPage),
                  onPageChanged: (index) {
                    setState(() {
                      currentPage = index + 1;
                    });
                  },
                  builder: (context, index) {
                    return PhotoViewGalleryPageOptions(
                      imageProvider: NetworkImage(listData[index]["imageUrl"]),
                    );
                  },
                ),
              ),
            ),
            //图片张数指示器
            Positioned(
              left: 0,
              right: 0,
              bottom: 20,
              child: Container(
                alignment: Alignment.center,
                child: Text(
                  "$currentPage/${listData.length}",
                  style: const TextStyle(
                    color: Colors.white,
                    fontSize: 16,
                    decoration: TextDecoration.none,
                  ),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

单击页面关闭图片预览用Navigator.pop。多图预览用PhotoViewGallery。单图预览用PhotoView。

photo_view三方库介绍及使用

库特色:单图预览,多图预览,双击放大缩小,双指放大缩小。

相关推荐

  1. vue实现图片

    2023-12-20 12:34:03       5 阅读
  2. uniappbase64图片

    2023-12-20 12:34:03       16 阅读
  3. vue项目实现doc/excel/pdf/txt/图片等文件的

    2023-12-20 12:34:03       33 阅读
  4. 小程序使用wx.previewImage实现图片与缩放

    2023-12-20 12:34:03       28 阅读
  5. 在Vue使用v-viewer插件实现点击图片

    2023-12-20 12:34:03       11 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-20 12:34:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-20 12:34:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-20 12:34:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-20 12:34:03       18 阅读

热门阅读

  1. 史上最牛软件开发工位

    2023-12-20 12:34:03       52 阅读
  2. 【已解决】MFC打开目录并保存到编辑框里

    2023-12-20 12:34:03       81 阅读
  3. SpringCloudGateway 3.1.4版本 Netty内存泄漏问题解决

    2023-12-20 12:34:03       42 阅读
  4. DataX迁移MongoDB

    2023-12-20 12:34:03       49 阅读
  5. mongoDB

    mongoDB

    2023-12-20 12:34:03      47 阅读
  6. 如何用python开发打包APP

    2023-12-20 12:34:03       51 阅读
  7. element-ui 抽屉里面嵌套弹窗

    2023-12-20 12:34:03       43 阅读