How to zoom chart with respect to pinch gesture orientation
You can zoom the chart independently on the orientation of pinch gesture using the ZoomMode property and IOnTouchListener interface. If you have the pinch gesture horizontally, the chart will be zoomed on the x-axis. If you have the pinch gesture vertically, the chart will be zoomed on the y-axis. Else, if the pinching position is diagonal, the chart will be zoomed on both the x and y-axes.
The following steps explain how to enable the pinch gesture zooming independently on the orientation of pinch gesture:
Step 1: Create a custom chart class inherited from SfChart and IOnTouchListener.
Step 2: Hook the Behaviors CollectionChanged event to get the ZoomPanBehavior.
Step 3: Access the root layout of chart, and set the touch listener using the GetChildAt and SetOnTouchListener methods.
Step 4: Implement the OnTouch interface method to get the touch positions of pinching, and set the ZoomMode value based on pinching.
Step 5: Use the custom chart class instead of SfChart in MainActivity.cs.
C#:
public class ChartExt : SfChart, IOnTouchListener
{
ChartZoomPanBehavior chartZoomPanBehavior;
public ChartExt(Context context) : base(context)
{
GetChildAt(0).SetOnTouchListener(this);
Behaviors.CollectionChanged += Behaviors_CollectionChanged;
}
private void Behaviors_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if(e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
ChartBehavior behavior = e.NewItems[0] as ChartBehavior;
if (behavior is ChartZoomPanBehavior)
{
chartZoomPanBehavior = behavior as ChartZoomPanBehavior;
}
}
else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
ChartBehavior behavior = e.OldItems[0] as ChartBehavior;
if (behavior is ChartZoomPanBehavior)
{
chartZoomPanBehavior = null;
}
}
}
bool needToValidate = true;
public bool OnTouch(View v, MotionEvent e)
{
if (e.Action == MotionEventActions.Up)
{
needToValidate = true;
}
if (e.PointerCount == 2 && needToValidate && chartZoomPanBehavior != null)
{
int pointer1Index = e.FindPointerIndex(0);
int pointer2Index = e.FindPointerIndex(1);
double radians = Math.Atan2(e.GetX(pointer2Index) - e.GetX(pointer1Index), -(e.GetY(pointer2Index) - e.GetY(pointer1Index)));
radians = radians < 0 ? Math.Abs(radians) : 2 * Math.PI - radians;
var angle = radians * (180 / Math.PI);
//Diagonal zooming
if ((angle > 20 && angle < 70) || (angle > 110 && angle < 160) || (angle > 200 && angle < 250) || (angle > 290 && angle < 340))
{
chartZoomPanBehavior.ZoomMode = ZoomMode.Xy;
}
else if (Math.Abs(e.GetX(pointer1Index) - e.GetX(pointer2Index)) > Math.Abs(e.GetY(pointer1Index) - e.GetY(pointer2Index)))
{
//Horizontal zooming
chartZoomPanBehavior.ZoomMode = ZoomMode.X;
}
else if (Math.Abs(e.GetY(pointer1Index) - e.GetY(pointer2Index)) > Math.Abs(e.GetX(pointer1Index) - e.GetX(pointer2Index)))
{
//Vertical zooming
chartZoomPanBehavior.ZoomMode = ZoomMode.Y;
}
needToValidate = false;
}
return base.OnTouchEvent(e);
}
}