Overlapping views in coordinatorlayout
Asked Answered
D

4

18

The code is below. When fragment loads, it covers the toolbar and my floating action bar. How can I handle this? I want the toolbar to show. It seems there is some overlapping in coordinatorlayout. I have checked out different problems like this. None seems to answer my question

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="@dimen/activity_horizontal_margin"
    android:orientation="vertical"
    tools:context="com.example.sammybobo.moglis.MoGLISMaps"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:android="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <android.support.v7.widget.Toolbar
        android:layout_width="fill_parent"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_height="?attr/actionBarSize"
        android:id="@+id/toolbar"
        android:elevation="4dp"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
        android:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

    <android.support.design.widget.FloatingActionButton
        android:id = "@+id/fab"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:src = "@android:drawable/ic_input_add"
        android:layout_gravity = "bottom|end"
        app:fabSize = "mini">

    </android.support.design.widget.FloatingActionButton>

    <fragment
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:id="@+id/main_map"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        xmlns:android="http://schemas.android.com/apk/res/android"
        tools:context = "com.example.sammybobo.moglis.MoGLISMaps"
        xmlns:tools="http://schemas.android.com/tools"
        />
 <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#fff"
        android:layout_gravity = "bottom"
        >
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="My location"
            android:onClick="observe"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text = "Friends"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text = "settings"/>
    </LinearLayout>
    </android.support.design.widget.CoordinatorLayout>
Dustproof answered 16/3, 2016 at 16:49 Comment(0)
P
13

It is because Inside a coordinator layout you can not set one view in relation to another. You can only have them in relation to the parent. Try with layout below.

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:android="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"
    android:orientation="vertical"
    android:padding="@dimen/activity_horizontal_margin"
    tools:context="com.example.sammybobo.moglis.MoGLISMaps">

    <RelativeLayout
        android:layout_height="wrap_content"
        android:layout_width="fill_parent">

        <android.support.v7.widget.Toolbar
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/toolbar"
            android:layout_width="fill_parent"
            android:layout_height="?attr/actionBarSize"
            android:elevation="4dp"
            android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            android:theme="@style/ThemeOverlay.AppCompat.ActionBar"/>

        <fragment
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/main_map"
            android:name="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:layout_below="@+id/toolbar"
            tools:context="com.example.sammybobo.moglis.MoGLISMaps"
            />

    </RelativeLayout>


    <LinearLayout
        android:background="#fff"
        android:layout_gravity="bottom"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        >

        <Button
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:onClick="observe"
            android:text="My location"/>

        <Button
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:text="Friends"/>

        <Button
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:text="settings"/>
    </LinearLayout>

    <android.support.design.widget.FloatingActionButton
        app:fabSize="mini"
        android:id="@+id/fab"
        android:layout_gravity="bottom|end"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:src="@android:drawable/ic_input_add">

    </android.support.design.widget.FloatingActionButton>

</android.support.design.widget.CoordinatorLayout>

If you want the bottom linear layout also to not overlap with the fragment then put it inside the relative layout and make sure fragment in above the linear layout.

Panjabi answered 16/3, 2016 at 16:56 Comment(6)
Thanks a lot. It works but how do I keep the relativelayout from overlapping the toolbarDustproof
The toolbar is inside the relative layout. Why would it overlap?Panjabi
I'm sorry - the relativelayout overlaps the fab.Dustproof
I have edited my answer. Move the fab layout to the bottom. Whichever layout is in the bottom will be drawn last and hence it will be drawn over the already drawn relative layout. You want the fab on top of relative layout right.Panjabi
Yes! Thanks man! I completely get it now. Do you have a tutorial blog or something? If not - you should start one bro!Dustproof
Glad i could help. Thats actually a very good idea. Will keep you posted.Panjabi
C
4

The child views are overlapping because there is nothing set to prevent the overlap. The basic layout behavior of CoordinatorLayout comes from FrameLayout, which is intended to provide a block of the screen (i.e. a frame) for its child. With multiple children, they are stacked in front of each other in source order, back to front, so the last child is in front. This is why the fragment @id/main_map and LinearLayout overlap the toolbar @id/toolbar and floating action button @id/fab.

CoordinatorLayouts own, more advanced layout mechanism is to animate child layout based on user interaction using Behaviors (more on this later). If you aren't making use of animated layouts, a CoordinatorLayout is not the most appropriate layout; the likes of a ConstraintLayout or LinearLayout would probably be better matches. This is potentially the simplest solution: change the layout. The following sections cover what to do if you want coordinated behaviors.

Behaviors

As previously mentioned, the main reason to use a CoordinatorLayout is to animate the layout of children, done by giving views Behaviors. A Behavior will update the layout of the owning view when some dependent view changes. Some widgets have built-in behavior, such as FloatingActionButtons and AppBarLayout. Others can be assigned via the layout_behavior property, setting it to the class name of the behavior to apply. For example, AppBarLayout provides a behavior that will offset a scrolling view relative to an AppBarLayout. This behavior is most often used with a collapsing toolbar. For example:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_height="192dp"
        android:layout_width="match_parent">

        <com.google.android.material.appbar.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:toolbarId="@+id/toolbar"
            app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
            app:contentScrim="?attr/colorPrimary"
            >
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:layout_gravity="top|fill_horizontal"
                app:layout_insetEdge="top"
                android:fitsSystemWindows="true"
                >
                ...
            </androidx.appcompat.widget.Toolbar>
        </com.google.android.material.appbar.CollapsingToolbarLayout>
    </com.google.android.material.appbar.AppBarLayout>
    
    <include layout="@layout/..."
        android:id="@+id/main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        ...

Absent app:layout_behavior set to the appropriate behavior, @id/main will overlap the AppBarLayout. For some views, you'll also have to set layout_width and layout_height to prevent overlap.

Note that if you create a new "Basic Activity" project, it will create something similar to the above.

Source Order

If you want widgets to overlap but want a different widget in front of another, change the source order so any widget in front comes after the widget it's supposed to eclipse.

Gravity

If the widgets are small enough, you can potentially pack them along different edges. Use gravity to anchor a child to an edge (e.g. center|bottom, center|start), corner (e.g. top|end, bottom|start) or center of a CoordinatorLayout. This is what you do with a FloatingActionButton:

    <android.support.design.widget.FloatingActionButton
        android:layout_gravity = "bottom|end"
        [...]
        >

You can also do this with, for example, a toolbar. You can't do this with Buttons, as the gravity attribute will affect the button's contents, rather than its position. If you want to position a Button, wrap it in (e.g.) a FrameLayout or Toolbar. Make sure the wrapping view is not set to (explicitly or implicitly) fill the parent, such as with FrameLayouts, else the wrapping view will expand to fill the entire frame, defeating the purpose of setting its gravity.

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top|end"
        ...
        />
        
        <Button
            ...

Layout based on gravity comes from FrameLayout.

Dodging

Once you've positioned something on an edge, you can shift another child away from the positioned views using dodgeInsetEdges. You must also set insetEdge on the positioned children, so the offset for the dodging view can be calculated. Note that this only shifts the view; it does not resize it, so if you try to dodge opposite edges, they may cancel out.

    <fragment
        app:layout_dodgeInsetEdges="top"
        ...
        />

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top|end"
        app:layout_insetEdge="top"
        ...
        />

While you can try inset dodging to prevent overlay, its intended purpose is to move views out of the way when another view (such as a SnackBar) enters along an edge; inset dodging will animate the other views, sliding them out of the way as the new view comes in.

Keylines

You can horizontally position child views using keylines. Note that if you do this, you can only vertically position the view using vertical padding & margins, relative to the CoordinatorLayout top.

Anchors

You can position a view along the edge of another view by using anchors. Set layout_anchor of the anchored view to the ID of the view to anchor to, and which part of the view to anchor to with layout_anchorGravity.

    <fragment
        android:id="@+id/main_map"
        ...
        />
    
    <Button
        app:layout_anchor="@id/main_map"
        app:layout_anchorGravity="top|end"
        ...
        />
Cabinda answered 21/10, 2021 at 7:22 Comment(0)
G
1

You can also just wrap all the views inside a LinearLayout to prevent any overlapping.

Graiggrail answered 22/10, 2019 at 12:43 Comment(0)
J
0

Children of a CoordinatorLayout may have an anchor. This view id must correspond to an arbitrary descendant of the CoordinatorLayout, but it may not be the anchored child itself or a descendant of the anchored child. This can be used to place floating views relative to other arbitrary content panes.

Children can specify CoordinatorLayout.LayoutParams.insetEdge to describe how the view insets the CoordinatorLayout. Any child views which are set to dodge the same inset edges by CoordinatorLayout.LayoutParams.dodgeInsetEdges will be moved appropriately so that the views do not overlap.

enter image description here

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:padding="10dp"
xmlns:android="http://schemas.android.com/apk/res/android">

<androidx.appcompat.widget.Toolbar
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:id="@+id/toolbar"
    app:layout_insetEdge="top"
    android:background="@color/teal_500"
    app:title="HOME"
    android:elevation="4dp"
    android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
    android:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>


<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/linearLayoutOptions"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff"
    app:layout_dodgeInsetEdges="top">

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:onClick="observe"
        android:text="My location"
        app:layout_constraintBottom_toBottomOf="@+id/button6"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button6"
        app:layout_constraintTop_toTopOf="@+id/button6" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Friends"
        app:layout_constraintEnd_toStartOf="@+id/button6"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="settings"
        app:layout_constraintBottom_toBottomOf="@+id/button4"
        app:layout_constraintEnd_toStartOf="@+id/button5"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/button4"
        app:layout_constraintTop_toTopOf="parent" />

    <fragment
        android:id="@+id/mobile_navigation_main"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button6" />

</androidx.constraintlayout.widget.ConstraintLayout>

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id = "@+id/fab"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:src = "@android:drawable/ic_input_add"
    android:layout_gravity = "bottom|end"
    app:fabSize = "mini"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Jacaranda answered 6/12, 2021 at 11:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.