layout method

  1. @override
List<Widget> layout(
  1. BuildContext context, {
  2. required double progress,
  3. required BoxConstraints constraints,
  4. required CarouselAlignment alignment,
  5. required Axis direction,
  6. required CarouselSizeConstraint sizeConstraint,
  7. required double progressedIndex,
  8. required int? itemCount,
  9. required CarouselItemBuilder itemBuilder,
  10. required bool wrap,
  11. required bool reverse,
})
override

Layouts the carousel items.

  • context is the build context.
  • progress is the progress of the carousel.
  • constraints is the constraints of the carousel.
  • alignment is the alignment of the carousel.
  • direction is the direction of the carousel.
  • sizeConstraint is the size constraint of the carousel.
  • progressedIndex is the progressed index of the carousel.
  • itemCount is the item count of the carousel.
  • itemBuilder is the item builder of the carousel.
  • wrap is whether the carousel should wrap.
  • reverse is whether the carousel should reverse.

Implementation

@override
List<Widget> layout(
  BuildContext context, {
  required double progress,
  required BoxConstraints constraints,
  required CarouselAlignment alignment,
  required Axis direction,
  required CarouselSizeConstraint sizeConstraint,
  required double progressedIndex,
  required int? itemCount,
  required CarouselItemBuilder itemBuilder,
  required bool wrap,
  required bool reverse,
}) {
  int additionalPreviousItems = 1;
  int additionalNextItems = 1;
  double originalSize = direction == Axis.horizontal
      ? constraints.maxWidth
      : constraints.maxHeight;
  double size;
  if (sizeConstraint is CarouselFixedConstraint) {
    size = sizeConstraint.size;
  } else if (sizeConstraint is CarouselFractionalConstraint) {
    size = originalSize * sizeConstraint.fraction;
  } else {
    size = originalSize;
  }
  double snapOffsetAlignment = (originalSize - size) * alignment.alignment;
  double gapBeforeItem = snapOffsetAlignment;
  double gapAfterItem = originalSize - size - gapBeforeItem;
  additionalPreviousItems += max(0, (gapBeforeItem / size).ceil());
  additionalNextItems += max(0, (gapAfterItem / size).ceil());
  List<_PlacedCarouselItem> items = [];
  // curving the index
  int start = progressedIndex.floor() - additionalPreviousItems;
  int end = progressedIndex.floor() + additionalNextItems;
  if (!wrap && itemCount != null) {
    start = start.clamp(0, itemCount - 1);
    end = end.clamp(0, itemCount - 1);
  }
  double currentIndex = progressedIndex + (gap / size) * progressedIndex;
  for (int i = start; i <= end; i++) {
    double index;
    if (itemCount != null) {
      index = wrapDouble(i.toDouble(), 0.0, itemCount.toDouble());
    } else {
      index = i.toDouble();
    }
    var itemIndex = reverse ? (-index).toInt() : index.toInt();
    final item = itemBuilder(context, itemIndex);
    double position = i.toDouble();
    // offset the gap
    items.add(_PlacedCarouselItem._(
      relativeIndex: i,
      child: item,
      position: position,
    ));
  }
  if (direction == Axis.horizontal) {
    return [
      for (var item in items)
        Positioned(
            left: snapOffsetAlignment +
                (item.position - currentIndex) * size +
                (gap * item.relativeIndex),
            width: size,
            height: constraints.maxHeight,
            child: item.child),
    ];
  } else {
    return [
      for (var item in items)
        Positioned(
            top: snapOffsetAlignment +
                (item.position - currentIndex) * size +
                (gap * item.relativeIndex),
            width: constraints.maxWidth,
            height: size,
            child: item.child),
    ];
  }
}