Fragment overlaps the AppCompat toolbar
Asked Answered
F

5

35

I'm working with the v7 support library and trying to have a navigation drawer on the left. As read elsewhere I set up:

  1. DrawerTest.java: The main activity that holds the drawer, into which I load my Toolbar with setSupportActionBar(), from a custom XML layout that holds just the Toolbar;

  2. toolbar.xml: A XML layout holding the toolbar;

  3. activity_drawer_listview.xml: A DrawerLayout XML resource, that holds containers for my fragment (a FrameLayout <including> the layout mentioned in 2.) and for the navigation drawer (a ListView);

  4. FragmentTest.java: Some really simple fragment code, extending Fragment;

  5. fragment_test_layout.xml: Some really simple fragment layout, with just a TextView inside.

I'll paste some code here, anyway my problem is that the fragment layout seems to start from the top of the screen, and not from the bottom of the Toolbar. Any text put in 5. will overlap the app title on the action bar. Where am I wrong?

(1.) DrawerTest.java

    public class DrawerTest extends ActionBarCompat {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawer_listview);

        DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        Toolbar tb = (Toolbar) findViewById(R.id.toolbar_main2);
        ActionBarDrawerToggle abDrawerToggle = new ActionBarDrawerToggle(
                        this, drawerLayout, tb,
                        R.string.navigation_drawer_open,
                        R.string.navigation_drawer_close )
        {
            // onDrawerClosed() { ... }
            // onDrawerOpened() { ... }
        };
        drawerLayout.setDrawerListener(abDrawerToggle);
        setSupportActionBar(tb);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        abDrawerToggle.syncState();

        //code to load my fragment
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.frame_layout_test, new FragmentTest()).commit();

        }
    }

(3.) activity_drawer_listview.xml

    <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout"
    android:layout_width="match_parent" android:layout_height="match_parent"
    tools:context="miav.ciotole.DrawerTest">

    <FrameLayout android:id="@+id/frame_layout_test" android:layout_width="match_parent"
        android:layout_height="match_parent" >
    <include layout="@layout/toolbar"/> <!-- What is this line about? -->
    </FrameLayout>

<ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>

(4.) FragmentTest.java

    public class FragmentTest extends Fragment {

    public FragmentTest() { }

    @Override
    public View onCreateView(LayoutInflater infl, ViewGroup container, Bundle SavedInstanceState) {
        View rootView = infl.inflate(R.layout.fragment_test_layout, container, false);
        return rootView;
    }
}

(5.) fragment_test_layout.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
// padding ...
>

<TextView android:id="@+id/section_label" android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world"/>

Note: I found some questions (and answers), but in most cases, the issue was related to AppCompat versions < 19, which is not my case.

Note2: I am inheriting from Theme.AppCompat.NoActionBar, as I'm setting the toolbar on runtime. Probably I could solve inheriting from Theme.AppCompat and avoid using setSupportActionBar(), but if possible I would stay with the actual configuration, as it makes easier to control the ActionBar.

Fabricant answered 23/12, 2014 at 17:6 Comment(0)
S
63

The reason is because you place it in a frame layout and then you add the fragment ontop of the toolbar. you need to do something like this

<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

       <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical">

       <android.support.v7.widget.Toolbar
           android:id="@+id/toolbar"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:minHeight="?attr/actionBarSize"
           android:background="?attr/colorPrimary"
           app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
           app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

       <FrameLayout
           android:id="@+id/content_frame"
           android:layout_width="match_parent"
           android:layout_height="match_parent" />

       </LinearLayout>

       <FrameLayout
       android:id="@+id/left_drawer"
       android:layout_width="325dp"
       android:layout_height="match_parent"
       android:layout_gravity="start"
       android:background="#FFFFFF"/>

</android.support.v4.widget.DrawerLayout>
Sempach answered 23/12, 2014 at 17:15 Comment(3)
Easier than I thought, thank you. My fragments loaded in your @id/content_frame will have, themselves, some layers of nested layouts. Is it so bad for performance as I read?Fabricant
I do this for a few of my apps and I see no performance problemsSempach
Thank you for the answer, but I prefer to use attribute layout_marginTop in the content_frame: android:layout_marginTop="?attr/actionBarSize". After all fragments you replace it with have the correct height. (I know this is a 2014 question but this was my best solution)Holland
D
6

Add this line in your FrameLayout

app:layout_behavior="@string/appbar_scrolling_view_behavior"
Divvy answered 24/5, 2017 at 14:27 Comment(1)
You can use this link for reference https://developer.android.com/reference/android/support/design/widget/AppBarLayout.htmlDivvy
M
1

You put the toolbar in the same Framelayout (with the id = frame_layout_test). FrameLayout overlaps views.

I guess you are trying to do something like this:

<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" 
android:layout_height="match_parent"
android:orientation="vertical" >

<include layout="@layout/toolbar"/> 
<!-- I don't know what your Toolbar layout is -->


    <android.support.v4.widget.DrawerLayout 
        android:layout_width="match_parent" 
        android:layout_height="0dp"
        android:layout_weight="1" 
        tools:context="miav.ciotole.DrawerTest">

        <FrameLayout android:id="@+id/frame_layout_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

        <ListView
            android:id="@+id/left_drawer"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:choiceMode="singleChoice"
            android:divider="@android:color/transparent"
            android:dividerHeight="0dp" />

    </android.support.v4.widget.DrawerLayout>
</LinearLayout>

The layout from above takes a linear layout and aligns the framelayout (where you will inflate your framgemt) below the toolbar ...

This lines

android:layout_height="0dp"
android:layout_weight="1"

says that the DrawerLayout should take the remaining height below the toolbar.

However, if you want to display a traditional actionbar / toolbar, you don't have to add a toolbar in the xml layout. You simply can change the Theme of the activity to @style/Theme.AppCompat.Light.DarkActionBar

Moitoso answered 23/12, 2014 at 17:15 Comment(3)
Have not tried it yet, but I feel like this way the drawer will slide below the Action Bar without covering it, which is actually my desired behavior. I want only the fragments to be below.Fabricant
yes, this way the drawer is below the action bar ... If you want to display drawer over the actionbar, then you should do it like described by @SempachMoitoso
Actually, this is against google material design best practices. Drawer should be on top of ToolBarDoolittle
M
0

This is very straight forward and easy. Just follow what I tried to say below.

You replace any View by using:

**

getFragmentManager().beginTransaction()
                .replace(R.id.blankFragment, new SettingsFragment())
                .commit();

** //Here, blackFragment is id of FrameLayout View. You replace FrameLayout View with Fragment's Layout. Note: It should be FrameLayout or FrameLayout's derivatives Layout.

My whole code is:

1) SettingsActivity.java

**

public class SettingsActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment);
        Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar2);
        mToolbar.setTitle("Settings");
////        remove the left margin from the logo
        mToolbar.setPadding(2, 0, 0, 0);//for tab otherwise give space in tab
        mToolbar.setContentInsetsAbsolute(0, 0);
        setSupportActionBar(mToolbar);
        // Display the fragment as the main content
        getFragmentManager().beginTransaction()
                .replace(R.id.blankFragment, new SettingsFragment())
                .commit();
    }
}

**

2) activity_fragment.xml

**

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
    android:fitsSystemWindows="true"
    android:orientation="horizontal">
    <!--scroll|snap-->
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/statusbar"
        android:minHeight="?attr/actionBarSize"
        app:theme="@style/ThemeOverlay.AppCompat.ActionBar" />
    <FrameLayout
        android:id="@+id/blankFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="?attr/actionBarSize"
        android:layout_gravity="top"
        android:fitsSystemWindows="true"
        android:orientation="horizontal" />
</FrameLayout>

** You can see my Screen after I replaced FrameLayout's View with Fragment's View

enter image description here

Merengue answered 6/1, 2017 at 2:22 Comment(0)
D
0

I have two activities and attach one fragment to them. In first activity it is shown right, while in second it overlaps Toolbar. Though android:layout_marginTop="?android:attr/actionBarSize" in a layout of the fragment may be a solution, I found an error.

Because Kotlin caches ids of views of layouts (instead of findViewById(R.id.some_id) you can write some_id), there is a big problem. Every time you should be very careful when copy an activity or a fragment. So, every time check your imports and attached layouts.

I copied FirstActivity to SecondActivity, copied activity_first to activity_second, but forgot to change:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_first) // Don't forget to change.

Similarly, in a fragment don't forget:

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {

    val view = inflater.inflate(R.layout.fragment_yours, container, false)

So, in my imports I had:

import kotlinx.android.synthetic.main.activity_second.*

In this case toolbar referenced to activity_second, while activity_first was actually attached. Then the fragment moved upper - just below the Toolbar. In most cases Kotlin never shows any problem with cached ids during compile or run time. It's a big pain.

Divulge answered 8/2, 2019 at 13:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.