How do you programmatically dismiss the crosshair on Android chart


#1

How do you programmatically dismiss the crosshair?  Setting CrosshairEnabled = false for the series when the crosshair is shown still leaves the chart in crosshair mode, meaning that panning the chart doesn’t work because it moves the crosshair instead.


#2

Hi

Thanks for getting in touch. A similar question was recently asked by another user and answered by a colleague - in the first instance may I ask you to please check the following post on Stack Overflow:

Whilst this question was asked with specific reference to the Xamarin bindings, the same general principle should apply and as such should help you to get started. The main difference with your specific case of course is that you wish to dismiss, rather than show the crosshair programmatically. As such you would need to create a single tap gesture, (rather than a long press) in the plot area in order to dismiss the cross hair. Again, as noted in my colleague’s response you would make use of the MotionEvent API, along with the Axis’ conversion methods (to help you convert from pixel values to data values and vice-versa) to help you achieve this.

Thanks,

Kai.


#3

Kai,

I was able to get the single touch to work, but not long press.  Do you see anything wrong with this sample in relationship to the charts or why it wouldn’t work?

I couldn’t get it to format very well, so it’s in this gist as well as below: https://gist.github.com/foresterh/9f8d011b0c2a33cc7793

|
if(enabled) |
|   | { |
|   | ChartLineSeries.CrosshairEnabled = true; |
|   | //long press to show tracking cursors, except it doesn’t work |
|   | /* |
|   | var x = _shinobiChart.PlotAreaRect.CenterX(); |
|   | var y = _shinobiChart.PlotAreaRect.CenterY(); |
|   | DispatchTouchEvent( |
|   | Android.Views.MotionEvent.Obtain( |
|   | Android.OS.SystemClock.UptimeMillis(), |
|   | Android.OS.SystemClock.UptimeMillis(), |
|   | Android.Views.MotionEventActions.Down, |
|   | x, y, default(Android.Views.MetaKeyStates))); |
|   | var touchSlop = Android.Views.ViewConfiguration.Get(this.Context).ScaledTouchSlop; |
|   | DispatchTouchEvent( |
|   | Android.Views.MotionEvent.Obtain( |
|   | Android.OS.SystemClock.UptimeMillis(), |
|   | Android.OS.SystemClock.UptimeMillis(), |
|   | Android.Views.MotionEventActions.Move, |
|   | x + touchSlop / 2, y + touchSlop / 2, default(Android.Views.MetaKeyStates))); |
|   | System.Threading.Tasks.Task.Delay((int)(Android.Views.ViewConfiguration.LongPressTimeout * 1.5)).Wait(); |
|   | DispatchTouchEvent( |
|   | Android.Views.MotionEvent.Obtain( |
|   | Android.OS.SystemClock.UptimeMillis(), |
|   | Android.OS.SystemClock.UptimeMillis(), |
|   | Android.Views.MotionEventActions.Up, |
|   | x, y, default(Android.Views.MetaKeyStates))); |
|   | */ |
|   | } |
|   | else |
|   | { |
|   | //tap to dismiss cursor |
|   | DispatchTouchEvent( |
|   | Android.Views.MotionEvent.Obtain( |
|   | Android.OS.SystemClock.UptimeMillis(), |
|   | Android.OS.SystemClock.UptimeMillis(), |
|   | Android.Views.MotionEventActions.Down, 0, 0, default(Android.Views.MetaKeyStates))); |
|   | DispatchTouchEvent( |
|   | Android.Views.MotionEvent.Obtain( |
|   | Android.OS.SystemClock.UptimeMillis(), |
|   | Android.OS.SystemClock.UptimeMillis(), |
|   | Android.Views.MotionEventActions.Up, 0, 0, default(Android.Views.MetaKeyStates))); |
|   | ChartLineSeries.CrosshairEnabled = false; |
|   | } |


#4

Hi

Thanks for posting your code. I’m glad you were able to dismiss the crosshair programmatically.

Now lets see if we can get the crosshair to show programmatically!

Looking at your code, I believe the issue is that the chain of events (in your case, press down, touch slop, release) are completing too quickly, and so the chart is not aware that a long press has taken place. Firstly, you can customize the time taken before a long press is recognized by the chart using this API:

https://www.shinobicontrols.com/docs/ShinobiControls/ShinobiChartsAndroid/1.7.2/Premium/Normal/apidocs/docs/reference/com/shinobicontrols/charts/ShinobiChart.html#setLongTouchTimeout(int)

I think you need to modify the part of your code which handles the ‘up’ gesture. Crucially I think you need to make sure that the eventTime parameter (which you pass to the obtain method of the MotionEvent class) is set to be that of the touch down gesture, plus an increment of time to denote the duration of the long press. If you modify the chart time-out duration by using the above API, then this increment simply needs to be greater than or equal to this figure. Alternatively, a common approach is to use the value returned by the following method:

http://developer.android.com/reference/android/view/ViewConfiguration.html#getLongPressTimeout()

One thing I also noticed about your code is that in each call to MotionEvent.obtain(), you pass the current time as the ‘downTime’ parameter. In my experience, when working with a chain of events, such as a long press I have always used the same value for this parameter. I am not 100% sure if this will matter but my understanding is that it tells Android the time at which (crucially) the first event in the chain was invoked. It may be worth trying this with your code, so you may want to capture the system time just before the first call to obtain(), then use this same value for the downTime parameter in each call to obtain().

Finally, for simplicity, I would start by removing your middle step concerning the touch slop.

I hope that this helps, please let us know how you get on!

Thanks,

Kai.