在Flutter中禁用ListWheelScrollView中第一个项目的滚动。

huangapple go评论78阅读模式
英文:

Disabling scroll of first item in ListWheelScrollView in flutter

问题

以下是您提供的内容的翻译:

如何停止ListWheelScrollView在第一个索引处滚动。

期望输出: -

ListWheelScrollView遇到禁用项或ListView的第一个索引时,应停止滚动。滚动索引不应计算第一个索引,也就是说它不应继续向前移动或到达禁用的索引。

期望输出GIF: -

在Flutter中禁用ListWheelScrollView中第一个项目的滚动。

代码: -

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'List',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: const List(),
    );
  }
}

class List extends StatefulWidget {
  const List({Key? key}) : super(key: key);
  @override
  _ListState createState() => _ListState();
}

class _ListState extends State<List> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("List"),
          backgroundColor: Colors.green,
        ),
        body: Center(
          child: Stack(
            alignment: AlignmentDirectional.center,
            children: [
              RotatedBox(
                quarterTurns: 1,
                child: SizedBox(
                  height: 600,
                  width: 800,
                  child: ListWheelScrollView(
                      itemExtent: 100,
                      physics: const FixedExtentScrollPhysics(),
                      onSelectedItemChanged: (value) {},
                      children: [
                        for (int i = 0; i < 4; i++) ...[
                          Container(
                            color: i != 3 ? Colors.green[200] : Colors.red[200],
                            height: 70,
                            width: 70,
                            alignment: Alignment.center,
                            child: RotatedBox(
                                quarterTurns: -1,
                                child: Text(i != 3 ? "Enabled" : "Disabled")),
                          )
                        ]
                      ]),
                ),
              ),
              const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
            ],
          ),
        ));
  }
}

提供的一个解决方案: -

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'List',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: const ScrollingList(),
    );
  }
}

class ScrollingList extends StatefulWidget {
  const ScrollingList({Key? key}) : super(key: key);

  @override
  _ScrollingListState createState() => _ScrollingListState();
}

class _ScrollingListState extends State<ScrollingList> {
  final controller = FixedExtentScrollController();

  final children = [
    for (int i = 0; i < 6; i++) ScrollingListItem(enabled: i != 0)
  ];

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("List"),
          backgroundColor: Colors.green,
        ),
        body: Center(
          child: Stack(
            alignment: AlignmentDirectional.center,
            children: [
              RotatedBox(
                quarterTurns: 1,
                child: SizedBox(
                  height: 600,
                  width: 800,
                  child: ListWheelScrollView(
                    controller: controller,
                    itemExtent: 100,
                    physics: const FixedExtentScrollPhysics(),
                    onSelectedItemChanged: (idx) {
                      if (!children[idx].enabled) {
                        controller.animateToItem(
                          idx + 1,
                          duration: const Duration(milliseconds: 500),
                          curve: Curves.linear,
                        );
                      }
                    },
                    children: children,
                  ),
                ),
              ),
              const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
            ],
          ),
        ));
  }
}

class ScrollingListItem extends StatelessWidget {
  final bool enabled;

  const ScrollingListItem({Key? key, required this.enabled});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: enabled ? Colors.green[200] : Colors.red[200],
      height: 70,
      width: 70,
      alignment: Alignment.center,
      child: RotatedBox(
        quarterTurns: -1,
        child: Text(
          enabled ? "Enabled" : "Disabled",
        ),
      ),
    );
  }
}

其中有一个bug,当List Wheel滚动到禁用元素时,最后一个元素(极左侧容器)会闪烁: -

在Flutter中禁用ListWheelScrollView中第一个项目的滚动。

英文:

How to stop scrolling of ListWheelScrollView for the first index.

Expected Output : -

ListWheelScrollView should stop scrolling when it encounters a disabled item or the first index of ListView. Scroll index should not count the first index, that is it should not move further or to the disabled index.

Expected Output GIF : -

<img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExMGZmNGU1ODMzMTUzMWFjYTY5ZDA4ZTkzZDkzOWMzYmU3ODY0MDE0MCZlcD12MV9pbnRlcm5hbF9naWZzX2dpZklkJmN0PWc/r6Tj1PNNYuGkm5ZnEy/giphy.gif">

Code : -

import &#39;package:flutter/material.dart&#39;;
void main() =&gt; runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: &#39;List&#39;,
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: const List(),
);
}
}
class List extends StatefulWidget {
const List({Key? key}) : super(key: key);
@override
_ListState createState() =&gt; _ListState();
}
class _ListState extends State&lt;List&gt; {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(&quot;List&quot;),
backgroundColor: Colors.green,
),
body: Center(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
RotatedBox(
quarterTurns: 1,
child: SizedBox(
height: 600,
width: 800,
child: ListWheelScrollView(
itemExtent: 100,
physics: const FixedExtentScrollPhysics(),
onSelectedItemChanged: (value) {},
children: [
for (int i = 0; i &lt; 4; i++) ...[
Container(
color: i != 3 ? Colors.green[200] : Colors.red[200],
height: 70,
width: 70,
alignment: Alignment.center,
child: RotatedBox(
quarterTurns: -1,
child: Text(i != 3 ? &quot;Enabled&quot; : &quot;Disabled&quot;)),
)
]
]),
),
),
const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
],
),
));
}
}

One solution provided : -

import &#39;package:flutter/material.dart&#39;;
void main() =&gt; runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: &#39;List&#39;,
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: const ScrollingList(),
);
}
}
class ScrollingList extends StatefulWidget {
const ScrollingList({Key? key}) : super(key: key);
@override
_ScrollingListState createState() =&gt; _ScrollingListState();
}
class _ScrollingListState extends State&lt;ScrollingList&gt; {
final controller = FixedExtentScrollController();
final children = [
for (int i = 0; i &lt; 6; i++) ScrollingListItem(enabled: i != 0)
];
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(&quot;List&quot;),
backgroundColor: Colors.green,
),
body: Center(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
RotatedBox(
quarterTurns: 1,
child: SizedBox(
height: 600,
width: 800,
child: ListWheelScrollView(
controller: controller,
itemExtent: 100,
physics: const FixedExtentScrollPhysics(),
onSelectedItemChanged: (idx) {
if (!children[idx].enabled) {
controller.animateToItem(
idx + 1,
duration: const Duration(milliseconds: 500),
curve: Curves.linear,
);
}
},
children: children,
),
),
),
const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
],
),
));
}
}
class ScrollingListItem extends StatelessWidget {
final bool enabled;
const ScrollingListItem({super.key, required this.enabled});
@override
Widget build(BuildContext context) {
return Container(
color: enabled ? Colors.green[200] : Colors.red[200],
height: 70,
width: 70,
alignment: Alignment.center,
child: RotatedBox(
quarterTurns: -1,
child: Text(
enabled ? &quot;Enabled&quot; : &quot;Disabled&quot;,
),
),
);
}
}

It has a bug , the last element(extreme left container) will flash when List Wheel is moved to the disable element : -

<img src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExYWJkMzVkMWI5M2JjNDRkYThiOTM2MTA4MWJhYmYzMWU3ODQwN2U0ZiZlcD12MV9pbnRlcm5hbF9naWZzX2dpZklkJmN0PWc/mj2sQyJVRabf6xjTEa/giphy.gif">

答案1

得分: 1

以下是您提供的代码的中文翻译:

以下代码与您提供的解决方案类似,但有一些小改动。

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

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'List',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: const ScrollingList(),
    );
  }
}

class ScrollingList extends StatefulWidget {
  const ScrollingList({Key? key}) : super(key: key);

  @override
  _ScrollingListState createState() => _ScrollingListState();
}

class _ScrollingListState extends State<ScrollingList> {
  final controller = FixedExtentScrollController(initialItem: 1);

  final children = [
    for (int i = 0; i < 6; i++) ScrollingListItem(enabled: i != 0)
  ];

  void scrollListener() {
    if (controller.selectedItem == 1) {
      if (controller.position.userScrollDirection == ScrollDirection.forward) {
        controller.jumpToItem(1);
      }
    }
  }

  @override
  void initState() {
    super.initState();
    controller.addListener(scrollListener);
  }

  @override
  void dispose() {
    controller.removeListener(scrollListener);
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("List"),
          backgroundColor: Colors.green,
        ),
        body: Center(
          child: Stack(
            alignment: AlignmentDirectional.center,
            children: [
              RotatedBox(
                quarterTurns: 1,
                child: SizedBox(
                  height: 600,
                  width: 800,
                  child: ListWheelScrollView(
                    controller: controller,
                    itemExtent: 100,
                    physics: const FixedExtentScrollPhysics(),
                    // onSelectedItemChanged: (idx) {
                    //   if (!children[idx].enabled) {
                    //     controller.animateToItem(
                    //       idx + 1,
                    //       duration: const Duration(milliseconds: 500),
                    //       curve: Curves.linear,
                    //     );
                    //   }
                    // },
                    children: children,
                  ),
                ),
              ),
              const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
            ],
          ),
        ));
  }
}

class ScrollingListItem extends StatelessWidget {
  final bool enabled;

  const ScrollingListItem({super.key, required this.enabled});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: enabled ? Colors.green[200] : Colors.red[200],
      height: 70,
      width: 70,
      alignment: Alignment.center,
      child: RotatedBox(
        quarterTurns: -1,
        child: Text(
          enabled ? "Enabled" : "Disabled",
        ),
      ),
    );
  }
}

希望对您有所帮助。谢谢 :)
英文:

The following code is similar to your provided solution but with little changes.

import &#39;package:flutter/material.dart&#39;;
import &#39;package:flutter/rendering.dart&#39;;
void main() =&gt; runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: &#39;List&#39;,
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: const ScrollingList(),
);
}
}
class ScrollingList extends StatefulWidget {
const ScrollingList({Key? key}) : super(key: key);
@override
_ScrollingListState createState() =&gt; _ScrollingListState();
}
class _ScrollingListState extends State&lt;ScrollingList&gt; {
final controller = FixedExtentScrollController(initialItem: 1);
final children = [
for (int i = 0; i &lt; 6; i++) ScrollingListItem(enabled: i != 0)
];
void scrollListener() {
if (controller.selectedItem == 1) {
if (controller.position.userScrollDirection == ScrollDirection.forward) {
controller.jumpToItem(1);
}
}
}
@override
void initState() {
super.initState();
controller.addListener(scrollListener);
}
@override
void dispose() {
controller.removeListener(scrollListener);
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(&quot;List&quot;),
backgroundColor: Colors.green,
),
body: Center(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
RotatedBox(
quarterTurns: 1,
child: SizedBox(
height: 600,
width: 800,
child: ListWheelScrollView(
controller: controller,
itemExtent: 100,
physics: const FixedExtentScrollPhysics(),
// onSelectedItemChanged: (idx) {
//   if (!children[idx].enabled) {
//     controller.animateToItem(
//       idx + 1,
//       duration: const Duration(milliseconds: 500),
//       curve: Curves.linear,
//     );
//   }
// },
children: children,
),
),
),
const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
],
),
));
}
}
class ScrollingListItem extends StatelessWidget {
final bool enabled;
const ScrollingListItem({super.key, required this.enabled});
@override
Widget build(BuildContext context) {
return Container(
color: enabled ? Colors.green[200] : Colors.red[200],
height: 70,
width: 70,
alignment: Alignment.center,
child: RotatedBox(
quarterTurns: -1,
child: Text(
enabled ? &quot;Enabled&quot; : &quot;Disabled&quot;,
),
),
);
}
}

Hope it helps.
Thanks 在Flutter中禁用ListWheelScrollView中第一个项目的滚动。

答案2

得分: -1

以下是翻译好的部分:

你需要一种方法来检测当前的 index 是否被禁用,以充分利用与 FixedExtentScrollController 配对的 onSelectedItemChanged(不要忘记释放资源!),以平滑地滚动到你正在滚动到的项目的中心,使用 animateToItem()。你可以通过一个具有启用/禁用 bool 的类来实现这一点。

(还请不要将类命名为Dart关键字)

这是一个简单的工作示例。

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'List',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: const ScrollingList(),
    );
  }
}

class ScrollingList extends StatefulWidget {
  const ScrollingList({Key? key}) : super(key: key);

  @override
  _ScrollingListState createState() => _ScrollingListState();
}

class _ScrollingListState extends State<ScrollingList> {
  final controller = FixedExtentScrollController();

  final children = [
    for (int i = 0; i < 6; i++) ScrollingListItem(enabled: i != 3)
  ];

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("List"),
          backgroundColor: Colors.green,
        ),
        body: Center(
          child: Stack(
            alignment: AlignmentDirectional.center,
            children: [
              RotatedBox(
                quarterTurns: 1,
                child: SizedBox(
                  height: 600,
                  width: 800,
                  child: ListWheelScrollView(
                    controller: controller,
                    itemExtent: 100,
                    physics: const FixedExtentScrollPhysics(),
                    onSelectedItemChanged: (idx) {
                      if (!children[idx].enabled) {
                        controller.animateToItem(
                          idx,
                          duration: const Duration(milliseconds: 500),
                          curve: Curves.linear,
                        );
                      }
                    },
                    children: children,
                  ),
                ),
              ),
              const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
            ],
          ),
        ));
  }
}

class ScrollingListItem extends StatelessWidget {
  final bool enabled;

  const ScrollingListItem({Key? key, required this.enabled});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: enabled ? Colors.green[200] : Colors.red[200],
      height: 70,
      width: 70,
      alignment: Alignment.center,
      child: RotatedBox(
        quarterTurns: -1,
        child: Text(
          enabled ? "Enabled" : "Disabled",
        ),
      ),
    );
  }
}
英文:

You would need a way to detect that the current index is disabled to take advantage of the onSelectedItemChanged paired with a FixedExtentScrollController (don't forget to dispose!) to smoothly go to the center of the item you're scrolling into using animateToItem(). You can do this with a class having a enabled/disabled bool.

(Also don't name classes the same as dart keywords)

Here's a simple working example.

import &#39;package:flutter/material.dart&#39;;
void main() =&gt; runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: &#39;List&#39;,
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: const ScrollingList(),
);
}
}
class ScrollingList extends StatefulWidget {
const ScrollingList({Key? key}) : super(key: key);
@override
_ScrollingListState createState() =&gt; _ScrollingListState();
}
class _ScrollingListState extends State&lt;ScrollingList&gt; {
final controller = FixedExtentScrollController();
final children = [
for (int i = 0; i &lt; 6; i++) ScrollingListItem(enabled: i != 3)
];
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(&quot;List&quot;),
backgroundColor: Colors.green,
),
body: Center(
child: Stack(
alignment: AlignmentDirectional.center,
children: [
RotatedBox(
quarterTurns: 1,
child: SizedBox(
height: 600,
width: 800,
child: ListWheelScrollView(
controller: controller,
itemExtent: 100,
physics: const FixedExtentScrollPhysics(),
onSelectedItemChanged: (idx) {
if (!children[idx].enabled) {
controller.animateToItem(
idx,
duration: const Duration(milliseconds: 500),
curve: Curves.linear,
);
}
},
children: children,
),
),
),
const Positioned(top: 440, child: Icon(Icons.arrow_circle_up))
],
),
));
}
}
class ScrollingListItem extends StatelessWidget {
final bool enabled;
const ScrollingListItem({super.key, required this.enabled});
@override
Widget build(BuildContext context) {
return Container(
color: enabled ? Colors.green[200] : Colors.red[200],
height: 70,
width: 70,
alignment: Alignment.center,
child: RotatedBox(
quarterTurns: -1,
child: Text(
enabled ? &quot;Enabled&quot; : &quot;Disabled&quot;,
),
),
);
}
}

huangapple
  • 本文由 发表于 2023年5月17日 21:35:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76272717.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定