Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overlapping views in coordinatorlayout

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>
like image 370
Samuel Agbede Avatar asked Mar 16 '16 16:03

Samuel Agbede


3 Answers

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.

like image 186
Ragesh Ramesh Avatar answered Nov 18 '22 11:11

Ragesh Ramesh


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"
        ...
        />
like image 42
outis Avatar answered Nov 18 '22 11:11

outis


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

like image 20
George Avatar answered Nov 18 '22 09:11

George