DrawerLayout inside fragment.xml not showing on home icon click - android

Background
I'm trying to implement a Drawer Navigation inside my fragment. I would prefer to have it there rather than in my main activity because I'm trying to handle toolbars per fragment and having the Drawerlayout coupled would make it easier to setup.
Problem
When I click on the hamburger home button, no drawer layout is displayed. How do I resolve this issue while keeping the drawerlayout inside my fragment.xml file instead of moving it to activity?
Things I've Tried
Followed the Android Navigation Drawer Guide
Made sure my xml layout hierarchy matches the requirements
fragment.xml
<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:id="#+id/drawer_article_topics"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="#layout/toolbar" />
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/articles_swipe_to_refresh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/articles"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.design.widget.CoordinatorLayout>
<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:menu="#menu/navigation_article_topic" />
</android.support.v4.widget.DrawerLayout>
activity.xml
<LinearLayout 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"
android:orientation="vertical"
tools:context=".ui.main.MainActivity">
<LinearLayout
android:id="#+id/main_content_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
Fragment.java
#BindView(R.id.drawer_article_topics)
DrawerLayout articleTopicDrawerLayout;
// Other code
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_articles_refresh:
articleListingViewModel.startRefresh();
refresh();
return true;
case android.R.id.home:
articleTopicDrawerLayout.openDrawer(GravityCompat.START);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
setSupportActionBar(toolbar);
setDrawerIcon();
setupRecyclerView();
setupSwipeRefreshLayout();
}
private void setDrawerIcon() {
if (isAdded()) {
ActionBar actionBar = ((AppCompatActivity)getActivity()).getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
}
}

The issue seemed to lie with DrawerLayout.openDrawer() and the Android Material Components library. Because I was inheriting Theme.MaterialComponents.Light.NoActionBar in my AppTheme, the Navigation Drawer did not open. Until they add a fix in, the workaround is to add this to your App Theme:
<item name="navigationViewStyle">#style/Widget.Design.NavigationView</item>
More information here:
https://github.com/material-components/material-components-android/issues/133

Related

NestedScrollView with Toolbar

So I set in styles.xml for AppTheme NoActionBar, because I want Toolbar only in a few Activites and also I create post_details_menu with two items. But toolbar not showing at all.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
Then in Manifest.xml, I have the theme: AppTheme
<application
android:theme="#style/AppTheme"
...>
</application>
Then i created my_toolbar:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"/>
</LinearLayout>
And in im PostDetailsActivity i want use my Toolbar:
public class PostDetailActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post_detail);
Toolbar toolbar = findViewById(R.id.my_toolbar);
setSupportActionBar(toolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.post_details_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()){
case R.id.post_Edit:
showMessage("post_edit clicked");
return true;
case R.id.post_Delete:
showMessage("post_delete clicked");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
And finally this is my layout for ActivityPostDetails:
<androidx.core.widget.NestedScrollView
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"
tools:context=".PostDetailActivity"
android:background="#fff">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView ... />
<TextView ... />
<androidx.recyclerview.widget.RecyclerView .../>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
It's too simple. set your app bar layout in the XML file where you want to show the toolbar.
check below XML code:-
<androidx.core.widget.NestedScrollView
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"
tools:context=".PostDetailActivity"
android:background="#fff">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appBarLayout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"
android:theme="#style/AppTheme.ActionBar"
app:navigationIcon="#drawable/ic_back"
app:subtitleTextAppearance="#style/CustomSubTitleTextAppearance"
app:titleTextColor="#color/black" />
</com.google.android.material.appbar.AppBarLayout>
<ImageView ... />
<TextView ... />
<androidx.recyclerview.widget.RecyclerView .../>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
In your java code, you have to bind toolbar programmatically in PostDetailsActivity.java.
toolbar = findViewById(R.id.toolbar)
toolbar!!.setNavigationIcon(R.drawable.ic_back)
if (toolbar != null) {
setSupportActionBar(toolbar)
}
Xml structure something like this should solve the problem
<LinearLayout>
<Toolbar/>
<NestedScrollView>
//one parent view inside nestedscrollview
<AnylayoutType>
// other required views
</AnylayoutType>
</NestedScrollView>
<LinearLayout/>
With this approach your Toolbar won't move and menu option will always be available and nested sroll view will work as required.
And if you are sure your view hierarchy is not nested its better to use LinearLayout inside nested scrollview

How to use viewpager and tablayout inside a fragment?

I need my app to have bottom bar navigation and swipable tabs. so I need viewpager to swap between fragments nested inside each fragment that is used by the bottom navigation. how do I do this?
First, you create a Fragment that contains ViewPager and TabLayout like this
<LinearLayout 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"
android:orientation="vertical"
tools:context=".FragmentThatHasViewPagerAndTabLayout">
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Then create a Activity which includes FrameLayout (that will be used as fragment container) and BottomNavigation
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_navigation_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="#color/colorPrimary"
app:itemIconTint="#FFF"
app:itemTextColor="#FFF"
app:menu="#menu/menu_bottom_navigation"/>
</LinearLayout>
Snippet code for Activity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation_view);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
//Change fragment when select another item in BottomNavigation
}
}
getFragmentManager().beginTransaction().replace(R.id.fragment_container, new FragmentThatHasViewPagerAndTabLayout(), "TAG_TO_REUSE_FRAGMENT_AFTER_CONFIG_CHANGES").commit();
}
And code in Fragment that contains ViewPager and TabLayout, you just write it like normally do (like having a FragmentPagerAdapter, etc.)

How to make navigation drawer and bottom navigation with the same app?

I'm trying to use navigation drawer and bottom bar nav in my app.therefore i have created navigation activity first.then i tried to add bottom bar nav to that same activity. I want to develop like this app:
without BottomNavigationView in Activity.xml,app is working.but when i add BottomNavigationView inside Activity.xml app crashed.nothing showing in logcat.
how can i use both bottombar nav and navigation drawer in same activity,please give me an simple example? thx
I am using Navigation Architecture Component following version:
def nav_version = "2.0.0"
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"
And below is a simple code to use BottomNavigation and Navigation Drawer
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private static final String TAG = "debinf MainActivity";
//public static final String FRAGMENT_KEY = "fragment";
private BottomNavigationView bottomNavigationView;
private NavigationView navigationView;
private DrawerLayout drawerLayout;
private NavController navController;
private AppBarConfiguration appBarConfiguration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "onCreate: ");
bottomNavigationView = (BottomNavigationView) findViewById(R.id.main_bottomnav);
navigationView = (NavigationView) findViewById(R.id.main_sidebar);
drawerLayout = (DrawerLayout) findViewById(R.id.main_drawer);
setupNavigation();
}
private void setupNavigation() {
Log.i(TAG, "setupNavigation: ");
navController = Navigation.findNavController(this, R.id.main_fragment);
appBarConfiguration =
new AppBarConfiguration.Builder(navController.getGraph()) //Pass the ids of fragments from nav_graph which you dont want to show back button in toolbar
.setDrawerLayout(drawerLayout)
.build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration); //Setup toolbar with back button and drawer icon according to appBarConfiguration
NavigationUI.setupWithNavController(navigationView, navController);
NavigationUI.setupWithNavController(bottomNavigationView, navController);
/*
** Listener for bottomNavigation must be called after been setupWithNavController
** This command will override NavigationUI.setupWithNavController(bottomNavigationView, navController)
** and the automatic transaction between fragments is lost
* */
//bottomNavigationView.setOnNavigationItemSelectedListener(this);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
Log.i(TAG, "onBackPressed: ");
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
Log.i(TAG, "onBackPressed: DRAWER IS OPEN - CLOSING IT");
drawerLayout.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onSupportNavigateUp() {
Log.i(TAG, "onSupportNavigateUp: ");
// replace navigation up button with nav drawer button when on start destination
return NavigationUI.navigateUp(navController, appBarConfiguration) || super.onSupportNavigateUp();
}
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
Log.i(TAG, "onNavigationItemSelected: SIDE BAR");
if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
}
// https://stackoverflow.com/questions/55990820/how-to-use-navigation-drawer-and-bottom-navigation-simultaneously-navigation-a
// https://stackoverflow.com/questions/58345696/how-to-use-android-navigation-component-bottomnavigationview-navigationview
// https://stackoverflow.com/questions/55667686/how-to-coordinate-a-navigation-drawer-with-a-buttom-navigation-view
// https://ux.stackexchange.com/questions/125627/is-it-okay-to-use-both-nav-drawer-and-bottom-nav-in-home-screen-of-an-android-ap?newreg=da5d1cea03db496982a00b256647728d
if (menuItem.getItemId() == R.id.main_menusidehome) {
Intent intent = new Intent(MainActivity.this, NotificationActivity.class);
startActivity(intent);
Log.i(TAG, "onNavigationItemSelected: conta");
}
if (menuItem.getItemId() == R.id.main_menusideshop) {
Log.i(TAG, "onNavigationItemSelected: compra");
}
if (menuItem.getItemId() == R.id.main_menusidesearch) {
Log.i(TAG, "onNavigationItemSelected: estatistica");
}
return true;
}
}
And below is acitivity_main.xml :
<androidx.drawerlayout.widget.DrawerLayout
android:id="#+id/main_drawer"
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"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/main_fragment"
android:layout_width="0dp"
android:layout_height="0dp"
android:name="androidx.navigation.fragment.NavHostFragment"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#id/main_bottomnav"
app:defaultNavHost="true"
app:navGraph="#navigation/mainnav_graph"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/main_bottomnav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/main_navmenu"
android:background="#color/colorAccent"
app:itemIconTint="#drawable/botton_item_color"
app:itemTextColor="#drawable/botton_item_color">
</com.google.android.material.bottomnavigation.BottomNavigationView>
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/main_sidebar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="#menu/main_sidebarmenu"/>
</androidx.drawerlayout.widget.DrawerLayout>
I hope it helps!
If you using includes. Just wrap app bar include with bottom navigation in some layout. For example I'm using ConstraintLayout for most of time.
content_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/view_pager_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
app_bar_main
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/app_bar_layout_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/gradient_main"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.appbar.MaterialToolbar
android:id="#+id/material_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:titleTextColor="#color/white" />
</com.google.android.material.appbar.AppBarLayout>
<include
android:id="#+id/content_main_include"
layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
activity_main
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.android.tool.ui.activty.main.MainActivity"
tools:openDrawer="start">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/app_bar_include"
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="#menu/menu_main" />
</androidx.constraintlayout.widget.ConstraintLayout>
<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"
app:headerLayout="#layout/nav_header_example"
app:menu="#menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
That's all.
Add a parent to <include ..../> then add BottomNavigationView
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.BottomNavigationView
android:id="#+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#color/colorPrimary"
app:itemTextColor="#color/colorAccent"
app:menu="#menu/bottom_navigation_menu"/>
</RelativeLayout>
Use TabLayout instead of bottom navigation
TabLayout is better and easier
create root.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="#+id/drawerlayout"
android:layout_height="match_parent">
<include layout="#layout/activity_main"/>
<include layout="#layout/navi_drawer"/>
</android.support.v4.widget.DrawerLayout>
create navi_drawer
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:background="?attr/navigationBackground"
android:orientation="vertical">
</LinearLayout>
and activity_main.xml
<LinearLayout 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:background="?attr/backgroundActivity"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</android.support.v4.view.ViewPager>
<LinearLayout
android:id="#+id/lnrTab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layoutDirection="rtl"
android:orientation="vertical"
app:layout_anchor="#+id/viewpager"
app:layout_anchorGravity="bottom|center">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/dividers_color_dark"
app:layout_anchor="#+id/viewpager"
app:layout_anchorGravity="bottom|center" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
app:tabBackground="?attr/backgroundTab"
app:tabContentStart="9dp"
app:tabGravity="fill"
app:tabIndicatorColor="#color/colorAccent"
app:tabIndicatorHeight="1dp"
app:tabMode="scrollable" />
</LinearLayout>
</LinearLayout>
then MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.root);
//config your TabLayout
}

Edit toolbar according to the fragment displaying

n my main activity I have a navigation drawer and by clicking it I m loading different fragments like Home , Cart , Settings etc.. Initially in my main activity I got the toolbar with spinner and button to navigation drawer as well. But for other fragments I need to customize tool bar as I need.
Here is how my activity_main.xml implemented :
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/navigation_drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="#bool/fitsSystemWindows">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="#dimen/status_bar_kitkat_height"
android:background="?colorPrimary" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="#dimen/status_bar_lollipop_height"
android:background="?colorPrimaryDark" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/status_bar_margin_top">
<FrameLayout
android:id="#+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?actionBarSize" />
<!--include different toolbars into the activity dont know this is correct implementation... If I missed any of them It gives me a null pointer exception in MainActivity..-->
<include
android:id="#+id/toolbar_cart"
layout="#layout/toolbar_cart" />
<include
android:id="#+id/toolbar_home"
layout="#layout/toolbar_home" />
</FrameLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="#bool/fitsSystemWindows"
app:headerLayout="#layout/navigation_drawer_header"
app:menu="#menu/navigation_drawer_menu"
app:theme="#style/NavigationViewTheme" />
</android.support.v4.widget.DrawerLayout>
Then I implemented a method to customize toolbar according to the fragment loading (inside main activity) :
public void customizeToolBar(int position) {
switch (position) {
case 0:
toolbar = (Toolbar) findViewById(R.id.toolbar_home);
setSupportActionBar(toolbar);
subCategories_spinner = (Spinner) findViewById(R.id.spinner_subCategories);
actionBar = getSupportActionBar();
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowTitleEnabled(false);
break;
case 1:
toolbar = (Toolbar) findViewById(R.id.toolbar_cart);
setSupportActionBar(toolbar);
actionBar = getSupportActionBar();
actionBar.setTitle("Check Out");
actionBar.setDisplayHomeAsUpEnabled(true);
break;
....
Then I call that method inside the NavigationItemSelectedListener like below :
private void setupNavigationDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(
new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.item_navigation_drawer_home:
menuItem.setChecked(true);
customizeToolBar(0);
setFragment(0);
drawerLayout.closeDrawer(GravityCompat.START);
return true;
case R.id.item_navigation_drawer_cart:
menuItem.setChecked(true);
customizeToolBar(1);
setFragment(1);
drawerLayout.closeDrawer(GravityCompat.START);
return true;
...
But this is not working. Every time displays the same toolbar. I m new to android. Any suggestion to make this work would be grateful. Thank you.
There are many solutions to this issue.
If you include different toolbars you can add set android:visibility=""
Ex:
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:background="#2196F3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
</android.support.v7.widget.Toolbar>
And set toolbar Visibility when you change fragment:
toolbar.setVisibility(View.VISIBLE);
Or you can edit toolbar in the fragment:
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
Get toolbar from Main Activity and edit.

Issue with appcompat v21 Material Design: Fragment overlay content and toolbar

I followed http://android-developers.blogspot.de/2014/10/appcompat-v21-material-design-for-pre.html to use the toolbar, without fragment, it works perfectly, but when I use fragment, the fragment always overlays the content, and I cannot see toolbar when displaying fragment.
screen:
and when I starts another activity from the current one, the icon of the toolbar in the new activity doesn't show up. screen:
I use Android Support Library 21.0.3.
and the code in the MainActivity class:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mLeftDrawerList = (ListView) findViewById(R.id.left_drawer);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
mNavigationDrawerAdapter=new ArrayAdapter<String>( MyActivity.this, android.R.layout.simple_list_item_1, data);
mLeftDrawerList.setAdapter(mNavigationDrawerAdapter);
if (mToolbar != null) {
mToolbar.setTitle("Home");
setSupportActionBar(mToolbar);
}
initDrawer();
final FragmentManager fragementMgr = getSupportFragmentManager();
FragmentTransaction transaction = fragementMgr.beginTransaction();
transaction.add(R.id.fragment_container, new MyFragment());
transaction.commit();
}
the layout xml:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
android:layout_width="match_parent"
android:id="#+id/drawerLayout"
android:layout_height="match_parent">
<!-- activity view -->
<LinearLayout
android:layout_width="match_parent"
android:background="#fff"
android:layout_height="match_parent">
<include layout="#layout/toolbar" />
<FrameLayout android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- navigation drawer -->
<RelativeLayout
android:layout_gravity="left|start"
android:layout_width="match_parent"
android:background="#fff"
android:layout_height="match_parent">
<ListView
android:id="#+id/left_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#eee"
android:background="#fff"
android:dividerHeight="1dp" />
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
code in MyFragment:
public class MyFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
final Button button = (Button) view.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
Intent intent = new Intent(getActivity(), DetailActivity.class);
startActivity(intent);
}
});
// Inflate the layout for this fragment
return view;
}
}
layout xml for Fragment:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello_fragment"
android:textStyle="bold"
android:gravity="center"
android:layout_gravity="top"
android:textSize="18sp"
android:id="#+id/text"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_below="#+id/text"
android:text="#string/open"
android:id="#+id/button"/>
</RelativeLayout>
The code in DetailActivity class:
public class DetailActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("Detail");
setSupportActionBar(toolbar);
}
}
layout for the detail activity:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context=".DetailActivity">
<include layout="#layout/toolbar" />
<TextView
android:layout_width="wrap_content"
android:textColor="#000"
android:text="Detail Activity Content"
android:layout_height="wrap_content" />
</LinearLayout>
can anyone help me out? thanks a lot!
Update: I updated the code and layout of the main activity according to reply from m iav.
new screen is blank now with the changes:
toolbar is a view in your layout , you can see it like textview ,now it is a textview overlay your fragment ,you use attrbibu to below it
so finally after checking the sample: MaterialEverywhere, I came with the solution with updating the layout:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
android:layout_width="match_parent"
android:id="#+id/drawerLayout"
android:layout_height="match_parent">
<!-- activity view -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<FrameLayout android:id="#+id/fragment_container"
android:layout_below="#id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
<!-- navigation drawer -->
<RelativeLayout
android:layout_gravity="left|start"
android:layout_width="match_parent"
android:background="#fff"
android:layout_height="match_parent">
<ListView
android:id="#+id/left_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#eee"
android:background="#fff"
android:dividerHeight="1dp" />
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
the trick is the parent layout of the toolbar and the content frame. Instead of LinearLayout, I use RelativeLayout. and it works now as expected.
anyway, I found such change from the SDK is over complex, with so many changes, and each can cause issues. It will be much better for the developers to have clean APIs with less all these tweaks.
This should be your main layout.
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
android:layout_width="match_parent"
android:id="#+id/drawerLayout"
android:layout_height="match_parent">
<!-- activity view -->
<LinearLayout
android:layout_width="match_parent"
android:background="#fff"
android:layout_height="match_parent">
<include layout="#layout/toolbar" />
<FrameLayout android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<!-- navigation drawer -->
<RelativeLayout
android:layout_gravity="left|start"
android:layout_width="match_parent"
android:background="#fff"
android:layout_height="match_parent">
<ListView
android:id="#+id/left_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#eee"
android:background="#fff"
android:dividerHeight="1dp" />
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
And this should be your call to the new fragment:
transaction.add(R.id.fragment_container, new MyFragment())
transaction.commit();
Regarding your second question, a navigation drawer can't be shared among different activities. You have to use a new Fragment and keep the same Activity you're working in now.

Categories

Resources