Flutter 滚轮年龄选择

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:notes/generated/l10n.dart';
import 'package:notes/res/colors.dart';
import 'package:notes/ui/widget/image_view.dart';
import 'package:notes/ui/widget/ink_widget.dart';

class AgePickerDialog {
  /// 显示年龄选择弹窗
  /// [initialAge] 初始选中的年龄,默认21
  /// 返回选中的年龄字符串,取消返回null
  static Future<String?> show(BuildContext context, {int initialAge = 18}) {
    return showModalBottomSheet<String>(
      context: context,
      backgroundColor: Colors.transparent,
      isScrollControlled: true,
      builder: (context) => _AgePickerDialog(initialAge: initialAge),
    );
  }
}

class _AgePickerDialog extends StatefulWidget {
  final int initialAge;

  const _AgePickerDialog({Key? key, required this.initialAge})
      : super(key: key);

  @override
  State<_AgePickerDialog> createState() => _AgePickerDialogState();
}

class _AgePickerDialogState extends State<_AgePickerDialog> {
  static const int _minAge = 18;
  static const int _maxAge = 99;

  late FixedExtentScrollController _scrollController;
  late int _selectedAge;

  @override
  void initState() {
    super.initState();
    _selectedAge = widget.initialAge.clamp(_minAge, _maxAge);
    _scrollController =
        FixedExtentScrollController(initialItem: _selectedAge - _minAge);
  }

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

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      decoration: BoxDecoration(
        color: const Color(0xFF1C1D20),
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(60.w),
          topRight: Radius.circular(60.w),
        ),
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          _buildHeader(),
          _buildPicker(),
          _buildSaveButton(),
        ],
      ),
    );
  }

  /// 标题栏:Age + 关闭按钮
  Widget _buildHeader() {
    return Stack(
      children: [

        Padding(
          padding: EdgeInsetsDirectional.only(
              start: 90.w, end: 90.w, top: 81.w,bottom: 21.w),
          child: Center(
            child: Text(
              S.current.lp2572,
              style: TextStyle(
                color: Colors.white,
                fontSize: 51.w,
                fontWeight: FontWeight.w500,
              ),
            ),
          ),
        ),
        Positioned(
          top: 48.w,
          right: 30.w,
          child: InkWidget(
            onTap: () => Navigator.of(context).pop(),
            borderRadius: BorderRadius.circular(36.w),
            inkW: 72.w,
            inkH: 72.w,
            child: CommonImageView(
              "ic_close" ,
              width: 54.w,
              height: 54.w,
            ),
          ),
        ),
      ],
    );
  }

  /// 滚轮选择器
  Widget _buildPicker() {
    final itemExtent = 108.w;
    const visibleCount = 5;
    final pickerHeight = itemExtent * visibleCount;

    return SizedBox(
      height: pickerHeight,
      child: Stack(
        alignment: Alignment.center,
        children: [
          // 选中项高亮背景
          Container(
            width: 467.w,
            height: 136.w,
            decoration: BoxDecoration(
              color: const Color(0xFF282A2E),
              borderRadius: BorderRadius.circular(36.w),
            ),
          ),
          // 滚轮
          ListWheelScrollView.useDelegate(
            controller: _scrollController,
            itemExtent: itemExtent,
            physics: const FixedExtentScrollPhysics(),
            diameterRatio: 1.5,
            perspective: 0.005,
            magnification: 1.2,
            useMagnifier: true,
            onSelectedItemChanged: (index) {
              setState(() {
                _selectedAge = _minAge + index;
              });
            },
            childDelegate: ListWheelChildBuilderDelegate(
              childCount: _maxAge - _minAge + 1,
              builder: (context, index) {
                final age = _minAge + index;
                final isSelected = age == _selectedAge;
                final distance = (age - _selectedAge).abs();

                double opacity;
                double fontSize;
                if (isSelected) {
                  opacity = 1.0;
                  fontSize = 64.w;
                } else if (distance == 1) {
                  opacity = 0.6;
                  fontSize = 54.w;
                } else if (distance == 2) {
                  opacity = 0.3;
                  fontSize = 45.w;
                } else {
                  opacity = 0.15;
                  fontSize = 39.w;
                }

                return Center(
                  child: Text(
                    '$age',
                    style: TextStyle(
                      color: Colors.white.withOpacity(opacity),
                      fontSize: fontSize,
                      fontWeight:FontWeight.w400,
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  /// Save 按钮
  Widget _buildSaveButton() {
    final bottomPadding = MediaQuery.of(context).padding.bottom;
    return Padding(
      padding: EdgeInsetsDirectional.only(
          start: 60.w, end: 60.w, top: 44.w, bottom: 44.w + bottomPadding),
      child: InkWidget(
        onTap: () {
          Navigator.of(context).pop('$_selectedAge');
        },
        borderRadius: BorderRadius.circular(60.w),
        child: Container(
          height: 120.w,
          decoration: BoxDecoration(
            color: const Color(0xFF8850F9),
            borderRadius: BorderRadius.circular(60.w),
          ),
          child: Center(
            child: Text(
              S.current.lp2241,
              style: TextStyle(
                color: Colors.white,
                fontSize: 42.w,
                fontWeight: FontWeight.w500,
              ),
            ),
          ),
        ),
      ),
    );
  }
}


©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容