tangram-es icon indicating copy to clipboard operation
tangram-es copied to clipboard

Android: Tangram map puts itself over NavigationView

Open quikssb opened this issue 3 years ago • 14 comments

I am using a regular NavigationDrawer in my Activity, see: https://s12.directupload.net/images/200729/hl9dxqt8.png

I am also using a Tangram map. For some reason the Tangram map puts itself over the navigation drawer: https://s12.directupload.net/images/200729/279br6ar.png

It covers the navigation drawer for a while until I start to navigate through the map. It is very inconsistent. At some random point the NavigationDrawer shows itself again. This issue is especially visible on a Samsung Galaxy S7, Android 8

This problem is strongly related with the Tangram map, since the navigation drawer doesnt cover behind other (native) view elements. I hope you can help me out.

quikssb avatar Jul 29 '20 09:07 quikssb

Hey @quikssb, thanks for the report! Can you try something for me to help diagnose the issue? In the part of your app where you initialize the map, try using a TextureViewHolder for rendering:

mapView.getMapAsync(mapReadyCallback, new TextureViewHolderFactory());

Let me know if this changes the behavior at all!

matteblair avatar Jul 29 '20 18:07 matteblair

@quikssb I would probably also be helpful to post your XML layout here. I am also a user of this library and I have buttons on top of the tangram map without any problems, so your issue is likely rather related to your layout than Tangram-Es.

westnordost avatar Aug 03 '20 13:08 westnordost

Thank you so much for the replies.

I am currently not working on the project. Next week I will apply the suggestion and post the XML layout and get back to you.

quikssb avatar Aug 04 '20 09:08 quikssb

Hey @matteblair . Your suggestion fixed the problem. Absolute legend.

quikssb avatar Aug 11 '20 10:08 quikssb

Hey @matteblair , I have to reopen the issue since after applying the new method of loading the map I am facing new issues.

After putting the app into background and again into foreground the map is frozen (on the Samsung Galaxy S7, Android 8). When I try to close the View this happens:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.SurfaceTexture.release()' on a null object reference at com.mapzen.tangram.viewholder.TextureViewHolder.onSurfaceTextureDestroyed(TextureViewHolder.java:88) at android.view.TextureView.releaseSurfaceTexture(TextureView.java:249) at android.view.TextureView.onDetachedFromWindowInternal(TextureView.java:222) at android.view.View.dispatchDetachedFromWindow(View.java:18677) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3878) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3878) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:5432) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:5403) at android.view.ViewGroup.removeView(ViewGroup.java:5334) at androidx.constraintlayout.widget.ConstraintLayout.removeView(ConstraintLayout.java:645) at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManager.java:1550) at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784) at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:797) at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625) at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411) at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366) at androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273) at androidx.fragment.app.FragmentManagerImpl$1.run(FragmentManager.java:733) at android.os.Handler.handleCallback(Handler.java:789) at android.os.Handler.dispatchMessage(Handler.java:98) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6944) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

This issue does not occur with a Google Pixel 2 on Android 10. It is 100% related with the new TextureViewHolderFactory()

quikssb avatar Aug 11 '20 11:08 quikssb

Thanks for the update. Can you share the XML layout that you're using for this view?

matteblair avatar Aug 11 '20 18:08 matteblair

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:openDrawer="start">

    <com.google.android.material.navigation.NavigationView
            android:id="@+id/nav_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/nav_header_main"
            app:menu="@menu/activity_main_drawer"/>

    <androidx.constraintlayout.widget.ConstraintLayout
            android:id="@+id/fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            tools:showIn="@layout/app_bar_main"
            tools:context=".MainActivity" />

</androidx.drawerlayout.widget.DrawerLayout>

Here you can see the navigationview, which gets covered by the tangram map.

Inside the fragment_container a Fragment gets loaded with the following layout:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:animateLayoutChanges="true"
                android:background="@android:color/white">

    <com.mapzen.tangram.MapView
            android:id="@+id/mv_route"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:keepScreenOn="true"/>

       [....]

</RelativeLayout>

quikssb avatar Aug 12 '20 10:08 quikssb

Ok, I don't see anything wrong with this.

Note though that each view decides by itself which child view to draw first. Usually, they draw the child views in the given z order (translationZ / evaluation) and for those for which it is the same, in the order in which they are written in the layout XML. If I remember correctly, the ActionBar for example is always put on top because it has some implicit evaluation (or translation/Z).

I didn't use a DrawerLayout yet, maybe you could take a look in the source and see if it does anything unusual on layout / on draw. Or maybe easier, put for example a button into the relative layout that contains the MapView that is on top of the MapView. If it stays on top, I'd think you have to look somewhere in the layout for the problem. If it is obscured by the map view, then there is an issue with Tangram.

westnordost avatar Aug 12 '20 10:08 westnordost

Ok so as you suggested I put a button into the RelativeLayout, where the map is:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:animateLayoutChanges="true"
                android:background="@android:color/white">

    <Button
            android:text="iii"
            android:background="@color/colorBlue"
            android:layout_width="200dp"
            android:layout_height="200dp"/>

    <com.mapzen.tangram.MapView
            android:id="@+id/mv_route"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:keepScreenOn="true"/>

          [...]

Here you can see the result, the button is the blue rectangle on the top left. Indeed it is on top of the map. https://s12.directupload.net/images/200812/87r3hgnq.jpg

When opening the drawer this very interesting effect occurs: https://s12.directupload.net/images/200812/wuodk2ze.jpg

The drawer can be seen until to the point where the button is placed. At the moment where the button's height ends, the drawer gets eaten up by the map.

Now this is interesting lol. Any ideas?

quikssb avatar Aug 12 '20 11:08 quikssb

More to add:

I swapped the Button with a normal View:

<View
            android:background="@color/colorBlue"
            android:layout_width="200dp"
            android:layout_height="200dp"/>

It should look the same, but the View gets eaten up by the map. The button does not.

quikssb avatar Aug 12 '20 11:08 quikssb

Okay, I think what is actually happening is not that the map is on top of the drawer, but that the drawer for some reason has wrong dimensions for some reason. Try looking at the layout in the layout inspector.

westnordost avatar Aug 12 '20 11:08 westnordost

What exactly do I need to look out for?

The problem is that the drawer gets only eaten up for a few seconds after app start. Before I can 'capture' that scenario in the layout inspector the drawer already gets shown correctly.

quikssb avatar Aug 12 '20 12:08 quikssb

Oof, sorry, I am not an expert on the drawer layout (or tangram drawing). In your place, I would experiment more with adding for example a full pink view behind the the fragment container in the drawer layout, or behind the map view within the fragment layout. Apparently the drawer is (initially) only made as high as any views within that fragment that are not the tangram MapView for some reason.

westnordost avatar Aug 12 '20 12:08 westnordost

I made a little hack to fix this problem.

I put this right over the map view:

<Button
        android:layout_height="match_parent"
        android:layout_width="1dp"
        android:background="@android:color/transparent"/>

When another native view is over the map the drawer doesn't get eaten up. So I put a transparent button on the left side with the width of 1pixel. I will still keep the issue open, just in case you guys want to investigate this further (apparently I don't know if this is now a problem of the lib in the end or messy code of the project).

Anyways thanks a lot for your help.

quikssb avatar Aug 12 '20 16:08 quikssb