Can't draw annotations w/ Xamarin on Android


#1

I have some code for drawing annotations (vertical lines & text) that used to work but started throwing exceptions a few Shinobi releases ago. The exception is thrown when the code tries to set the annotation position. The exception message is “The specified child already has a parent. You must call removeView() on the child’s parent first.”.

Here’s the code that adds the annotations:

private void DrawAnnotations(NumberAxis yAxis)
        {
            // Annotations
            var distanceIntervalsInMeters = new int[] { 0, 250, 500, 1000, 2000 };
            int distanceInterval = distanceIntervalsInMeters[Model.Instance.Settings.ChartDistanceInterval];

            if (distanceInterval > 0)
            {
                Log.Debug(TAG, "Drawing annotations (interval = {0}m)", distanceInterval);

                var distanceAnnotationPosition = yAxis.DataRange.Minimum + (yAxis.DataRange.Span * 0.12);
                var splitAnnotationPosition = yAxis.DataRange.Minimum + (yAxis.DataRange.Span * 0.34);

                int numAnnotations = 0;
            
                int lastDistance = 0;
                DateTime lastTime = DateTime.MinValue;
                DateTime lastIntervalTime = DateTime.MinValue;
                AnnotationsManager manager = this.shinobiChart.AnnotationsManager;

                for (int i = 0; i < this.timeValues.Count; i++)
                {
                    var distance = this.distanceValues[i];
                    DateTime time = this.timeValues[i];

                    int nextMarker = (numAnnotations + 1) * distanceInterval;

                    if (lastDistance < nextMarker && distance >= nextMarker)
                    {
                        numAnnotations++;

                        float fraction = ((float)nextMarker - lastDistance) / ((float)distance - lastDistance);

                        DateTime interpolatedTime = time + TimeSpan.FromSeconds(fraction * (time - lastTime).TotalSeconds);

                        var lineAnnotation = manager.AddVerticalLineAnnotation(
                            DateUtils.ConvertToJavaDate(interpolatedTime),
                            2.0f,
                            this.shinobiChart.XAxis,
                            yAxis);
                        lineAnnotation.Style.BackgroundColor = Color.Red;
                        lineAnnotation.AnnotationPosition = Com.ShinobiControls.Charts.Annotation.Position.BehindData;

                        // make a text annotation for the distance
                        var distAnnotation = manager.AddTextAnnotation(
                            string.Format("{0}m", numAnnotations * distanceInterval),
                            DateUtils.ConvertToJavaDate(interpolatedTime),
                            distanceAnnotationPosition,
                            this.shinobiChart.XAxis,
                            yAxis);
                        distAnnotation.AnnotationPosition = Com.ShinobiControls.Charts.Annotation.Position.InFrontOfData;
                        distAnnotation.Style.BackgroundColor = Color.Argb(216, 255, 255, 255);
                        distAnnotation.Style.TextColor = Color.Black;

                        // make an annotation for the split
                        var thisIntervalSplit = interpolatedTime - lastIntervalTime;
                        var splitAnnotation = manager.AddTextAnnotation(
                            thisIntervalSplit.ToString("m\\:ss\\.F"),
                            DateUtils.ConvertToJavaDate(interpolatedTime),
                            splitAnnotationPosition,
                            this.shinobiChart.XAxis,
                            yAxis);
                        splitAnnotation.AnnotationPosition = Com.ShinobiControls.Charts.Annotation.Position.InFrontOfData;
                        splitAnnotation.Style.BackgroundColor = Color.Argb(216, 255, 255, 255);
                        splitAnnotation.Style.TextColor = Color.Black;

                        lastIntervalTime = interpolatedTime;
                    }

                    lastDistance = distance;
                    lastTime = time;
                }
            }
        }

Here’s the stack backtrace:

09-05 13:46:44.791  9198  9198 D ChartActivity: Drawing annotations (interval = 250m)
09-05 13:46:44.841  9198  9198 E ChartActivity: Caught an exception in DrawAnnotations: The specified child already has a parent. You must call removeView() on the child’s parent first.
09-05 13:46:44.871  9198  9198 E ChartActivity: Stack trace:   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <0x6239b9b8 + 0x00024> in <filename unknown>:0
09-05 13:46:44.871  9198  9198 E ChartActivity:   at Java.Interop.JniEnvironment+InstanceMethods.CallVoidMethod (JniObjectReference instance, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) <0x603b1b70 + 0x000af> in <filename unknown>:0
09-05 13:46:44.871  9198  9198 E ChartActivity:   at Android.Runtime.JNIEnv.CallVoidMethod (IntPtr jobject, IntPtr jmethod, Android.Runtime.JValue* parms) <0x603b1ad0 + 0x0006f> in <filename unknown>:0
09-05 13:46:44.871  9198  9198 E ChartActivity:   at Com.ShinobiControls.Charts.Annotation.SetPosition (Com.ShinobiControls.Charts.Position p0) <0x61b6b5b8 + 0x0016f> in <filename unknown>:0
09-05 13:46:44.871  9198  9198 E ChartActivity:   at Com.ShinobiControls.Charts.Annotation.set_AnnotationPosition (Com.ShinobiControls.Charts.Position value) <0x61b6b588 + 0x00027> in <filename unknown>:0
09-05 13:46:44.871  9198  9198 E ChartActivity:   at PerformancePhones.CrewNerd.ChartActivity.DrawAnnotations (Com.ShinobiControls.Charts.NumberAxis yAxis) <0x61b68ff0 + 0x00587> in <filename unknown>:0
09-05 13:46:44.871  9198  9198 E ChartActivity:   at PerformancePhones.CrewNerd.ChartActivity.RenderInterval () <0x61b61730 + 0x005c7> in <filename unknown>:0
09-05 13:46:44.871  9198  9198 E ChartActivity:   — End of managed Java.Lang.RuntimeException stack trace —
09-05 13:46:44.871  9198  9198 E ChartActivity: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child’s parent first.
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.view.ViewGroup.addViewInner(ViewGroup.java:3387)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.view.ViewGroup.addView(ViewGroup.java:3258)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.view.ViewGroup.addView(ViewGroup.java:3203)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.view.ViewGroup.addView(ViewGroup.java:3179)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.ay.a(SourceFile:383)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.AnnotationsManager.a(SourceFile:595)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.AnnotationsManager.a(SourceFile:23)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.AnnotationsManager$a.a(SourceFile:37)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.d.b(SourceFile:36)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.d.a(SourceFile:4)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.bu.b(SourceFile:57)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.bu.a(SourceFile:63)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.ce.a(SourceFile:40)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.ce.a(SourceFile:23)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.Annotation.d(SourceFile:338)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.shinobicontrols.charts.Annotation.setPosition(SourceFile:309)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at md5633312d6c16c670d01f56977ae1d9436.ChartActivity.n_onCreate(Native Method)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at md5633312d6c16c670d01f56977ae1d9436.ChartActivity.onCreate(ChartActivity.java:58)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.app.Activity.performCreate(Activity.java:5048)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2052)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2113)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.app.ActivityThread.access$700(ActivityThread.java:139)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1224)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.os.Handler.dispatchMessage(Handler.java:99)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.os.Looper.loop(Looper.java:137)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at android.app.ActivityThread.main(ActivityThread.java:4918)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at java.lang.reflect.Method.invokeNative(Native Method)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at java.lang.reflect.Method.invoke(Method.java:511)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771)
09-05 13:46:44.871  9198  9198 E ChartActivity:  at dalvik.system.NativeStart.main(Native Method)


#2

Hi.

Thanks for getting in touch and we are sorry to hear that you are having problems using our Annotations.

We are not currently aware of any issues relating to the Annotations functionality of shinobicharts. I’m interested to learn that this issue began to occur a few shinobi releases ago. Can you recall specifically which release introduced the issue? If at all possible, could you provide us with a small cut-down sample app which demonstrates the issue? If you can, please get in touch with us at info@shinobicontrols.com.

Is the issue random or does it occur overtime the app is run? Could you advise at what point you call ‘DrawAnnotations’ with respect to the measure, layout and draw phases please?

We look forward to hearing from you.

Thanks, Kai.