如何在Flutter中创建图像轮播?分步指南

2021年11月30日02:46:08 发表评论 984 次浏览
如何在Flutter中创建图像轮播?分步指南

从社交媒体应用程序到电子商务应用程序,大多数现代应用程序都有某种图像轮播来展示产品、图像或广告。

由于 flutter 提供的内置小部件,从头开始实现图像轮播并不像你想象的那么难。

如何在Flutter中创建图像轮播?在本文中,你将学习如何从头开始创建图像轮播并根据需要进行自定义。最后,你将学习如何使用carousel_slider插件以更少的代码创建图像轮播。

这些是我们的Flutter图像轮播创建教程将要讨论的主题。

  • Flutter创建图像轮播实例
  • 图像轮播的小部件结构
  • 使用 PageView 小部件创建轮播
  • 控制初始页面
  • 添加位置指示器
  • 为滑动图像添加动画
  • 如何使用 carousel_slider 插件

图像轮播的小部件结构

在我们进入编码部分之前,让我们了解我们需要拥有的小部件结构。

如何在Flutter中创建图像轮播?分步指南

页面视图小部件需要在应用程序中实现图像滑动功能和图像视图以显示实际图像。除此之外,你需要一个容器小部件来在滑块底部实现页面指示器。

使用 PageView 小部件创建轮播

首先,让我们创建一个名为 Carousel 的有状态小部件。这是我们将用来实现轮播的小部件。

Flutter创建图像轮播实例:首先,让我们创建一个包含图像 URL 的列表:

List<String> images = [
    "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQTIZccfNPnqalhrWev-Xo7uBhkor57_rKbkw&usqp=CAU",
    "https://wallpaperaccess.com/full/2637581.jpg"
  ];

现在你可以使用 PageView 小部件构建器方法来创建轮播页面:

         PageView.builder(
            itemCount: 2,
            pageSnapping: true,
            itemBuilder: (context,pagePosition){
              return Container(
                margin: EdgeInsets.all(10),
                child: Image.network());
            })

itemCount代表页数,它会决定itemBuilder需要执行多少次。因此,你可以通过访问它的索引来设置每个图像 URL。

PageView.builder(
            itemCount: 2,
            pageSnapping: true,
            itemBuilder: (context,pagePosition){
            return Container(
              margin: EdgeInsets.all(10),
              child: Image.network(images[pagePosition]));
          })

现在你可以在屏幕上看到这些图像,并且可以滑动这些图像。

如何在Flutter中创建图像轮播?分步指南

如果你像这样显示图像,用户将不知道是否有更多图像。因此,在显示中间图像的同时显示左右图像的一部分将改善图像轮播的用户体验。

如何在Flutter中创建图像轮播?首先,你应该创建PageController并将其设置为我们的 PageView 小部件。此外,我添加了第三张图像并更改了itemCount从图像数组本身的长度获取计数。然后你可以设置该viewportFraction属性PageController以显示其他图像的分数:

late PageController _pageController;
  List<String> images = [
    "https://images.wallpapersden.com/image/download/purple-sunrise-4k-vaporwave_bGplZmiUmZqaraWkpJRmbmdlrWZlbWU.jpg",
    "https://wallpaperaccess.com/full/2637581.jpg",
    "https://uhdwallpapers.org/uploads/converted/20/01/14/the-mandalorian-5k-1920x1080_477555-mm-90.jpg"
  ];

  @override
  void initState() {
    super.initState();
    _pageController = PageController(viewportFraction: 0.8);
  }

@override
  Widget build(BuildContext context) {
    return PageView.builder(
        itemCount: images.length,
        pageSnapping: true,
        controller: _pageController,
        onPageChanged: (page) {
          setState(() {
            activePage = page;
          });
        },
        itemBuilder: (context, pagePosition) {
          return Container(
            margin: EdgeInsets.all(10),
            child: Image.network(images[pagePosition]),
          );
        });
  }
如何在Flutter中创建图像轮播?分步指南

尽管图像显示在 PageView 的中间,但它实际上占用了整个屏幕空间。如果你将fit类型更改为cover,你可以看到它占据了整个屏幕。

如何在Flutter中创建图像轮播?分步指南

要控制它,你可以将小部件包装在小SizedBox部件中:

SizedBox(
        height: 200,
        width: MediaQuery.of(context).size.width,
        child:   PageView.builder(
                itemCount: images.length,
                pageSnapping: true,
                controller: _pageController,
                onPageChanged: (page) {
                  setState(() {
                    activePage = page;
                  });
                },
                itemBuilder: (context, pagePosition) {
                  return Container(
                    margin: EdgeInsets.all(10),
                    child: Image.network(images[pagePosition],fit: BoxFit.cover,),
                  );
                }),
      )
如何在Flutter中创建图像轮播?分步指南

Flutter图像轮播创建教程:控制初始页面

轮播在第一次加载时将第一张图片加载为默认页面。但是如果你需要更改初始图像以从不同的页面开始,你可以initialPage 在 PageController 中提供该属性。它接受索引作为一个位置:

_pageController = PageController(viewportFraction: 0.8,initialPage: 1);

添加位置指示器

如何在Flutter中创建图像轮播?首先,将PageView小部件移动到小部件SizedBox内部Column

Column(
      children: [
        SizedBox(
          width: MediaQuery.of(context).size.width,
          height: 200,
          child: PageView.builder(
              itemCount: images.length,
              pageSnapping: true,
              controller: _pageController,
              onPageChanged: (page) {
                setState(() {
                  activePage = page;
                });
              },
              itemBuilder: (context, pagePosition) {
                return Container(
                  margin: EdgeInsets.all(10),
                  child: Image.network(images[pagePosition]),
                );
              }),
        ),
      ],
    )

然后你可以创建一个方法来返回指标列表,你应该根据当前活动位置更改指标的颜色。因此,让我们创建一个接受currentIndex 和imagesLength作为参数的方法。通过检查索引,你可以更改活动位置指示器的颜色,如下所示:

List<Widget> indicators(imagesLength,currentIndex) {
  return List<Widget>.generate(imagesLength, (index) {
    return Container(
      margin: EdgeInsets.all(3),
      width: 10,
      height: 10,
      decoration: BoxDecoration(
          color: currentIndex == index ? Colors.black : Colors.black26,
          shape: BoxShape.circle),
    );
  });
}

当用户滑动图像时,应该有一种方法可以获取当前活动位置。该onPageChanged方法适用于:

int activePage = 1;

  PageView.builder(
              itemCount: images.length,
              pageSnapping: true,
              controller: _pageController,
              onPageChanged: (page) {
                setState(() {
                  activePage = page;
                });
              })

现在你可以将activePage值传递给我们创建的方法。在小部件内创建一个 Row 小Column部件作为第二个孩子。然后,你可以将方法的返回指示符indicators作为子项分配给Row小部件:

   Row(
         mainAxisAlignment: MainAxisAlignment.center,
         children: indicators(images.length,activePage))
如何在Flutter中创建图像轮播?分步指南

Flutter创建图像轮播实例:为滑动图像添加动画

尽管我们的轮播效果很好,但在图像之间滑动时有动画效果还是不错的。让我们看看如何在图像变化时添加动画。

有多种方法可用于应用放大动画。但是在这里我们将使用内置的 FlutterAnimationContainer 小部件来创建这个动画,因为它开箱即用,AnimationContainer提供了我们需要的所有功能。

在当前滑块图像中,所有容器的大小都相同。通过更改图像的边距,你可以添加放大效果。

AnimationContainer包含样特性durationcurvemargin,和decoration你可以用它来实现这个动画。

让我们创建一个单独的滑块方法,并将图像列表、当前页面位置以及当前图像是否处于活动状态作为参数。可以itemBuilder通过检查页面位置和当前活动页面位置来检查此活动状态。

curve属性可用于指定需要如何放置动画曲线。请查看这篇Flutter 文章以了解可用值及其行为:

itemBuilder: (context, pagePosition) {
      //checking active position
      bool active = pagePosition == activePage;
      return slider(images,pagePosition,active);
}
AnimatedContainer slider(images,pagePosition,active){
  double margin = active ? 10 : 20;
  return AnimatedContainer(
    duration: Duration(milliseconds: 500),
    curve: Curves.easeInOutCubic, 
    margin: EdgeInsets.all(margin),
    decoration: BoxDecoration(
      image: DecorationImage(image: NetworkImage(images[pagePosition]))
    ),
    );
}
如何在Flutter中创建图像轮播?分步指南

如何使用 carousel_slider 插件

Flutter图像轮播创建教程:尽管从头开始实施轮播很容易,但根据你的项目和时间表,添加不同的功能可能很困难。因此,可以在你的项目中使用像 carousel_slider 这样的插件来创建一个更轻松的轮播。

首先,将插件添加到pubspec.yaml

dependencies:
  carousel_slider: ^4.0.0

接下来,导入你要使用滑块的库:

import 'package:carousel_slider/carousel_slider.dart';

CarouselSlider班主要接受两个参数:optionsitems。对于选项,你可以配置滑块所需的行为。我已经提到了CarouselOptions类中可用的一些属性。

属性描述
height设置滑块高度
enableInfiniteScroll设置页面是否需要无限滚动。默认情况下,此选项处于打开状态,你可以根据需要将其关闭
autoplay滑块将自动更改图像。默认时间为 4 秒
autoPlayInterval更改自动播放间隔,默认4秒
onPageChanged页面更改时的回调触发器。它包含两个参数:当前位置和原因。该reason值可以是定时、手动或控制器
enlargeCenterPage放大中间页面,就像我们之前实现的那样

对于项目,你可以使用该map方法创建图像列表:

SliderPlugin(images) {
  return CarouselSlider(
    options: CarouselOptions(
      height: 200.0,
      enlargeCenterPage: true,
      onPageChanged: (position,reason){
        print(reason);
        print(CarouselPageChangedReason.controller);
      },
      enableInfiniteScroll: false,
    ),
    items: images.map<Widget>((i) {
      return Builder(
        builder: (BuildContext context) {
          return Container(
              width: MediaQuery.of(context).size.width,
              decoration: BoxDecoration(
                  image: DecorationImage(image: NetworkImage(i))));
        },
      );
    }).toList(),
  );
}
如何在Flutter中创建图像轮播?分步指南
Flutter创建图像轮播实例

Flutter图像轮播创建教程结论

如何在Flutter中创建图像轮播?正如我们所讨论的,如果你有合理的时间并需要更多的自定义,你可以自己实现一个轮播小部件。但是如果你需要一个快速的解决方案,使用 carousel_slider 会节省你的时间,因为它包含所有必要的功能,从头开始实施可能需要相当多的时间。

尽管我们为此示例实现了图像轮播,但你也可以使用相同的技术在你的应用程序中实现入门体验。

你可以在此处访问完整代码

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: