Xamarin.forms 如何实现收缩缩放&;在SKCanvasView上滑动?
我正在使用xamarin表单开发图像查看器。我的源图像是无限大的,比我的视口大得多。所以我使用SKCanvasView控件逐部分绘制,这样我就可以浏览图像了 我可以通过SKCanvasView上提供的触摸事件获得触摸点。在这里,我能够检测到双击。滑动和平移 我无法决定何时向上/向下滑动需要向上/向下移动多少图像Xamarin.forms 如何实现收缩缩放&;在SKCanvasView上滑动?,xamarin.forms,skiasharp,Xamarin.forms,Skiasharp,我正在使用xamarin表单开发图像查看器。我的源图像是无限大的,比我的视口大得多。所以我使用SKCanvasView控件逐部分绘制,这样我就可以浏览图像了 我可以通过SKCanvasView上提供的触摸事件获得触摸点。在这里,我能够检测到双击。滑动和平移 我无法决定何时向上/向下滑动需要向上/向下移动多少图像 最初,我尝试将SKCanvasView放置在ScrollView控件的顶部,并使用绘制SKCanvas时使用的滚动位置值。这里的滚动和打印工作完美。但在这里,捏缩缩放不起作用,因为捏缩手
最初,我尝试将SKCanvasView放置在ScrollView控件的顶部,并使用绘制SKCanvas时使用的滚动位置值。这里的滚动和打印工作完美。但在这里,捏缩缩放不起作用,因为捏缩手势事件没有触发,而是滚动。我曾经为我的一个朋友为SKCanvas做过类似的事情,尽管我个人从未使用过Skia 在任何情况下,它都有捏、平移和点击缩放事件,您可以根据需要随意进行任何更改:
public class CustomSKCanvas : SKCanvasView
{
private const double MIN_SCALE = 1;
private const double MAX_SCALE = 4;
private const double OVERSHOOT = 0.15;
private double StartScale, LastScale;
private double StartX, StartY;
public CustomSKCanvas()
{
var pinch = new PinchGestureRecognizer();
pinch.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add(pinch);
var pan = new PanGestureRecognizer();
pan.PanUpdated += OnPanUpdated;
GestureRecognizers.Add(pan);
var tap = new TapGestureRecognizer { NumberOfTapsRequired = 2 };
tap.Tapped += OnTapped;
GestureRecognizers.Add(tap);
Scale = MIN_SCALE;
TranslationX = TranslationY = 0;
AnchorX = AnchorY = 0;
}
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
Scale = MIN_SCALE;
TranslationX = TranslationY = 0;
AnchorX = AnchorY = 0;
return base.OnMeasure(widthConstraint, heightConstraint);
}
private void OnTapped(object sender, EventArgs e)
{
if (Scale > MIN_SCALE)
{
this.ScaleTo(MIN_SCALE, 250, Easing.CubicInOut);
this.TranslateTo(0, 0, 250, Easing.CubicInOut);
}
else
{
AnchorX = AnchorY = 0.5; //TODO tapped position
this.ScaleTo(MAX_SCALE, 250, Easing.CubicInOut);
}
}
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
switch (e.StatusType)
{
case GestureStatus.Started:
StartX = (1 - AnchorX) * Width;
StartY = (1 - AnchorY) * Height;
break;
case GestureStatus.Running:
AnchorX = Clamp(1 - (StartX + e.TotalX) / Width, 0, 1);
AnchorY = Clamp(1 - (StartY + e.TotalY) / Height, 0, 1);
break;
}
}
private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
switch (e.Status)
{
case GestureStatus.Started:
LastScale = e.Scale;
StartScale = Scale;
AnchorX = e.ScaleOrigin.X;
AnchorY = e.ScaleOrigin.Y;
break;
case GestureStatus.Running:
if (e.Scale < 0 || Math.Abs(LastScale - e.Scale) > (LastScale * 1.3) - LastScale)
{ return; }
LastScale = e.Scale;
var current = Scale + (e.Scale - 1) * StartScale;
Scale = Clamp(current, MIN_SCALE * (1 - OVERSHOOT), MAX_SCALE * (1 + OVERSHOOT));
break;
case GestureStatus.Completed:
if (Scale > MAX_SCALE)
this.ScaleTo(MAX_SCALE, 250, Easing.SpringOut);
else if (Scale < MIN_SCALE)
this.ScaleTo(MIN_SCALE, 250, Easing.SpringOut);
break;
}
}
private T Clamp<T>(T value, T minimum, T maximum) where T : IComparable
{
if (value.CompareTo(minimum) < 0)
return minimum;
else if (value.CompareTo(maximum) > 0)
return maximum;
else
return value;
}
}
公共类CustomSKCanvas:SKCanvasView
{
私人常数双最小刻度=1;
私人常数双最大刻度=4;
专用常数双超调=0.15;
私人双星标度,最新标度;
私人双星;
公共定制画布()
{
var pinch=新的PinchGestureRecognitor();
pinch.PinchUpdated+=OnPinchUpdated;
手势识别器。添加(捏);
var pan=新的PangestureRecognitor();
pan.PanUpdated+=OnPanUpdated;
手势识别器。添加(平移);
var tap=新的TapGestureRecognitor{NumberOfTapsRequired=2};
抽头。抽头+=无抽头;
手势识别器。添加(轻触);
刻度=最小刻度;
TranslationX=TranslationY=0;
AnchorX=AnchorY=0;
}
测量时受保护的覆盖大小请求(双宽度约束、双高度约束)
{
刻度=最小刻度;
TranslationX=TranslationY=0;
AnchorX=AnchorY=0;
返回base.OnMeasure(宽度约束、高度约束);
}
私有void OnTapped(对象发送方,事件参数e)
{
如果(比例>最小比例)
{
这个.ScaleTo(最小刻度,250,放松.CubicInOut);
这个.TranslateTo(0,0250,Easing.CubicInOut);
}
其他的
{
AnchorX=AnchorY=0.5;//TODO分接位置
此.ScaleTo(最大刻度,250,宽松.CubicInOut);
}
}
私有void OnPanUpdated(对象发送方,PanUpdatedEventArgs e)
{
开关(如状态类型)
{
案例手势状态。已启动:
StartX=(1-锚点)*宽度;
星形=(1-锚定)*高度;
打破
案例手势状态。正在运行:
锚具=夹具(1-(StartX+e.TotalX)/宽度,0,1);
锚定=夹具(1-(起点+e.TotalY)/高度,0,1);
打破
}
}
PinchUpdated上的私有void(对象发送方,PinchEstureUpdatedEventArgs e)
{
开关(如状态)
{
案例手势状态。已启动:
LastScale=e.刻度;
StartScale=比例;
AnchorX=e.ScaleOrigin.X;
AnchorY=e.ScaleOrigin.Y;
打破
案例手势状态。正在运行:
如果(e.Scale<0 | | Math.Abs(LastScale-e.Scale)>(LastScale*1.3)-LastScale)
{return;}
LastScale=e.刻度;
无功电流=标度+(e.标度-1)*标准标度;
刻度=钳位(电流、最小刻度*(1-超调)、最大刻度*(1+超调));
打破
案例管理状态。已完成:
如果(比例>最大比例)
这个.ScaleTo(最大刻度,250,放松.SpringOut);
else if(刻度<最小刻度)
这个.ScaleTo(MIN_SCALE,250,Easing.SpringOut);
打破
}
}
专用T形夹(T值,T最小值,T最大值),其中T:I可比较
{
如果(值比较到(最小值)<0)
返回最小值;
如果(值比较(最大值)>0)
返回最大值;
其他的
返回值;
}
}
祝你好运
如有疑问,请回复