xamarin / urho

Code to integrate with the Urho3D engine
Other
462 stars 122 forks source link

LineEdit on Android crashes on second open #341

Open woychukb opened 6 years ago

woychukb commented 6 years ago

I've got a Urhosharp.Forms project that I'm trying to test on Android (both physical and emulator) and I'm getting exceptions on the second time the LineEdit control is selected.

Steps to reproduce: Start app (on emulator or physical device) Touch LineEdit control Touch anywhere else on screen Touch LineEdit control again (or a different LineEdit control)

Callstack:

07-10 10:22:49.122 E/AndroidRuntime( 2225): java.lang.ClassCastException: android.widget.AbsoluteLayout$LayoutParams cannot be cast to android.view.ViewGroup$MarginLayoutParams
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5116)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.View.measure(View.java:16497)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewGroup.measureChild(ViewGroup.java:5096)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewGroup.measureChildren(ViewGroup.java:5073)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.widget.AbsoluteLayout.onMeasure(AbsoluteLayout.java:63)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.View.measure(View.java:16497)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.View.measure(View.java:16497)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.widget.LinearLayout.measureVertical(LinearLayout.java:695)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.widget.LinearLayout.onMeasure(LinearLayout.java:588)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.View.measure(View.java:16497)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2291)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.View.measure(View.java:16497)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1912)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1109)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1291)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:996)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5600)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.Choreographer.doCallbacks(Choreographer.java:574)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.Choreographer.doFrame(Choreographer.java:544)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.os.Handler.handleCallback(Handler.java:733)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.os.Handler.dispatchMessage(Handler.java:95)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.os.Looper.loop(Looper.java:136)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at android.app.ActivityThread.main(ActivityThread.java:5001)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at java.lang.reflect.Method.invokeNative(Native Method)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at java.lang.reflect.Method.invoke(Method.java:515)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
07-10 10:22:49.122 E/AndroidRuntime( 2225):     at dalvik.system.NativeStart.main(Native Method)

MainActivity.cs

using Android.App;
using Android.Content.PM;
using Android.Widget;
using Android.OS;
using Urho.Droid;

namespace Foo.Droid
{
    [Activity(Label = "Test", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : Activity
    {
        protected override async void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);            
            var mLayout = new AbsoluteLayout(this); // also tried with FrameLayout or LinearLayout
            var surface = UrhoSurface.CreateSurface(this);
            mLayout.AddView(surface);
            SetContentView(mLayout);
            var app = await surface.Show<GameEngine>(new Urho.ApplicationOptions("Data"));
        }

        protected override void OnResume()
        {
            UrhoSurface.OnResume();
            base.OnResume();
        }

        protected override void OnPause()
        {
            UrhoSurface.OnPause();
            base.OnPause();
        }

        public override void OnLowMemory()
        {
            UrhoSurface.OnLowMemory();
            base.OnLowMemory();
        }

        protected override void OnDestroy()
        {
            UrhoSurface.OnDestroy();
            base.OnDestroy();
        }
    }
}

GameEngine.cs (trimmed of anything not necessary to reproduce this)

using Urho;
using Urho.Gui;

namespace Foo
{
    public class GameEngine : Application
    {
        private Scene scene;

        public GameEngine(ApplicationOptions options): base(options)
        {
        }

        protected override async void Start()
        {
            base.Start();
            scene = new Scene();
            var testEdit = new LineEdit();
            UI.Root.AddChild(testEdit);
            testEdit.SetStyleAuto(null);
            testEdit.Text = "WTF";
            testEdit.SetFixedSize(600, 50);
        }
    }
}

From what I can tell the problem is that ShowTextInputTask in SDLActivity.java creates AbsoluteLayout.LayoutParams and uses that for the call to addView which gets called on the UrhoSurfacePlaceholder which uses FrameLayout as its base class.

Is anybody else experiencing issues with the LineEdit on Android? I haven't found any references to similar behavior which makes me think I'm missing something.

hwd71 commented 5 years ago

Me too!

woychukb commented 5 years ago

I actually submitted a pull request (https://github.com/xamarin/urho/pull/345) with the change to SDLActivity.java to change AbsoluteLayout to RelativeLayout which I think should fix this. I'm also not set up to build everything though so I can't guarantee it worked. Not sure if there are plans to do another release of the NuGet package any time soon.

barefists commented 5 years ago

I'm caught by this bug too! :(

hwd71 commented 5 years ago

Well, in a way that's a good thing.. more noise the better!

barefists commented 5 years ago

I also realized that by subscribing to the LineEdit's Focused event, it stopped the crash from triggering but also stops the on-screen keyboard from showing up.

LorenzCK commented 5 years ago

We’ve also been hit by the same issue: has anybody found a workaround?

slango0513 commented 5 years ago

I'm too. Is there any solution?

slango0513 commented 5 years ago

"Input.ScreenKeyboardVisible = true" twice will also trigger the same bug.

Solved without rebuild source or replace any nuget file. It worked fine for me but not fully tested. See MainActivity.cs and AbsoluteUrhoSurfacePlaceholder.cs:

https://github.com/slango0513/UrhoSamples2019/tree/master/BugWorkarounds/BugWorkarounds.Droid

woychukb commented 5 years ago

Thank you so much for the workaround @slango0513. Seems to work for me!