I have a screen with multiple chart surfaces stacked on top of each other within a ScrollView. I can’t use a single chart surface because each of the charts is combined with other types of views to display extra information about the data in the charts.
I have a few issues I’m trying to solve:
-
Each of the charts uses the same x-axis range. When a user pinches to zoom or drags to pan on a chart, I want all the charts to be synchronized to zoom and pan at the same time. How can I do this?
-
Because the charts are embedded in a ScrollView, when I use the following modifiers it is very difficult to smoothly zoom and pan without the ScrollView being activated to scroll up and down. How can I make it so that the ScrollView is deactivated from moving while the user is attempting to zoom or pan a chart
surface.chartModifiers.add(
XAxisDragModifier().apply {
dragMode = AxisDragModifierBase.AxisDragMode.Pan
minTouchArea = 1000.0f
}
)
surface.chartModifiers.add(
PinchZoomModifier().apply {
direction = Direction2D.XDirection
}
)
- Marcela Guerra asked 1 year ago
- You must login to post comments
To satisfy point 2 above I used a NestScrollView in combination with some customized Modifiers (code snippets below).
Still trying to figure out point 1 above though (synchronizing the panning and zooming of multiple surfaces
interface GestureCallback {
fun onPerformingChartGesture()
}
override fun onPerformingChartGesture() {
binding.scrollView.requestDisallowInterceptTouchEvent(true)
}
private class CustomPinchZoomModifier(val gestureCallback: GestureCallback) : PinchZoomModifier() {
override fun onScale(detector: ScaleGestureDetector): Boolean {
gestureCallback.onPerformingChartGesture()
return super.onScale(detector)
}
}
private class CustomXAxisDragModifier(val gestureCallback: GestureCallback) : XAxisDragModifier() {
override fun performPan(xDelta: Float, yDelta: Float, isSecondHalf: Boolean, axis: IAxis?) {
gestureCallback.onPerformingChartGesture()
super.performPan(xDelta, yDelta, isSecondHalf, axis)
}
}
surface.chartModifiers.add(
CustomXAxisDragModifier(callback).apply {
dragMode = AxisDragModifierBase.AxisDragMode.Pan
minTouchArea = 1000.0f
clipModeX = ClipMode.ClipAtExtents
}
)
surface.chartModifiers.add(
CustomPinchZoomModifier(callback).apply {
direction = Direction2D.XDirection
}
)
- Marcela Guerra answered 1 year ago
- last edited 1 year ago
- You must login to post comments
Found a solution for synchronizing zooming and panning across multiple chart surfaces. The solution was to intercept the updates that happen when the modifiers pan and zoom and to share those updates with all the other surfaces. Intercepting the values involved overriding the following functions:
private class CustomPinchZoomModifier(
val gestureCallback: GestureCallback
) : PinchZoomModifier() {
override fun performZoom(point: PointF, xValue: Double, yValue: Double) {
gestureCallback.onPerformingZoom(point, xValue, yValue)
}
fun zoom(point: PointF, xValue: Double, yValue: Double) {
super.performZoom(point, xValue, yValue)
}
}
private class CustomXAxisDragModifier(
val gestureCallback: GestureCallback
) : XAxisDragModifier() {
override fun performPan(xDelta: Float, yDelta: Float, isSecondHalf: Boolean, axis: IAxis) {
gestureCallback.onPerformingPan(xDelta, yDelta, isSecondHalf)
}
fun pan(xDelta: Float, yDelta: Float, isSecondHalf: Boolean) {
super.performPan(xDelta, yDelta, isSecondHalf, xAxis)
}
}
fun performZoom(point: PointF, xValue: Double, yValue: Double) {
zoomModifier?.zoom(point, xValue, yValue)
}
fun performPan(xDelta: Float, yDelta: Float, isSecondHalf: Boolean) {
panModifier?.pan(xDelta, yDelta, isSecondHalf)
}
- Marcela Guerra answered 1 year ago
- last edited 1 year ago
- You must login to post comments
Please login first to submit.