前言
最近做股票软件鸿蒙版本的适配,K线趋势图的手势交互上遇到了问题,这里记录下~
功能需求:
实现k线趋势图滑动及fling的效果
思路:
1. 借鉴Flutter版本的思路,在K线趋势图上面叠加一个Scroll布局,使用系统提供给我们的Scroller来计算手势滑动及fling效果。
2. 监听滑动手势PanGesture来处理,fling的惯性滑动效果需要自己模拟计算。
Scroll(this.mScroller) {
Text('').width('100%')
}
.onAreaChange((oldValue: Area, newValue: Area)=>{
this.mScroller.scrollEdge(Edge.End)
})
.height('100%')
.width(this.getTotalKLineWidth() + 200)
.scrollable(ScrollDirection.Horizontal)
.scrollBar(BarState.On)
.friction(0.5)
.onScroll((xOffset, yOffset)=>{
let result: boolean = this.mGestureHelper.scroll(this.mScroller.currentOffset().xOffset, this.getTotalKLineWidth());
if (result) {
this.onDraw();
}
})
.gesture(GestureGroup(GestureMode.Parallel,
LongPressGesture()
.onAction((event?: GestureEvent) => {
if (!this.mCanHorizontalScroll) {
this.mCanHorizontalScroll = true;
}
this.setCrossState(UPMarketUIGestureHelper.CROSS_STATE_SHOW);
this.mGestureHelper.updateCrossPoint(event?.fingerList[0].localX, event?.fingerList[0].localY);
this.onDraw();
})
.onActionEnd((event?: GestureEvent) => {
this.setCrossState(UPMarketUIGestureHelper.CROSS_STATE_NORMAL);
this.onDraw();
})
.onActionCancel((event?: GestureEvent) => {
this.setCrossState(UPMarketUIGestureHelper.CROSS_STATE_NORMAL);
this.onDraw();
})
), GestureMask.Normal)
由于k线趋势图初始位置是展示最新的k线,然而Scroller不能设置初始位置,尝试在onAreaChange
中滑动到最后,但是会有动画效果,所以这个思路实现不了。
使用平移手势接口:
.gesture(GestureGroup(GestureMode.Parallel,
PanGesture({ direction: this.mCanHorizontalScroll ? PanDirection.All : PanDirection.Horizontal, distance: 1})
.onActionStart(() => {
if (!this.mIsLongPressed) {
this.mGestureHelper.startScroll();
}
})
.onActionEnd(() => {
this.mGestureHelper.stopScroll();
this.onDraw();
})
.onActionUpdate((event?: GestureEvent) => {
if (event) {
if (this.mIsLongPressed) {
let reallyOffsetX: number = event.offsetX - this.mLastOffsetX;
let reallyOffsetY: number = event.offsetY - this.mLastOffsetY;
this.mLastOffsetX = event.offsetX;
this.mLastOffsetY = event.offsetY;
this.mCrossTouchPoint.offset(reallyOffsetX, reallyOffsetY);
this.mCrossTouchPoint.y = Math.max(this.mMainRenderTitleHeight + 1, this.mCrossTouchPoint.y);
this.mCrossTouchPoint.y = Math.min(this.totalHeight - 1, this.mCrossTouchPoint.y);
this.mGestureHelper.updateCrossPoint(this.mCrossTouchPoint.x, this.mCrossTouchPoint.y);
this.onDraw();
} else {
if (this.mGestureHelper.scroll(event.offsetX, this.totalWidth)) {
this.onDraw();
}
}
}
}),
LongPressGesture()
.onAction((event?: GestureEvent) => {
if (!this.mCanHorizontalScroll) {
this.mCanHorizontalScroll = true;
}
this.setCrossState(UPMarketUIGestureHelper.CROSS_STATE_SHOW);
this.mCrossTouchPoint.set(event?.fingerList[0].localX, event?.fingerList[0].localY);
this.mGestureHelper.updateCrossPoint(this.mCrossTouchPoint.x, this.mCrossTouchPoint.y);
this.onDraw();
})
.onActionEnd((event?: GestureEvent) => {
this.setCrossState(UPMarketUIGestureHelper.CROSS_STATE_NORMAL);
this.onDraw();
})
.onActionCancel((event?: GestureEvent) => {
this.setCrossState(UPMarketUIGestureHelper.CROSS_STATE_NORMAL);
this.onDraw();
}),
PinchGesture()
.onActionStart(() => {
this.mGestureHelper.startScale();
})
.onActionUpdate((event) => {
console.log("UPMarketUISDK PinchGesture scale: " + event.scale);
if(this.mGestureHelper.scale(event.scale)) {
this.onDraw();
}
})
), GestureMask.Normal)
使用PanGesture也可以实现滑动效果,但是松手惯性滑动需要自己计算。