I am creating a single activity application using jetpack navigation. Everything is working as expected. I have a requirement to make some fragments full screen.
Here is my layout 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/main_drawer"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
tools:context=".features.HomeActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/main_nav_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/main_navigation" />
<com.google.android.material.navigation.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/main_header"
app:itemShapeInsetStart="0dp" />
</androidx.drawerlayout.widget.DrawerLayout>
As you can see I have used the android:fitsSystemWindows attribute in FragmentContainerView.
But this is not working as expected and after inspecting the layout using Layout Inspector I am seeing duplicate FragmentContainerView in the view hierarchy.
Here is a screen shot of the view hierarchy.
The problem this creates is that the first FragmentContainerView has the fitsSystemWindows attribute set to true but the second FragmentContainerView doesn't have that attribute set. I also tried the Advanced Navigation Sample and inspected the view and it also has the duplicate FragmentContainerView.
Can anyone please explain this to me? Thanks in advance.
Related
I'm creating new app with MVVM architecture. So it has strong connection with dataBinding.
I want to use DrawerLayout and data Binding in MainActivity and here i have stuck, because rule for DrawerLayout root element in xml must be DrawerLayout and for success data binding, root element must be layout. Can somebody help me to combine this two root elements in correct way?
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/actionBar_layout"
app:navGraph="#navigation/navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
</android.support.v4.widget.DrawerLayout>
</layout>
Compiler told me that DrawerLayout can't be placed inside layout tag. If i put layout inside DrawerLayout then data binding is not working anymore
you should put the drawer layout in the layout tag, it works fine. your problem is that you are getting the drawer layout from android.support but your constraint layout is from androidx my suggestion is to migrate to androidx
In Swift, we can use a Library called "SideMenu" to show a viewController on the SideMenu.
Now, I'm coding in Android. I want to display activity in the NavigationView we can only display a Menu or header.
I cannot show an activity or fragment on the NavigationView.
Can you help me or give me some advice about this problem?
ANDROID STUDIO NAVIGATION VIEW
XCODE SWIFT SIDE MENU
Android app can display one activity at once (it's changed recently but in your scenario it's still true). In your case you should inflate View or Fragment. Just put your layout or fragment inside NavigationView:
<?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">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<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">
<TextView
android:text="Custom View"
android:layout_gravity="center"
android:background="#ff0000"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
NavigationView extends FrameLayout so if you will inflate menu it will overlap. Because of that you may want to delete:
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer"
If you are using the android navigation component you can see the full detailed information to achieve this and replacing the fragments to corresponding to user clicks/choices drawer layout with navigation component
if you aren't using the android navigation component and just using the drawer layout you can see this drawer layout
im having an issue with layout. I am trying to get the constraint layout to be placed underneath the toolbar. However, it decides it wants to overlap the toolbar. I have tried using app:layout_behavior="#string/appbar_scrolling_view_behavior" with no luck.
The toolbar is creating in another xml file and called in using include.
Activity below
<android.support.v4.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:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/drawer_layout"
android:fitsSystemWindows="true"
tools:context="XXXXXX"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<include
android:id="#+id/test1234"
layout="#layout/app_bar_home"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.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"
app:menu="#menu/drawer_menu" />
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="#id/test1234">
**Bunch of constraints here etc**
**Bunch of buttons here**
</android.support.constraint.ConstraintLayout>
</android.support.v4.widget.DrawerLayout>
Here is an image of what it looks like
What it should look like
Edit
It is fine when shown in the design view of the android studio. However when opened on a phone or emulator it is still broken.
App still looks like the second image when emulated.
With the fixes below
I faced the same issue then i cracked it with this.
in your constraint layout, write this
android:layout_marginTop="?attr/actionBarSize"
app:layout_behavior="#string/appbar_scrolling_view_behavior
You're implying this attribute to the parent tag. You must add this to the ConstraintLayout or the main content of the drawer layout.
I have a custom View within the NavigationView. The problem is no matter in what combination, fitsSystemWindows is not working within the NavigationView. and the top item in the drawer always stays behind the transcludent statusbar.
main_layout
<?xml version="1.0" encoding="utf-8"?>
<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:openDrawer="start">
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#color/colorPrimaryBottomBar"
android:fitsSystemWindows="true">
<include layout="#layout/navigation_main_drawer" />
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
navigation_main_drawer
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:fillViewport="true"
android:fitsSystemWindows="true"
android:paddingBottom="#dimen/default_margin">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/default_margin"
android:fitsSystemWindows="true"
android:orientation="vertical">
<LinearLayout
...
</LinearLayout>
<View
... />
<LinearLayout
...
</LinearLayout>
<View
... />
<LinearLayout
...
</LinearLayout>
<View
... />
</LinearLayout>
</ScrollView>
</android.support.design.widget.CoordinatorLayout>
So, if I've understood correctly, you want your custom view to get the necessary padding so that its contents are not clipped by the status bar right?
If that's the case then you need to set
android:fitsSystemWindows="true"
in your root DrawerLayout, and then set
android:fitsSystemWindows="false"
in your NavigationView component. Note that's false, not true :)
REASONING:
The new NavigationView component designed by Google uses the 'fitsSystemWindows' property to customize how its content relates to the status bar. Note that "customize" here is the key word, because the hardcoded behaviour for this particular component is that its contents should overlap the status bar and reach the top of the screen, while the status bar itself should be transparent to allow the drawer's content to be seen through it. This is specified as part of the new Material Design, as can be seen in https://material.io/guidelines/patterns/navigation-drawer.html.
So, the only way to disable this behaviour is to tell the NavigationView to not signal the fitsSystemWindow property, and only set this in the root DrawerLayout that contains all other views, which will do what you would expect and pad all its children views appropriately.
Note that this reasoning is confirmed also by this comment from Android developer Ian Lake in a blog post talking about this specific property.
P.S.
I would also remove all mentions to the 'fitsSystemWindows' property in all the child elements in your navigation_main_drawer XML, just in case, although it probably does have no effect whatsoever as it is..
Got a weird problem. Contents of the fragment getting hidden under the action bar. Its a pretty basic drawer layout and a fragment.
New to android and don't know if this is how it is.
I used margin just to pull this down, as you can see below. But this doesn't sound correct to me... please throw some light where am I going wrong. Thanks in Advance.
It is the normal and expected behaviour if you set FEATURE_ACTION_BAR_OVERLAY (android:windowActionBarOverlay) . Here the documentation
Add an attribute
app:layout_behavior="#string/appbar_scrolling_view_behavior"
to your parent view of your fragment.
Another possible solution for many who see this question is to change the parent layout of the toolbar to LinearLayout (likely with a vertical orientation), as this type of layout does not allow its children to overlap.
For example, this layout in activity_main.xml will result in the fragment being below the toolbar, rather than behind it:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"/>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph"/>
</FrameLayout>
</LinearLayout>
Setting top margin of the fragment's layout to height of AcionBar worked, at last!!
android:layout_marginTop="?attr/actionBarSize"
Don't know if this is a better solution but for me this is the only working solution.