You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中实现刻度线式PageView商品数量选择组件

Flutter实现刻度线滚动数量选择器(PageView版)

针对你需要的这种带刻度线的滚动数量选择组件,完全可以用Flutter的PageView配合自定义布局来实现,下面是具体的实现思路和代码示例:

核心实现思路

  1. 用PageView.builder构建数量选项,通过viewportFraction设置小于1的值,让多个数量项同时显示在视口中,实现左右可见相邻选项的效果。
  2. 利用PageController监听滚动进度,动态计算每个数量项的缩放比例、透明度,让选中的中间项放大高亮。
  3. 刻度线部分通过Row包裹小容器实现,根据滚动进度更新刻度的高亮状态,也可以用CustomPaint做更精细的绘制。

完整代码示例

import 'package:flutter/material.dart';

class QuantityPicker extends StatefulWidget {
  final int minQuantity;
  final int maxQuantity;
  final ValueChanged<int>? onQuantityChanged;

  const QuantityPicker({
    super.key,
    this.minQuantity = 1,
    this.maxQuantity = 10,
    this.onQuantityChanged,
  });

  @override
  State<QuantityPicker> createState() => _QuantityPickerState();
}

class _QuantityPickerState extends State<QuantityPicker> {
  late PageController _pageController;
  double _currentPage = 0.0;

  @override
  void initState() {
    super.initState();
    _currentPage = widget.minQuantity - 1.toDouble();
    _pageController = PageController(
      initialPage: widget.minQuantity - 1,
      viewportFraction: 0.35, // 控制每个item占视口的比例,按需调整
    )..addListener(() {
        setState(() {
          _currentPage = _pageController.page!;
        });
      });
  }

  @override
  void dispose() {
    _pageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        // 顶部刻度线
        _buildIndicator(),
        const SizedBox(height: 16),
        // PageView数量选择
        SizedBox(
          height: 80,
          child: PageView.builder(
            controller: _pageController,
            itemCount: widget.maxQuantity - widget.minQuantity + 1,
            onPageChanged: (index) {
              widget.onQuantityChanged?.call(index + widget.minQuantity);
            },
            itemBuilder: (context, index) {
              final quantity = index + widget.minQuantity;
              // 计算当前item的缩放比例:选中项放大,其他项缩小
              final scale = 1 - (_currentPage - index).abs() * 0.7;
              return Center(
                child: Text(
                  quantity.toString(),
                  style: TextStyle(
                    fontSize: 40 * scale,
                    fontWeight: _currentPage.round() == index ? FontWeight.bold : FontWeight.normal,
                    color: _currentPage.round() == index ? Colors.black : Colors.grey.shade400,
                  ),
                ),
              );
            },
          ),
        ),
        const SizedBox(height: 16),
        // 底部刻度线(和顶部一致)
        _buildIndicator(),
      ],
    );
  }

  Widget _buildIndicator() {
    final totalItems = widget.maxQuantity - widget.minQuantity + 1;
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: List.generate(totalItems, (index) {
        // 计算当前刻度的高亮状态:当前选中页附近的刻度高亮
        final isActive = (_currentPage - index).abs() < 0.5;
        return Container(
          width: 8,
          height: isActive ? 6 : 3,
          margin: const EdgeInsets.symmetric(horizontal: 4),
          decoration: BoxDecoration(
            color: isActive ? Colors.black : Colors.grey.shade300,
            borderRadius: BorderRadius.circular(3),
          ),
        );
      }),
    );
  }
}

// 使用示例
class DemoScreen extends StatelessWidget {
  const DemoScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("数量选择器")),
      body: const Center(
        child: QuantityPicker(
          minQuantity: 1,
          maxQuantity: 10,
        ),
      ),
    );
  }
}

自定义调整说明

  • 修改viewportFraction可以调整同时显示的数量项个数,数值越小显示的项越多。
  • 调整_buildIndicator里的刻度尺寸、间距,以及itemBuilder里的缩放比例、字体大小,就能匹配你的设计图样式。
  • 如果需要更精致的刻度动画,可以把_buildIndicator换成CustomPaint,根据_currentPage的精确值绘制刻度的渐变高亮效果。

内容的提问来源于stack exchange,提问作者muhammed salih T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:47:36