颤振列表视图字母索引
Posted
技术标签:
【中文标题】颤振列表视图字母索引【英文标题】:flutter listview alphabet index 【发布时间】:2019-04-25 06:00:24 【问题描述】:如何在“android 中的 recyclerview 字母索引”之类的颤动中获取手指移动事件检查示例图像。
我创建了一个定位字母索引列表视图,但在 DragUpdate 中找不到当前索引。
var alphabet = ["#","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
new Positioned(
top: .0,
left: 1,
bottom: 10,
width: 55,
child: Material(
borderRadius: BorderRadius.circular(15.0),
elevation: 10.0,
child: ListView.builder(
itemCount: alphabet.length,
itemBuilder: (BuildContext context, int index)
return new GestureDetector(
onVerticalDragUpdate:
(DragUpdateDetails detail)
setState(()
_barOffset += detail.delta.dy;
);
print("$detail");
print("Update $alphabet[index]");
,
onVerticalDragStart: (DragStartDetails detail)
print("onVerticalDragStart");
print("Start $alphabet[index]");
,
onVerticalDragEnd: (DragEndDetails detail)
print("onVerticalDragEnd");
print("End $alphabet[index]");
,
onTap: () => print(alphabet[index]),
child: new Container(
margin: EdgeInsets.only(
left: 20.0, right: 10.0, top: 6.5),
height: 15.0,
child: new Text('$alphabet[index]'),
));
),
),
【问题讨论】:
pub.dartlang.org/packages/side_header_list_view 有点类似 或者这个:pub.dartlang.org/packages/draggable_scrollbar 这正是您所寻求的:pub.dev/packages/alphabet_list_scroll_view 【参考方案1】:请执行以下步骤来实现此目的。
第 1 步: A 到 Z 滑块的手势检测器
onVerticalDragUpdate:_onVerticalDragUpdate
onVerticalDragStart: _onVerticalDragStart
第 2 步:为滚动字母添加对话气泡。
第三步:计算垂直滚动位置的索引
if ((_offsetContainer + details.delta.dy) >= 0 &&
(_offsetContainer + details.delta.dy) <=
(_sizeheightcontainer - _heightscroller))
_offsetContainer += details.delta.dy;
posSelected =
((_offsetContainer / _heightscroller) % _alphabet.length).round();
_text = _alphabet[posSelected];
if (_text != _oldtext)
for (var i = 0; i < exampleList.length; i++)
if (_text
.toString()
.compareTo(exampleList[i].toString().toUpperCase()[0]) == 0)
_controller.jumpTo(i * _itemsizeheight);
break;
_oldtext = _text;
对于完整的实现,请检查:
https://github.com/sanjaysingh1990/AtoZSliderCustomized.git
【讨论】:
嗨,我刚刚实现了上面给出的与 A 到 Z 滑块相关的逻辑。 请分享你的库到 dartpub【参考方案2】:拥有这样的东西:
开头部分
要解决此问题,您需要创建一个自定义小部件,该小部件将返回一个 LayoutBuilder
,其中包含一个 Stack
,其中在第一层包含一个 ListView
,在右侧的第二层(作为滚动条)包含一个 Container
(要将您的滚动条放在右侧,请将alignment: Alignment.topRight
添加到您的Stack
)。
使滚动条移动
要移动滚动条,请添加GestureDetector
并捕捉onVerticalDragUpdate
,将自定义属性_offsetContainer
添加到您将添加details.delta.dy
(来自事件)的属性中,以使滚动条上下移动。
使 ListView 从滚动条中移动
第一部分
之后,您需要将ScrollController
添加到您的ListView
以控制它的垂直移动(作为controller
属性)。
好的,现在你需要知道多个东西才能继续:
您的字母数组长度ListView
的高度大小
滚动条的高度尺寸
对项目集合进行排序(逻辑)
您的ListView
(我们将其称为_itemsizeheight
)中一项的高度尺寸
现在要达到的目标是将您的ListView
移动到列表中以所选字母开头的第一项。
为此,您需要一些数学知识和一些技巧。
要计算您的ListView
高度,您需要获取身体高度并移除其他小部件的高度。但是为了简化这里我们会说你的ListView
占据了所有的身高。然后对应contrainsts.biggest.height
(感谢LayoutBuilder
)。
要计算您的滚动条高度,您可以有效地进行计算,然后将主体高度除以字母数组中的字母数。
_heightscroller = contrainsts.biggest.height / _alphabet.length;
第二部分
我们将首先使用Text
小部件使滚动条显示字母索引。然后将Text
小部件添加到您的控制器,并在您的自定义小部件中添加_text
属性,以便您使用setState
函数对其进行更改。
在您的onVerticalDragUpdate
中,您的_offset
值对应于您的滚动条位置。然后你需要做一个“简单”的计算来找到它对应的字母数组的女巫索引。
_text = _alphabet[((_offsetContainer / _heightscroller) % _alphabet.length).round()];
第三部分
现在您知道了这封信,那么您就可以轻松移动您的ListView
。
首先获取列表中与所选字母相对应的第一个元素的索引。
例子:
var index = 0;
for (var i = 0; i < widget.items.length; i++)
if (widget.items[i].toString().trim().length > 0 &&
widget.items[i].toString().trim().toUpperCase()[0] ==
_text.toString().toUpperCase()[0])
index = i;
break;
现在您有了索引,只需使用您的ScrollController
移动您的ListView
。
_scrollController.animateTo(index * _itemsizeheight,
duration: new Duration(milliseconds: 500),
curve: Curves.ease);
从 ListView 移动滚动条
好的,现在它可以工作了,但是我们也需要移动滚动条,不是吗?我的意思是当ListView
将显示我A
字母项目时,我不希望它留在V
字母上。
如何做到这一点?
在你的初始化函数中,你设置你的ScrollController
添加一个
_scrollController.addListener(onscrolllistview);
知道用户何时会直接在ListView
中滚动。
在您的 onscrolllistview
function 中,您需要进行一些计算才能显示第一个项目和最后一个项目。
var indexFirst = ((_scrollController.offset / _itemsizeheight) % widget.items.length).floor();
var indexLast = ((((_heightscroller * _alphabet.length) / _itemsizeheight).floor() + indexFirst) - 1) % widget.items.length;
现在完美了,您可以轻松知道需要在滚动条上显示的女巫字母,然后知道它需要在哪里(更改它的偏移量)。
var i = _alphabet.indexOf(fletter);
if (i != -1)
setState(()
_text = _alphabet[i];
_offsetContainer = i * _heightscroller;
);
fletter
变量将取决于滚动的方向。
如果你往下走,它将是:
var fletter = widget.items[indexLast].toString().toUpperCase()[0];
如果你往上走,它将是:
var fletter = widget.items[indexFirst].toString().toUpperCase()[0];
修复滚动条动画
好的,现在如果你放一个debugPrint
,你会看到onscrolllistview
函数一直被调用,即使我们正在使用滚动条。这是个问题。那怎么解决呢?
您需要知道何时完成才能在所有动画完成后移动。
然后在你的类中添加一个_animationcounter
属性。
当您移动滚动条时,您将增加它,并在一个动画完成时减少它。
像这样:
for (var i = 0; i < widget.items.length; i++)
if (widget.items[i].toString().trim().length > 0 &&
widget.items[i].toString().trim().toUpperCase()[0] ==
_text.toString().toUpperCase()[0])
_animationcounter++;
_scrollController.animateTo(i * _itemsizeheight,
duration: new Duration(milliseconds: 500),
curve: Curves.ease) .then((x) => _animationcounter--);
break;
现在只需将滚动条的代码包围在onscrolllistview
中
if (_animationcounter == 0) /*...your code...*/
PS
您需要照顾好您_offsetContainer
,以免越界。
你可以这样举例:
if ((_offsetContainer + details.delta.dy) >= 0 &&
(_offsetContainer + details.delta.dy) <=
(context.size.height - _heightscroller))
_offsetContainer += details.delta.dy;
这个解决方案可能可以优化(不发送多个动画,添加 var 减少计算)。你可以在这里找到一个完整的实现: AtoZscrollflutter
【讨论】:
【参考方案3】:你可以尝试做这样的事情:
Material(
child: ListView.builder(
itemCount: alphabet.length,
itemBuilder: (BuildContext context, int index)
var letterHeight = (SizeConfig.safeBlockVertical * 100) / 33;
return GestureDetector(
onVerticalDragUpdate: (DragUpdateDetails detail)
setState(()
currentPosition += detail.delta.dy;
);
,
onVerticalDragEnd: (DragEndDetails detail)
setState(()
int letters = currentPosition > 0
? ((currentPosition + letterHeight) / letterHeight)
.round()
: ((currentPosition - letterHeight) / letterHeight)
.round();
if (index + letters < alphabet.length)
index += letters;
else
index = alphabet.length;
currentPosition = 0;
currentLetter = alphabet[index];
);
,
child: InkWell(
onTap: ()
setState(()
currentLetter = alphabet[index];
);
,
child: Container(
height: letterHeight,
child: Center(
child: Text('$alphabet[index]'),
),
),
),
);
,
),
)
【讨论】:
以上是关于颤振列表视图字母索引的主要内容,如果未能解决你的问题,请参考以下文章