0

I'd like to place a View on a certain position/area of a GoogleMap object.

It needs to be a View, and not simply a Marker, as I'd like to add an OnDragListener to it.

There is another question with a similar title, but I don't think it's applicable to my use case.

I've tried to get the x and y position of a touch on the MapView in order to pinpoint a location to place the View, but the GoogleMap object consumes the MapView's touch events.

In my layout, I've placed an inner ConstraintLayout with the id con_red_rectangle and another which contains the MapView. The idea is to place con_red_rectangle on a certain position of the map (screenshot below).

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/con_top" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/con_red_rectangle" 
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:background="@drawable/rounded_red"
        app:layout_constraintTop_toTopOf="parent" 
        app:layout_constraintLeft_toLeftOf="parent"
        android:translationZ="1dp">

    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/con_map_container" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        android:translationZ="0dp">

        <com.google.android.gms.maps.MapView
            android:id="@+id/mapView" 
            android:layout_width="0dp" 
            android:layout_height="0dp"
            app:layout_constraintTop_toTopOf="parent" 
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent" 
            app:layout_constraintStart_toStartOf="parent"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

In the onMapReady callback, I dynamically set the margins of con_red_rectangle. However, it isn't positioned on the map, but rather based on the parent layout.

val lp: ConstraintLayout.LayoutParams = con_red_rectangle?.layoutParams as ConstraintLayout.LayoutParams
lp.leftMargin=x
lp.topMargin=y
con_red_rectangle!!.layoutParams=lp 

Screenshot

I realized that my issue may not be clear, so hopefully a screenshot could help.

I'd like to place a View where the Marker named "Place View Here" is at. That View would cover a certain area of the map, and would not "move" with camera movement. I've also realized that the size during zoom changes could become a matter, but the first priority is to place a View on that location.

As shown on the screenshot, that red semi-transparent View is positioned based on the main layout and not the map.

enter image description here

Erlend K.H.
  • 448
  • 6
  • 21

2 Answers2

0

If I understand your question correctly, in this case, you should put your view after MapView. Constraint layout depends on views order in XML. If yours MapView lower than it will be drawn over your view. Right views order should look like this:

<!-- Top level layout. -->
<ConstraintLayout>

    <!-- Layout with other views. -->
    <ConstraintLayout>
        <TextView/>
    </ConstraintLayout>

    <!-- Layout with a View (should be over the map) and the Google Map object. -->
    <ConstraintLayout>
        <MapView/>
        <View/> <!-- Referred to as "con_map_area" below. -->
    </ConstraintLayout>

</ConstraintLayout>

And in this case, View consumes touch event first.

ZSergei
  • 807
  • 10
  • 18
0

First thing, ConstraintLayout is different than other layouts in such a way that the view declared after other views will appear on top which is exact opposite of other layouts.

It means that in below case:

<ConstraintLayout>
    <View1/>
    View2/>
</ConstraintLayout>

View2 will be on top of View1 as it's declared after View1. Opposite of this happens in Layouts like Relative or Linear.

This will definitely work, you can further give android:elevation as 5dp or 3dp (your call) to keep the view on top with depth shadow.

So, declare your views like this:

<ConstraintLayout>
    <MapView/>
    <View/> <!-- Referred to as "con_map_area" below. -->        
</ConstraintLayout>

Don't forget that your first child ConstraintLayout will also work this way which you may want to declare after this one. And, at last you really don't need to nest ConstraintLayout, it is especially designed for flat view hierarchy. Also, to change the postition programmatically, you should use ConstraintSet.

Lalit Fauzdar
  • 5,953
  • 2
  • 26
  • 50
  • Thank you for your answer and advice, Lalit Fauzdar. I appreciate your suggestions for optimizing the layout, however, the main issue is that I don't know how to place a View on top of a GoogleMap object. I can place the View above the map by setting different translationZ values, but I need to place the View on a specific area of the map. I'm sorry if it sounds confusing. – Erlend K.H. Jun 13 '20 at 17:57
  • Hi @ErlendK.H. Have a look on these two : [This](https://stackoverflow.com/questions/50556625/using-android-google-maps-v2-with-custom-view-or-imageview) and [This](https://stackoverflow.com/questions/10792349/drawing-shapes-in-android-mapview-independent-of-the-zoom-level). Also, I don't actually understand what you want but If you want to place the view somewhere on screen, you can do it using Constraints, else you want to postition it somewhere on map then check the first link, – Lalit Fauzdar Jun 13 '20 at 18:26
  • Thanks for the links. I've added a screenshot to the question, does it help clarifying my issue? Yes, I'd like to position a view somewhere on the map. As for the first link, maybe it could work, but I don't think it would be the optimal solution, since I'd like to place several views, which with custom views could impact performance considerably. Plus, I'd need to get the views as variables. – Erlend K.H. Jun 13 '20 at 19:00