Cupertino DateTime Picker干扰滚动行为

发布于 2025-02-13 12:33:39 字数 5138 浏览 0 评论 0 原文

我有一个包括一系列问卷的应用程序。其中之一是5页长,每个页面本质上是一个单式唱片,其中包含5-10个相同自定义小部件的列,除了第一页外,还包括2个库比蒂诺时代的拾取器。自定义小部件本身是一个具有5行的列 - 顶行是文本窗口小部件(问题),而行2-5是其中一个可能的答案(文本窗口小部件)和一个无线电按钮。

但是,当第一页最初加载时,通过问卷调查表时,我可以上下滚动,但是在从上到下进行5个滚动大约5个滚动后,滚动变得越来越janky。性能配置文件显示,滚动从前几个滚动中的120fps变为10fps或更低。现在,我花了一段时间以为这是一个滚动问题,但是我也注意到,如果我在Appbar上按“向后”页面过渡动画也很笨拙且缓慢。

在测试时,似乎是库比蒂诺采摘者。我已经制作了一个示例应用程序(下图),以模拟问卷的文本介绍,但没有依赖性。如果该应用程序运行并注释了,并且您反复上下滚动,则帧速率很好。如果未评论采摘器并出现在应用程序中,则重复滚动会导致FPS逐渐跌落,最终很笨拙。这是在真实的iOS设备上(如果有任何效果在模拟器上的效果要少得多),并且不需要与选择器进行任何交互(无需选择时间)。

有人知道为什么会发生这种情况吗?

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(

        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {


    return Scaffold(
      appBar: AppBar(
        title: const  Text('Scroll Test'),
      ),
      body: SafeArea(
        child: SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              const Padding(
                padding: EdgeInsets.only(top: 8.0),
                child: Text( 'This is an instruction to make sense of the rest of the questions'
                ),
              ),
              SizedBox(
                width: MediaQuery.of(context).size.width * .9,
                height: MediaQuery.of(context).size.height * .2,
                child: CupertinoDatePicker(
                    key: UniqueKey(),
                    use24hFormat: true,
                    onDateTimeChanged: (DateTime newtime) {

                    },
                    initialDateTime: DateTime(2020, 3, 6, 8),
                    maximumDate: DateTime(2020, 3, 6, 20),
                    mode: CupertinoDatePickerMode.time),
              ),
              TestWidget(),
              TestWidget(),
              TestWidget(),
              TestWidget(),
              SizedBox(
                width: MediaQuery.of(context).size.width * .9,
                height: MediaQuery.of(context).size.height * .2,
                child: CupertinoDatePicker(
                    key: UniqueKey(),
                    use24hFormat: true,
                    onDateTimeChanged: (DateTime newtime) {

                    },
                    initialDateTime: DateTime(2020, 3, 6, 8),
                    maximumDate: DateTime(2020, 3, 6, 20),
                    mode: CupertinoDatePickerMode.time),
              ),
              TestWidget(),
              TestWidget(),
              TestWidget(),

              TextButton(
                  onPressed: () {
                  },
                  child: const Text('Next'))
            ],
          ),
        ),
      ),
    );
  }
}



class TestWidget extends StatelessWidget {

  final String quest;
  final String opt1;
  final String opt2;
  final String opt3;
  final String opt4;


  const TestWidget({Key? key,
    this.quest = 'Here  is a question with some quite long text.  And even a second sentence',
    this.opt1 = "option 1",
    this.opt2 = 'option 2',
    this.opt3 = 'Option 3',
    this.opt4 = 'Option 4'
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {

    return SizedBox(
      height: 300,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(quest),
          Row(
            children: [
              Expanded(
                  flex: 8,
                  child: Text(opt1)),
              Expanded(
                flex: 2,
                child: Text('x'),
              )
            ],
          ),
          Row(
            children: [
              Expanded(
                  flex: 8,
                  child: Text(opt2)),
              Expanded(
                flex: 2,
                child: Text('x'),
              )
            ],

          ),

          Row(
            children: [
              Expanded(
                  flex: 8,
                  child: Text(opt3)),
              Expanded(
                flex: 2,
                child: Text('x'),
              )
            ],

          ),
          Row(
            children: [
              Expanded(
                  flex: 8,
                  child: Text(opt4)),
              Expanded(
                flex: 2,
                child: Text('x'),
              )

            ],
          ),

          const Padding(
            padding: EdgeInsets.only(top:8.0),
            child: Divider(),
          )
        ],
      ),
    );
  }
}

I have an app that includes a series of questionnaires. One of which is 5 pages long, and each page is essentially a SingleChildScrollView with a column containing 5-10 items of the same custom widget, apart from the first page which also includes 2 cupertino time pickers. The custom widget itself is a column with 5 Rows - The top row is a Text widget (the question) and rows 2-5 are rows each of which contains a possible answer (text widget) and a radio button.

However, when going through the questionnaire when the first page initially loads, I can scroll up and down fine, but after around 5 scrolls from top to bottom, the scrolling becomes increasingly janky. The performance profile shows the scrolling goes from 120fps in the first few scrolls to 10fps or lower. Now I spent a while assuming this was a scrolling issue, but I've also noticed that if I press 'back' on the AppBar the page transition animation is also very janky and slow.

On testing, it seems that it is the Cupertino pickers. I have made a sample app (below) to mock up the text presentation of the questionnaire but with no dependencies. If the app is run with the pickers commented out and you scroll up and down repeatedly, the frame rate is fine. If the pickers are not commented out and show up in the app, then repeated scrolling causes a progressive fall in the fps which eventually is very janky. This is on a real iOS device (if anything the effect is much less on the simulator) and doesn't require any interaction with the picker (no need to pick a time).

Anyone have any idea why this is happening?

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(

        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {


    return Scaffold(
      appBar: AppBar(
        title: const  Text('Scroll Test'),
      ),
      body: SafeArea(
        child: SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              const Padding(
                padding: EdgeInsets.only(top: 8.0),
                child: Text( 'This is an instruction to make sense of the rest of the questions'
                ),
              ),
              SizedBox(
                width: MediaQuery.of(context).size.width * .9,
                height: MediaQuery.of(context).size.height * .2,
                child: CupertinoDatePicker(
                    key: UniqueKey(),
                    use24hFormat: true,
                    onDateTimeChanged: (DateTime newtime) {

                    },
                    initialDateTime: DateTime(2020, 3, 6, 8),
                    maximumDate: DateTime(2020, 3, 6, 20),
                    mode: CupertinoDatePickerMode.time),
              ),
              TestWidget(),
              TestWidget(),
              TestWidget(),
              TestWidget(),
              SizedBox(
                width: MediaQuery.of(context).size.width * .9,
                height: MediaQuery.of(context).size.height * .2,
                child: CupertinoDatePicker(
                    key: UniqueKey(),
                    use24hFormat: true,
                    onDateTimeChanged: (DateTime newtime) {

                    },
                    initialDateTime: DateTime(2020, 3, 6, 8),
                    maximumDate: DateTime(2020, 3, 6, 20),
                    mode: CupertinoDatePickerMode.time),
              ),
              TestWidget(),
              TestWidget(),
              TestWidget(),

              TextButton(
                  onPressed: () {
                  },
                  child: const Text('Next'))
            ],
          ),
        ),
      ),
    );
  }
}



class TestWidget extends StatelessWidget {

  final String quest;
  final String opt1;
  final String opt2;
  final String opt3;
  final String opt4;


  const TestWidget({Key? key,
    this.quest = 'Here  is a question with some quite long text.  And even a second sentence',
    this.opt1 = "option 1",
    this.opt2 = 'option 2',
    this.opt3 = 'Option 3',
    this.opt4 = 'Option 4'
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {

    return SizedBox(
      height: 300,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Text(quest),
          Row(
            children: [
              Expanded(
                  flex: 8,
                  child: Text(opt1)),
              Expanded(
                flex: 2,
                child: Text('x'),
              )
            ],
          ),
          Row(
            children: [
              Expanded(
                  flex: 8,
                  child: Text(opt2)),
              Expanded(
                flex: 2,
                child: Text('x'),
              )
            ],

          ),

          Row(
            children: [
              Expanded(
                  flex: 8,
                  child: Text(opt3)),
              Expanded(
                flex: 2,
                child: Text('x'),
              )
            ],

          ),
          Row(
            children: [
              Expanded(
                  flex: 8,
                  child: Text(opt4)),
              Expanded(
                flex: 2,
                child: Text('x'),
              )

            ],
          ),

          const Padding(
            padding: EdgeInsets.only(top:8.0),
            child: Divider(),
          )
        ],
      ),
    );
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

懒的傷心 2025-02-20 12:33:39

如果有人来找同一问题,这是当前主频道

https://github.com/flutter/flutter/issues/106737

In case anyone comes looking for the same issue, this turned out to be anctual bug addressed in the current master channel

https://github.com/flutter/flutter/issues/106737

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文