CarouselView

一个基于Material设计的轮播图组件

CarouselView是一个Material Design轮播组件,用于创建可滚动的动态列表。它类似于ListView,但支持项的大小动态调整、吸附效果和各种布局模式,适用于图像画廊、产品展示或内容滑动器等场景。CarouselView支持水平或者垂直滚动,默认水平。

CarouselView的布局主要通过两个构造函数实现:

  • CarouselView() 默认的uncontained布局模型,所有子项均匀大小,类似于ListView
  • CarouselView.weighted() 支持动态项大小,通过权重weights分配视口比例,实现更加复杂的布局,如hero或者multi-browse

主要的布局类型:

  • Uncontained 默认布局

这是CarouselView的默认布局,所有子项大小均匀,滚动到容器边缘,类似于ListView。适合简单、均匀的轮播,如产品卡片列表。项不会动态缩放,滚动平滑,支持无限滚动(通过PageController)。

示例

import 'package:flutter/material.dart';

class UncontainedCarousel extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: CarouselView(
        itemExtent: 200,  // 每个项宽度(水平滚动)
        padding: const EdgeInsets.all(16),
        itemSnapping: true, //滚动到边缘时吸附
        children: List.generate(5, (index) => Card(
          child: Center(child: Text('Item $index')),
        )),
      ),
    );
  }
}

  • Full-Screen布局

项占满整个视口,提供沉浸式体验,常用于图像画廊或全屏产品展示。只显示一个项,滚动时完全替换。使用uncontained模式,但是将itemExtent设置为视口大小(double.infinity或者MediaQuery获取屏幕尺寸)。结合垂直滚动scrollDirection: Axis.verical可实现全屏滑动。

示例

import 'package:flutter/material.dart';

class FullScreenCarousel extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: CarouselView(
        scrollDirection: Axis.vertical,  // 可选:垂直全屏
        itemExtent: double.infinity,  // 占满视口
        itemSnapping: true,
        children: List.generate(10, (index) => Image.network(
          'https://picsum.photos/500/800?image=$index',
          fit: BoxFit.cover,
          width: double.infinity,
          height: double.infinity,
        )),
      ),
    );
  }
}

  • Multi-Browse布局

允许多个项同时可见,每个项根据权重动态分配视口比例(如[3,2,1]表示前项较大,后项渐小)。使用weighted构造函数,实现"瀑布式"布局,项进入/退出视口时大小渐变。适合浏览多个相关内容,如新闻卡片或者多产品预览。当第一项完全移出屏幕时,后续项保持相同比例。

示例

import 'package:flutter/material.dart';

class MultiBrowseCarousel extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: CarouselView.weighted(
        flexWeights: const [3, 2, 1],  // 权重:前大后小
        padding: const EdgeInsets.all(8),
        children: List.generate(5, (index) => Container(
          color: Colors.blue[100 * (index + 1)],
          child: Center(child: Text('Browse Item $index')),
        )),
      ),
    );
  }
}

  • Hero布局

焦点项(中心项)最大化展示,其他项缩小或者部分可见,创建焦点效果。基于weighted模式,通过自定义权重实现。变体包括center-alinged hero(中心对齐英雄布局),项围绕中心渐变大小。适合突出推荐内容,如焦点产品展示。使用CarouselView.weighted()设置权重如[1, 3, 1]中心项最大。

示例

import 'package:flutter/material.dart';

class HeroCarousel extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Scaffold(
      body: CarouselView.weighted(
        flexWeights: const [1, 3, 1],  // 中心项权重最高
        padding: const EdgeInsets.symmetric(horizontal: 32),
        children: List.generate(5, (index) => Card(
          child: Container(
            height: 200,
            child: Center(child: Text('Hero Item $index')),
          ),
        )),
      ),
    );
  }
}

构造函数

CarouselView.new({
  Key? key, 
  EdgeInsets? padding, 
  Color? backgroundColor, 
  double? elevation, 
  ShapeBorder? shape, 
  Clip? itemClipBehavior, 
  WidgetStateProperty<Color?>? overlayColor, 
  bool itemSnapping = false, 
  double shrinkExtent = 0.0, 
  CarouselController? controller, 
  Axis scrollDirection = Axis.horizontal, 
  bool reverse = false, 
  ValueChanged<int>? onTap, 
  bool enableSplash = true, 
  required double itemExtent, 
  required List<Widget> children
})


CarouselView.weighted({
  Key? key, 
  EdgeInsets? padding, 
  Color? backgroundColor, 
  double? elevation, 
  ShapeBorder? shape, 
  Clip? itemClipBehavior, 
  WidgetStateProperty<Color?>? overlayColor, 
  bool itemSnapping = false, 
  double shrinkExtent = 0.0, 
  CarouselController? controller, 
  Axis scrollDirection = Axis.horizontal, 
  bool reverse = false, 
  bool consumeMaxWeight = true, 
  ValueChanged<int>? onTap, 
  bool enableSplash = true, 
  required List<int> flexWeights, 
  required List<Widget> children
})

属性

属性名属性类型说明
backgroundColorColor?背景颜色
childrenList<Widget>子组件,轮播图项列表
consumeMaxWeightbool用于控制是否优先让焦点项占用最大权重
controllerCarouselController?用于控制滚动视图滚动位置的控制器
elevationdouble?Z轴深度
enableSplashbool用于控制是否每个轮播项都覆盖有墨水效果,即InkWell组件
flexWeightsList<int>?用于控制权重比例的列表
itemClipBehaviorClip?用于控制每个轮播项的裁剪
itemExtentdouble?设置轮播项在主轴上的占用空间
itemSnappingbool控制轮播项在边缘时是否进行吸附
onTapValueChanged<int>?轮播项点击事件
overlayColorWidgetStateProperty<Color?>?用于设置指示轮播项在被点击,悬停和聚焦时的高亮颜色
paddingEdgeInsets?内边距
reversebool设置轮播项是否反向排列
scrollDirectionAxis控制滚动方向为水平还是垂直
shapeShapeBorder?设置每个轮播项的遮罩形状
shrinkExtentdouble设置每个轮播项在滚动时主轴方向上缩小的最小的尺寸