Flutter 表单构建器小部件:无意滚动

Flutter form builder widgets : unintentional scrolling

我正在使用 flutter_form_builder 创建表单。问题是,当我单击表单复选框时,复选框小部件会移动到屏幕顶部。该复选框包含在另一个有状态小部件(颜色较浅)中,该小部件嵌入在 Column->FormBuilder->SingleChildScrollView

    return SingleChildScrollView(
    child: FormBuilder(
      key: _formKey,
      autovalidateMode: AutovalidateMode.disabled,
      onWillPop: () async {
        return true;
      },
      skipDisabled: false,
      child: Column(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          ...
          SpecialContainer(
            title: 'Content',
            children: [
              FormBuilderCheckbox(
                name: 'damageLocalized',
                initialValue: false,
                title: const Text('Form Builder Widget'),
              ),
              Row(
                children: [
                  Checkbox(
                    value: test, onChanged: (bool? value) {
                    setState(() {
                      test = !test;
                    });
                    },
                    autofocus: true,
                  ),
                  const Text('Checkbox'),
                ],
              ),
            ],
            defaultExpandedStatus: false,
          ),
          ...
       ],
      ),
    )
);

包含复选框的 SpecialContainer 小部件:

class FormSection extends StatefulWidget{

  final List<Widget> children;
  final String title;
  final bool defaultExpandedStatus;

  const FormSection({Key? key, required this.children, required this.title, required 
  this.defaultExpandedStatus}) : super(key: key);

  @override
  State<StatefulWidget> createState() => FormSectionState();
}

class FormSectionState extends State<FormSection> with SingleTickerProviderStateMixin{

  late final AnimationController expandController;
  late final Animation<double> animation;
  bool isExpanded = false;

  FormSectionState(){
    expandController = AnimationController(
        vsync: this,
        duration: const Duration(milliseconds: 250)
    );
    animation = CurvedAnimation(
      parent: expandController,
      curve: Curves.fastOutSlowIn,
    );
  }

  @override
  void initState() {
    super.initState();
    //isExpanded = widget.defaultExpandedStatus;
    _runExpandCheck();
  }

  void _runExpandCheck() {
    if(isExpanded) {
      expandController.reverse();
      setState(() {
        isExpanded = false;
      });
    }
    else {
      expandController.forward();
      setState(() {
       isExpanded = true;
          });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(10),
      child: Container(
        width: double.infinity,
        padding: const EdgeInsets.symmetric(horizontal: 16),
        decoration: BoxDecoration(
          color: Theme.of(context).colorScheme.surface,
          borderRadius: const BorderRadius.all(Radius.circular(10)),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.start,
          children: [
            GestureDetector(
                onTap: (){
                  _runExpandCheck();
                },
                child: Padding(
                  padding: const EdgeInsets.all(16),
                  child: Container(
                    padding: const EdgeInsets.symmetric(horizontal: 16),
                    child: Row(
                      mainAxisSize: MainAxisSize.max,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text(
                          widget.title,
                          style: Theme.of(context).textTheme.headline6,
                        ),
                        Icon(
                            isExpanded?Icons.keyboard_arrow_down:Icons.keyboard_arrow_up
                        ),
                      ],
                    ),
                    width: double.infinity,
                  ),
                )
            ),
            SizeTransition(
              axisAlignment: 1.0,
              sizeFactor: animation,
              child: Column(
                  children: widget.children
              ),
            )
          ],
        ),
      ),
    );
  }

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

}

可以使用表单生成器下拉菜单重现相同的行为

添加阻止表单小部件请求焦点的选项将解决此问题。

https://github.com/danvick/flutter_form_builder/issues/921

WilliamCunhaCardoso 在此拉取请求中请求该功能:

https://github.com/danvick/flutter_form_builder/pull/881