[英]How to add zoomin-zoomout functionalities with mouse events for the image in WPF in xamarin.froms
我正在嘗試使用xamarin.forms在WPF中使用圖像查看器,但沒有找到可啟動的縮放功能。 我只能在Xamarin中獲得WPF或Android。 表單,但找不到WPF與xamarin.forms的組合。 請幫助我實現這一目標。
編輯
我創建了另一個視圖,並能夠使用兩個按鈕進行放大和縮小。
<ContentPage.Content>
<ScrollView>
<StackLayout>
<Image x:Name="ImageToDisplay"
HorizontalOptions="Center"
VerticalOptions="Center"
Aspect="AspectFill" >
</Image>
<StackLayout Orientation="Horizontal" Grid.Row="1" HorizontalOptions="CenterAndExpand">
<Button Text="ZoomOut" Clicked="ZoomOut"/>
<Button Text="ZoomIn" Clicked="ZoomIn"/>
</StackLayout>
</StackLayout>
</ScrollView>
</ContentPage.Content>
private void ZoomIn(object sender, EventArgs e)
{
var currentScale = ImageToDisplay.Scale;
if(currentScale>=1 && currentScale < 5)
{
ImageToDisplay.Scale = currentScale + 0.25;
}
}
private void ZoomOut(object sender, EventArgs e)
{
var currentScale = ImageToDisplay.Scale;
if (currentScale >= 1 && currentScale < 5)
{
ImageToDisplay.Scale = currentScale - 0.25;
}
}
但是在這里,當圖像為“放大”時,圖像的其余部分不可見。 滾動視圖中的圖像未滾動。
您可以自定義Image
Behaviors
來實現此功能。
創建一個自定義的行為類MultiTouchBehavior.cs :
public class MultiTouchBehavior : Behavior<View>
{
#region Fields
private double _currentScale = 1, _startScale = 1, _xOffset, _yOffset;
private PinchGestureRecognizer _pinchGestureRecognizer;
private PanGestureRecognizer _panGestureRecognizer;
private ContentView _parent;
private View _associatedObject;
#endregion
/// <summary>
/// Occurs when BindingContext is changed: used to initialise the Gesture Recognizers.
/// </summary>
/// <param name="sender">The sender object.</param>
/// <param name="e">The event parameters.</param>
private void AssociatedObjectBindingContextChanged(object sender, EventArgs e)
{
_parent = _associatedObject.Parent as ContentView;
_parent?.GestureRecognizers.Remove(_panGestureRecognizer);
_parent?.GestureRecognizers.Add(_panGestureRecognizer);
_parent?.GestureRecognizers.Remove(_pinchGestureRecognizer);
_parent?.GestureRecognizers.Add(_pinchGestureRecognizer);
}
/// <summary>
/// Cleanup the events.
/// </summary>
private void CleanupEvents()
{
_pinchGestureRecognizer.PinchUpdated -= OnPinchUpdated;
_panGestureRecognizer.PanUpdated -= OnPanUpdated;
_associatedObject.BindingContextChanged -= AssociatedObjectBindingContextChanged;
}
/// <summary>
/// Initialise the events.
/// </summary>
private void InitializeEvents()
{
CleanupEvents();
_pinchGestureRecognizer.PinchUpdated += OnPinchUpdated;
_panGestureRecognizer.PanUpdated += OnPanUpdated;
_associatedObject.BindingContextChanged += AssociatedObjectBindingContextChanged;
}
/// <summary>
/// Initialise the Gesture Recognizers.
/// </summary>
private void InitialiseRecognizers()
{
_pinchGestureRecognizer = new PinchGestureRecognizer();
_panGestureRecognizer = new PanGestureRecognizer();
}
/// <summary>
/// Occurs when Behavior is attached to the View: initialises fields, properties and events.
/// </summary>
protected override void OnAttachedTo(View associatedObject)
{
InitialiseRecognizers();
_associatedObject = associatedObject;
InitializeEvents();
base.OnAttachedTo(associatedObject);
}
/// <summary>
/// Occurs when Behavior is detached from the View: cleanup fields, properties and events.
/// </summary>
protected override void OnDetachingFrom(View associatedObject)
{
CleanupEvents();
_parent = null;
_pinchGestureRecognizer = null;
_panGestureRecognizer = null;
_associatedObject = null;
base.OnDetachingFrom(associatedObject);
}
/// <summary>
/// Implements Pan/Translate.
/// </summary>
/// <param name="sender">The sender object.</param>
/// <param name="e">The event parameters.</param>
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
if (_parent == null)
{
return;
}
if (!IsTranslateEnabled)
{
return;
}
switch (e.StatusType)
{
case GestureStatus.Running:
_parent.Content.TranslationX = _xOffset + e.TotalX;
_parent.Content.TranslationY = _yOffset + e.TotalY;
break;
case GestureStatus.Completed:
_xOffset = _parent.Content.TranslationX;
_yOffset = _parent.Content.TranslationY;
break;
}
}
/// <summary>
/// Implements Pinch/Zoom.
/// </summary>
/// <param name="sender">The sender object.</param>
/// <param name="e">The event parameters.</param>
private void OnPinchUpdated(object sender, PinchGestureUpdatedEventArgs e)
{
if (_parent == null)
{
return;
}
if (!IsScaleEnabled)
{
return;
}
switch (e.Status)
{
case GestureStatus.Started:
_startScale = _parent.Content.Scale;
_parent.Content.AnchorX = 0;
_parent.Content.AnchorY = 0;
break;
case GestureStatus.Running:
_currentScale += (e.Scale - 1) * _startScale;
_currentScale = Math.Max(1, _currentScale);
var renderedX = _parent.Content.X + _xOffset;
var deltaX = renderedX / _parent.Width;
var deltaWidth = _parent.Width / (_parent.Content.Width * _startScale);
var originX = (e.ScaleOrigin.X - deltaX) * deltaWidth;
var renderedY = _parent.Content.Y + _yOffset;
var deltaY = renderedY / _parent.Height;
var deltaHeight = _parent.Height / (_parent.Content.Height * _startScale);
var originY = (e.ScaleOrigin.Y - deltaY) * deltaHeight;
var targetX = _xOffset - (originX * _parent.Content.Width) * (_currentScale - _startScale);
var targetY = _yOffset - (originY * _parent.Content.Height) * (_currentScale - _startScale);
_parent.Content.TranslationX = targetX.Clamp(-_parent.Content.Width * (_currentScale - 1), 0);
_parent.Content.TranslationY = targetY.Clamp(-_parent.Content.Height * (_currentScale - 1), 0);
_parent.Content.Scale = _currentScale;
break;
case GestureStatus.Completed:
_xOffset = _parent.Content.TranslationX;
_yOffset = _parent.Content.TranslationY;
break;
}
}
/// <summary>
/// Initialize the behavior when OnAppearing is executed.
/// </summary>
public void OnAppearing()
{
AssociatedObjectBindingContextChanged(_associatedObject, null);
}
#region IsScaleEnabled property
/// <summary>
/// Identifies the <see cref="IsScaleEnabledProperty" /> property.
/// </summary>
public static readonly BindableProperty IsScaleEnabledProperty =
BindableProperty.Create<MultiTouchBehavior, bool>(w => w.IsScaleEnabled, default(bool));
/// <summary>
/// Identifies the <see cref="IsScaleEnabled" /> dependency / bindable property.
/// </summary>
public bool IsScaleEnabled
{
get { return (bool)GetValue(IsScaleEnabledProperty); }
set { SetValue(IsScaleEnabledProperty, value); }
}
#endregion
#region IsTranslateEnabled property
/// <summary>
/// Identifies the <see cref="IsTranslateEnabledProperty" /> property.
/// </summary>
public static readonly BindableProperty IsTranslateEnabledProperty =
BindableProperty.Create<MultiTouchBehavior, bool>(w => w.IsTranslateEnabled, default(bool));
/// <summary>
/// Identifies the <see cref="IsTranslateEnabled" /> dependency / bindable property.
/// </summary>
public bool IsTranslateEnabled
{
get { return (bool)GetValue(IsTranslateEnabledProperty); }
set { SetValue(IsTranslateEnabledProperty, value); }
}
#endregion
}
添加在MultiTouchBehavior.cs中使用的DoubleExtensions.cs :
public static class DoubleExtensions
{
public static double Clamp(this double self, double min, double max)
{
return Math.Min(max, Math.Max(self, min));
}
}
最后,在Xmal中 ,在此處添加兩個Button
:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:behaviors="clr-namespace:MultiTouch.Behaviors"
x:Class="MultiTouch.MainPage">
<StackLayout>
<ContentView >
<Image x:Name="MyImage" Source="desert.jpg">
<Image.Behaviors>
<behaviors:MultiTouchBehavior IsScaleEnabled="True" IsTranslateEnabled="True" />
</Image.Behaviors>
</Image>
</ContentView>
<Button Text="ZoomIn" Clicked="ZoomIn_Clicked"/>
<Button Text="ZoomOut" Clicked="ZoomOut_Clicked"/>
</StackLayout>
</ContentPage>
按鈕方式:
private void ZoomIn_Clicked(object sender, System.EventArgs e)
{
var currentScale = MyImage.Scale;
if (currentScale >= 1 && currentScale < 5)
{
MyImage.Scale = currentScale + 0.25;
}
}
private void ZoomOut_Clicked(object sender, System.EventArgs e)
{
var currentScale = MyImage.Scale;
if (currentScale >= 1 && currentScale < 5)
{
MyImage.Scale = currentScale - 0.25;
}
}
這是示例鏈接 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.