Flutter 3D画廊插件gallery_3d的使用

Flutter 3D画廊插件gallery_3d的使用

模仿哔哩哔哩漫画

示例代码

import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:gallery_3d/gallery_3d.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
  var imageUrlList = [
    "https://i0.hdslb.com/bfs/manga-static/42b2143b5694835ae35763bea634cdfc36392801.jpg@300w.jpg",
    "https://i0.hdslb.com/bfs/manga-static/87e22d652eb4c456fe251e15b57bbb25da39925a.jpg@300w.jpg",
    "https://i0.hdslb.com/bfs/manga-static/3f01609c36d4816eb227c95ac31471710fa706e6.jpg@300w.jpg",
    "https://i0.hdslb.com/bfs/manga-static/6b5ab1a7cb883504db182ee46381835e70d6d460.jpg@300w.jpg",
    "https://i0.hdslb.com/bfs/manga-static/5482454680757477d728dae82f80a280a9cc97a2.jpg@300w.jpg",
    // "https://i0.hdslb.com/bfs/manga-static/5482454680757477d728dae82f80a280a9cc97a2.jpg@300w.jpg",
    // "https://i0.hdslb.com/bfs/manga-static/5482454680757477d728dae82f80a280a9cc97a2.jpg@300w.jpg",
    // "https://i0.hdslb.com/bfs/manga-static/5482454680757477d728dae82f80a280a9cc97a2.jpg@300w.jpg",
    // "https://i0.hdslb.com/bfs/manga-static/5482454680757477d728dae82f80a280a9cc97a2.jpg@300w.jpg",
    // "https://i0.hdslb.com/bfs/manga-static/5482454680757477d728dae82f80a280a9cc97a2.jpg@300w.jpg",
    // "https://i0.hdslb.com/bfs/manga-static/5482454680757477d728dae82f80a280a9cc97a2.jpg@300w.jpg",
    // "https://i0.hdslb.com/bfs/manga-static/5482454680757477d728dae82f80a280a9cc97a2.jpg@300w.jpg",
  ];

  int currentIndex = 0;

  Widget buildGallery3D() {
    return Gallery3D(
        autoLoop: false,
        itemCount: 3,
        width: MediaQuery.of(context).size.width,
        height: 300,
        isClip: false,

        // ellipseHeight: 80,
        itemConfig: GalleryItemConfig(
          width: 220,
          height: 300,
          radius: 10,
          isShowTransformMask: false,
          // shadows: [
          //   BoxShadow(
          //       color: Color(0x90000000), offset: Offset(2, 0), blurRadius: 5)
          // ]
        ),
        currentIndex: currentIndex,
        onItemChanged: (index) {
          setState(() {
            this.currentIndex = index;
          });
        },
        onActivePage: (index) {
          print('onActivePage $index');
        },
        onClickItem: (index) => print("currentIndex:$index"),
        itemBuilder: (context, index) {
          return Image.network(
            imageUrlList[index],
            fit: BoxFit.fill,
          );
        });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: [
            Stack(
              children: [
                BackgrounBlurView(
                  imageUrl: imageUrlList[currentIndex],
                ),
                Container(
                  padding: EdgeInsets.only(top: 40),
                  child: buildGallery3D(),
                  margin: EdgeInsets.fromLTRB(0, 20, 0, 20),
                ),
              ],
            )
          ],
        ),
      ),
    );
  }
}

class BackgrounBlurView extends StatelessWidget {
  final String imageUrl;
  BackgrounBlurView({Key? key, required this.imageUrl}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(children: [
      Container(
        height: 200,
        width: MediaQuery.of(context).size.width,
        child: Image.network(
          imageUrl,
          fit: BoxFit.cover,
        ),
      ),
      BackdropFilter(
          filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
          child: Container(
            color: Colors.black.withOpacity(0.1),
            height: 200,
            width: MediaQuery.of(context).size.width,
          ))
    ]);
  }
}

完整示例代码

上述代码展示了一个完整的Flutter应用,该应用使用了gallery_3d插件来创建一个3D画廊。以下是代码的详细解释:

  1. 导入必要的库

    import 'dart:ui';
    import 'package:flutter/material.dart';
    import 'package:gallery_3d/gallery_3d.dart';
    
  2. 定义主应用类

    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }
    
  3. 定义主页类

    class MyHomePage extends StatefulWidget {
      MyHomePage({Key? key, required this.title}) : super(key: key);
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
  4. 定义主页状态类

    class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
      var imageUrlList = [
        "https://i0.hdslb.com/bfs/manga-static/42b2143b5694835ae35763bea634cdfc36392801.jpg@300w.jpg",
        "https://i0.hdslb.com/bfs/manga-static/87e22d652eb4c456fe251e15b57bbb25da39925a.jpg@300w.jpg",
        "https://i0.hdslb.com/bfs/manga-static/3f01609c36d4816eb227c95ac31471710fa706e6.jpg@300w.jpg",
        "https://i0.hdslb.com/bfs/manga-static/6b5ab1a7cb883504db182ee46381835e70d6d460.jpg@300w.jpg",
        "https://i0.hdslb.com/bfs/manga-static/5482454680757477d728dae82f80a280a9cc97a2.jpg@300w.jpg",
      ];
      int currentIndex = 0;
    
  5. 构建3D画廊

    Widget buildGallery3D() {
      return Gallery3D(
          autoLoop: false,
          itemCount: 3,
          width: MediaQuery.of(context).size.width,
          height: 300,
          isClip: false,
          itemConfig: GalleryItemConfig(
            width: 220,
            height: 300,
            radius: 10,
            isShowTransformMask: false,
          ),
          currentIndex: currentIndex,
          onItemChanged: (index) {
            setState(() {
              this.currentIndex = index;
            });
          },
          onActivePage: (index) {
            print('onActivePage $index');
          },
          onClickItem: (index) => print("currentIndex:$index"),
          itemBuilder: (context, index) {
            return Image.network(
              imageUrlList[index],
              fit: BoxFit.fill,
            );
          });
    }
    
  6. 构建页面布局

    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: SingleChildScrollView(
          child: Column(
            children: [
              Stack(
                children: [
                  BackgrounBlurView(
                    imageUrl: imageUrlList[currentIndex],
                  ),
                  Container(
                    padding: EdgeInsets.only(top: 40),
                    child: buildGallery3D(),
                    margin: EdgeInsets.fromLTRB(0, 20, 0, 20),
                  ),
                ],
              )
            ],
          ),
        ),
      );
    }
    
  7. 背景模糊视图类

    class BackgrounBlurView extends StatelessWidget {
      final String imageUrl;
      BackgrounBlurView({Key? key, required this.imageUrl}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Stack(children: [
          Container(
            height: 200,
            width: MediaQuery.of(context).size.width,
            child: Image.network(
              imageUrl,
              fit: BoxFit.cover,
            ),
          ),
          BackdropFilter(
              filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
              child: Container(
                color: Colors.black.withOpacity(0.1),
                height: 200,
                width: MediaQuery.of(context).size.width,
              ))
        ]);
      }
    }
    

更多关于Flutter 3D画廊插件gallery_3d的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter 3D画廊插件gallery_3d的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用gallery_3d插件来创建一个3D画廊的示例代码。gallery_3d插件允许你以3D方式展示图片集合。首先,确保你已经在pubspec.yaml文件中添加了该插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  gallery_3d: ^x.y.z  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来是一个完整的示例代码,展示如何使用gallery_3d插件:

import 'package:flutter/material.dart';
import 'package:gallery_3d/gallery_3d.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '3D Gallery Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Gallery3DScreen(),
    );
  }
}

class Gallery3DScreen extends StatefulWidget {
  @override
  _Gallery3DScreenState createState() => _Gallery3DScreenState();
}

class _Gallery3DScreenState extends State<Gallery3DScreen> {
  final List<String> imageUrls = [
    'https://example.com/image1.jpg',
    'https://example.com/image2.jpg',
    'https://example.com/image3.jpg',
    // 添加更多图片URL
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('3D Gallery'),
      ),
      body: Center(
        child: Gallery3D(
          images: imageUrls.map((url) => NetworkImage(url)).toList(),
          imageCount: imageUrls.length,
          pageController: PageController(initialPage: 0),
          onPageChanged: (index) {
            print('Current image index: $index');
          },
          onScaleStart: (details) {
            print('Scale start: ${details.localPosition}');
          },
          onScaleUpdate: (details) {
            print('Scale update: ${details.scale}');
          },
          onScaleEnd: (details) {
            print('Scale end: ${details.velocity}');
          },
          // 自定义选项
          crossAxisCount: 2, // 每行显示的图片数量
          scaleFactor: 0.8,  // 图片缩放比例
          space: 10.0,       // 图片之间的间距
          animationDuration: Duration(milliseconds: 500), // 动画持续时间
        ),
      ),
    );
  }
}

在这个示例中:

  1. Gallery3DScreen是我们的主屏幕,它包含了3D画廊。
  2. imageUrls列表包含了图片的URL,你可以根据需要添加更多的图片URL。
  3. Gallery3D组件接受多个参数:
    • images:图片列表,这里我们使用NetworkImage从URL加载图片。
    • imageCount:图片总数。
    • pageController:用于控制页面切换的PageController
    • onPageChanged:页面改变时的回调。
    • onScaleStartonScaleUpdateonScaleEnd:用于处理缩放事件的回调。
    • 其他自定义选项如crossAxisCountscaleFactorspaceanimationDuration允许你调整画廊的布局和动画效果。

确保替换imageUrls中的URL为有效的图片URL。运行这个Flutter应用,你应该会看到一个3D画廊,可以通过滑动和缩放来浏览图片。

回到顶部