ListWheelChildBuilderDelegate 组件实战

27 阅读1分钟
import 'package:flutter/material.dart';
import 'package:module_base/util/log_util.dart';

class HeatListWheelScrollView extends StatefulWidget {
  final int initValue;
  final List<int> dataSources;
  final Color color;
  final ValueChanged<int> onChange;

  const HeatListWheelScrollView({
    super.key,
    required this.initValue,
    required this.dataSources,
    required this.onChange,
    required this.color,
  });

  @override
  State<HeatListWheelScrollView> createState() => _HeatListWheelScrollViewState();
}

class _HeatListWheelScrollViewState extends State<HeatListWheelScrollView> {
  String TAG = "_HeatListWheelScrollViewState";

  late FixedExtentScrollController _controller;

  late int _selectIndex;

  bool isUserScrolling = false;  // 标记是否是用户手动滚动

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _selectIndex = widget.dataSources.indexOf(widget.initValue);
    _controller = FixedExtentScrollController(initialItem: _selectIndex);
  }

  // @override
  @override
  void didUpdateWidget(covariant HeatListWheelScrollView oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 当 initValue 或 dataSources 发生变化时,更新 _controller 的位置
    if (oldWidget.initValue != widget.initValue || oldWidget.dataSources != widget.dataSources) {
      _selectIndex = widget.dataSources.indexOf(widget.initValue);
      _controller.jumpToItem(_selectIndex);
      Log.d("_HeatListWheelScrollViewState", "Updated to index $_selectIndex");
    }
  }

  @override
  Widget build(BuildContext context) {
    return NotificationListener<ScrollNotification>(
      onNotification: (notification) {
        if (notification is ScrollStartNotification) {
          // 手动滑动
          if (notification.dragDetails != null) {
            isUserScrolling = true;  // 用户手动滚动
            Log.d(TAG, "用户开始滚动");
          }
        } else if (notification is ScrollEndNotification) {
          // 滚动结束
          if (isUserScrolling) {
            Log.d(TAG, "手动滑动滚动结束");
            widget.onChange(widget.dataSources[_selectIndex]);
          } else {
            Log.d(TAG, "编程滚动结束");
          }
          isUserScrolling = false; // 归位

        }
        return true;
      },
      child: RotatedBox(
        quarterTurns: 1,
        child: ListWheelScrollView.useDelegate(
          controller: _controller,
          physics: FixedExtentScrollPhysics(),
          // 每个项的高度
          itemExtent: 100,
          //是否方法效果
          // useMagnifier: true,
          magnification: 1.2,
          //压缩
          // squeeze: 0.7,
          overAndUnderCenterOpacity: 0.5,
          clipBehavior: Clip.none,
          onSelectedItemChanged: (index) {
            _selectIndex = index;
            Log.d(TAG, "_selectIndex11 = $_selectIndex");
            setState(() {});
          },
          childDelegate: ListWheelChildBuilderDelegate(
            builder: (context, index) {
              int item = widget.dataSources[index];
              return SizedBox(
                width: 78,
                height: 51,
                child: RotatedBox(
                  quarterTurns: 3,
                  child: Stack(
                    children: [
                      Align(
                        alignment: Alignment.topCenter,
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            Text(
                              "$item",
                              style: TextStyle(color: widget.color, fontSize: 44),
                            ),
                          ],
                        ),
                      ),
                      Visibility(
                        visible: index == _selectIndex,
                        child: Positioned(
                          top: 5,
                          right: 5,
                          child: Text(
                            "℃",
                            style: TextStyle(color: widget.color, fontSize: 18),
                          ),
                        ),
                      )
                    ],
                  ),
                ),
              );
            },
            childCount: widget.dataSources.length,
          ),
        ),
      ),
    );
  }
}