LoginSignup
13
1
お題は不問!Qiita Engineer Festa 2023で記事投稿!

Flutterでループするスライダーを実装する(carousel_slider)

Posted at

今回作るもの

Webでは過去に無限にスクロールできるカルーセルスライダーを実装したことがあったのですが、Flutterでどうやるんだろう?と思い調べてみました。

(いらすとやから、最近流行りの「ヤツ」を使ってみました)

トップ画面 ボトムシート 動画

使用したパッケージ

今回は、このようなカルーセルが簡単にできるcarousel_sliderを採用しました。
パッケージ選定の条件的には問題なさそうです

実際のウィジェット(サンプル)

カルーセルに出したいリスト
final List<String> images = [
  'assets/kodai_sacabambaspis.png',
];
カルーセルの要素
class _CarouselCard extends StatelessWidget {
  const _CarouselCard({
    required this.image,
  });

  final String image;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 180,
      width: 120,
      decoration: BoxDecoration(
        color: Colors.black54,
        borderRadius: BorderRadius.circular(20),
      ),
      child: SizedBox(
        child: Image(
          image: AssetImage(image),
          fit: BoxFit.fitWidth,
        ),
      ),
    );
  }
}

今回のメインどころ

今回は、CarouserlSlider.builderを用いてカルーセルを設定しています。
CarouselSlideritemBuilderは3つの引数を持ちます。

itemBuilder:
  (BuildContext context, int itemIndex, int pageViewIndex) {
    return _CarouselCard(image: images[itemIndex]);
},
  • 第一引数: お馴染みのBuildContext
  • 第二引数: スライダーの要素のindexが取れます(images
    たとえば、配列要素が10件あった場合は0~9の値が取れます。
  • 第三引数: 擬似的なindex(詳細は後ほど説明します)
スライドできるカルーセル
class _CarouselSlider extends StatelessWidget {
  const _CarouselSlider();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 24),
      child: SizedBox(
        height: 180,
        child: CarouselSlider.builder(
          itemCount: images.length,
          itemBuilder:
              (BuildContext context, int itemIndex, int pageViewIndex) {
            return _CarouselCard(image: images[itemIndex]);
          },
          options: CarouselOptions(
            height: 180,
            viewportFraction: 0.35, // カルーセルの横幅を管理します
          ),
        ),
      ),
    );
  }
}
気休めにボトムシートエリアです
class _BottomSheetWidget extends StatelessWidget {
  const _BottomSheetWidget();

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 500,
      width: double.maxFinite,
      // 上だけ丸める
      decoration: const BoxDecoration(
        borderRadius: BorderRadius.vertical(
          top: Radius.circular(20),
        ),
        color: Color.fromARGB(42, 255, 255, 255),
      ),
      child: const Padding(
        padding: EdgeInsets.symmetric(vertical: 20),
        child: Column(
          children: [
            _CarouselSlider(),
          ],
        ),
      ),
    );
  }
}

注意点

実は、このcarousel_sliderは無限ではありません。
itemBuilderの先ほど3つの引数の話をしましたが、その中のpageViewIndexはどうなっているのか調べてみました。
パッケージの該当箇所を見てみます。

carousel_slider-4.2.1/lib/carousel_state.dart
class CarouselState {
  /// The [CarouselOptions] to create this state
  CarouselOptions options;

  /// [pageController] is created using the properties passed to the constructor
  /// and can be used to control the [PageView] it is passed to.
  PageController? pageController;

  /// The actual index of the [PageView].
  ///
  /// This value can be ignored unless you know the carousel will be scrolled
  /// backwards more then 10000 pages.
  /// Defaults to 10000 to simulate infinite backwards scrolling.
  int realPage = 10000;

  /// The initial index of the [PageView] on [CarouselSlider] init.
  ///
  int initialPage = 0;

  /// The widgets count that should be shown at carousel
  int? itemCount;

  /// Will be called when using pageController to go to next page or
  /// previous page. It will clear the autoPlay timer.
  /// Internal use only
  Function onResetTimer;

  /// Will be called when using pageController to go to next page or
  /// previous page. It will restart the autoPlay timer.
  /// Internal use only
  Function onResumeTimer;

  /// The callback to set the Reason Carousel changed
  Function(CarouselPageChangedReason) changeMode;

  CarouselState(
      this.options, this.onResetTimer, this.onResumeTimer, this.changeMode);
}

以下にある通り、上限は10000要素だということがわかりました。

carousel_slider-4.2.1/lib/carousel_state.dart
  /// The actual index of the [PageView].
  ///
  /// This value can be ignored unless you know the carousel will be scrolled
  /// backwards more then 10000 pages.
  /// Defaults to 10000 to simulate infinite backwards scrolling.
  int realPage = 10000;

実際に10000個分もスクロールするユーザーは稀かと思いますが、実は無限ではないという点には気をつけておきましょう。

kodai_sacabambaspis.png
サカバンバスピス

13
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
1