通常,我们会在App首页的滚动控件上放一个ImageListViewer

滚动控件可以是ScollBoxListBoxListView

它们都具有上下滑动的功能,

ImageListViewer具有左右切换图片的功能,

这样一来,当我在ImageListViewer左右切换图片时,

很容易造成滚动控件的上下滑动,

十分影响用户体验,

 

正确的效果应该是,

我在ImageListViewer上垂直切换时滚动控件才会上下滑动,

其他情况下,ImageListViewer都应该能切换图片,

 

如何解决这种手势冲突呢?

 

所有滚动控件都是从ScrollControl继承的,

ScrollControl有两个手势管理组件,

VertControlGestureManagerHorzControlGestureManager

VertControlGestureManager用来处理上下滑动,上下惯性滚动等,

我们需要把VertControlGestureManager.IsNeedDecideFirstGestureKind设置为True

IsNeedDecideFirstGestureKindTrue了之后,

表示每次开始手势滑动ScrollControl时,都需要先滑动一段距离,

然后VertControlGestureManager判断出滑动的方向为上下垂直方向之后,

才响应上下滚动,

ScrollControl上面放了ImageListViewer之后,

只需要手势滑动在ImageListViewer上时需要判断上下垂直方向,

ImageListViewer之外的地方则不需要判断,

如下箭头所示:

那就要编写VertControlGestureManager.OnPrepareDecidedFirstGestureKind事件,

这个事件会传入鼠标滑动所在的位置,

如果鼠标滑动位置在ImageListViewer中,

那么需要判断上下垂直方向,

如果不在ImageListViewer中,那么不需要判断方向,

ScrollBox处理的代码如下:

procedure TFrameHome.DoScrollBoxVertManagerPrepareDecidedFirstGestureKind(

  Sender: TObject; AMouseMoveX, AMouseMoveY: Double;

  var AIsDecidedFirstGestureKind: Boolean;

  var ADecidedFirstGestureKind: TGestureKind);

var

  APlayerOriginPoint:TPointF;

  AFirstItemRect:TRectF;

begin

  //传给ScrollBox的是相对窗体的绝对坐标

  //广告轮播Item的绘制区域

  APlayerOriginPoint:=PointF(0,0);

  APlayerOriginPoint:=imgPlayer.LocalToAbsolute(APlayerOriginPoint);

  AFirstItemRect:=RectF(APlayerOriginPoint.X,APlayerOriginPoint.Y,

                        APlayerOriginPoint.X+Self.imgPlayer.Width,

                        APlayerOriginPoint.Y+Self.imgPlayer.Height

                        );

  if PtInRect(AFirstItemRect,PointF(AMouseMoveX,AMouseMoveY)) then

  begin

    //在广告轮播控件内,那么要检查初始手势方向

  end

  else

  begin

    //不在在广告轮播控件内,那么随意滑动

    //AIsDecidedFirstGestureKind表示我已经确定好方向了,不需要再判断了

    //ADecidedFirstGestureKind表示判断好的方向

    AIsDecidedFirstGestureKind:=True;

    ADecidedFirstGestureKind:=TGestureKind.gmkVertical;

  end;

end;

 

初始设置代码如下:

  Self.sbClient.Prop.VertControlGestureManager.IsNeedDecideFirstGestureKind:=True;

  Self.sbClient.Prop.VertControlGestureManager.OnPrepareDecidedFirstGestureKind:=

            Self.DoScrollBoxVertManagerPrepareDecidedFirstGestureKind;

 

 

ListBox处理的代码如下:

procedure TFrameShop.DoListBoxVertManagerPrepareDecidedFirstGestureKind(

  Sender: TObject; AMouseMoveX, AMouseMoveY: Double;

  var AIsDecidedFirstGestureKind: Boolean;

  var ADecidedFirstGestureKind: TGestureKind);

var

  AFirstItemRect:TRectF;

begin

  //广告轮播Item的绘制区域

  AFirstItemRect:=Self.lbHome.Prop.Items[0].ItemDrawRect;

  if PtInRect(AFirstItemRect,PointF(AMouseMoveX,AMouseMoveY)) then

  begin

      //在广告轮播控件内,那么要检查初始手势方向

  end

  else

  begin

      //不在在广告轮播控件内,那么随意滑动

      AIsDecidedFirstGestureKind:=True;

      ADecidedFirstGestureKind:=TGestureKind.gmkVertical;

  end;

end;

 

初始设置代码如下:

  Self.lbHome.Prop.VertControlGestureManager.IsNeedDecideFirstGestureKind:=True;

  Self.lbHome.Prop.VertControlGestureManager.OnPrepareDecidedFirstGestureKind:=

    Self.DoListBoxVertManagerPrepareDecidedFirstGestureKind;