**首先效果上图:
注意开头的时候,动态增加了4条数据,柱子和线都变了,如果你们用websocket或者tcp传输不间断数据,就动态了。 now,let‘s go。
分为三节:
思想:利用GestureDetector和RawGestureDetector,处理一下滑动冲突,笔者再发现缩放时,取消滑动事件。
这里时滑动,当缩放开始时allowDrag = false;阻止两者一起动。
onHorizontalDragUpdate: allowDrag ? _dragUpdate : null,
onHorizontalDragStart: _dragStart,
onHorizontalDragEnd: _dragEnd,
_dragUpdate(DragUpdateDetails details) {
//此处的 *1为系数,可以改变这个值来改变offsetNum, 即可当成滑动阻尼来用。
int offsetNum = (details.delta.dx * 1).toInt();
//offsetNum只让慢慢改变
if(offsetNum <0 && offsetNum> -1){
offsetNum = -1;
}else if(offsetNum >0 && offsetNum< 1){
offsetNum = 1;
}
//用来确定显示的数据集,通过_subList()
start = start - offsetNum;
end = end - offsetNum;
//保证不越界
if (end >= widget.dataList.length) {
end = widget.dataList.length;
start = end - lastNum;
}
if (start <= widget.maxPreDay) {
start = widget.maxPreDay;
end = start + lastNum;
}
//计算出出现在屏幕上的数据集
_data = _subList(start, end: end);
setState(() {});
}
从整个数据中通过start和end,抽取一部分到屏幕上
//获取段落
List _subList(int start, {int end}) {
List result;
if (end != null) {
result = widget.dataList.sublist(start, end);
} else {
result = widget.dataList.sublist(start);
}
return result;
}
这里需要用自定义的Recognizer,通过重写rejectGesture方法来改变冲突时的决定 此处,当该手势竞争失败时,强行执行竞争成功的方法,不过此时两个手势都会执行,我们会在update中禁止其中之一
@override
void rejectGesture(int pointer) {
//当battle失败后执行的语句
acceptGesture(pointer);//强行执行竞争成功的方法,
}
RawGestureDetector(
gestures: {
ScaleEveryGestureRecognizer:GestureRecognizerFactoryWithHandlers<ScaleEveryGestureRecognizer>(
() =>ScaleEveryGestureRecognizer(),
(ScaleEveryGestureRecognizer instance){
instance.onUpdate = (ScaleUpdateDetails de){
if(de.horizontalScale != 1.0){
_scaleUpload(de);
};
};
instance.onStart = handleScaleStart;
instance.onEnd = _scaleEnd;
}
//缩放时的事件
_scaleUpload(ScaleUpdateDetails details) {
allowDrag = false;//禁止滑动事件
//if(details.horizontalScale != 1.0){
double ho = (details.horizontalScale - 1).abs();
double ve = (details.verticalScale - 1).abs();
if (isFirstScaleFrame) {
isFirstScaleFrame = false;
return;
}
double scale = details.horizontalScale;
//决定当前显示k柱总数
currentNum = ((1 / scale) * lastNum).floor();
currentNum = (currentNum * widget.scaleDamp).toInt();
currentNum = clamp(widget.minNum, widget.dataList.length - widget.maxPreDay, currentNum);
//改变起始值和结束值
double center = (end + start)/2;//保证缩放时中心不变, 当你发现中心改变了的时候,请再观察是否已经到了终点
//加0.5保证均衡性,要是不加会发现缩放时一边倒
end = (center + currentNum/2 +0.5).toInt();
start = (center - currentNum/2).toInt();
if (end >= widget.dataList.length) {
end = widget.dataList.length;
start = end - currentNum;
}
if (start <= widget.maxPreDay) {
start = widget.maxPreDay;
end = start + currentNum;
}
//重新取值
_data = _subList(start, end: end);
setState(() {});
}
本节核心就这些,详情看源码。如果觉得可以一看,请看下节。