How to handle drawer toggle and toolbar up when having toolbar for each fragment - android

I am using single activity and many fragments approach in my app
Now since in my some fragments I have custom view in toolbar I decided to have separate toolbar for each fragment.
How to implement separate toolbar for each fragment also the drawer layout is in my activity

I have the same problem, I will add custom toolbar view for each fragment.
My Utility method is:
public static View addRemoveViewFromToolbar(FragmentActivity fragmentActivity, int resourceId) {
Toolbar toolbar = removeViewFromToolbar(fragmentActivity);
if (resourceId == 0) {
return null;
} else {
View view = LayoutInflater.from(fragmentActivity).inflate(resourceId, toolbar, false);
toolbar.addView(view);
return view;
}
}
public static Toolbar removeViewFromToolbar(FragmentActivity fragmentActivity) {
Toolbar toolbar = (Toolbar) fragmentActivity.findViewById(R.id.toolbar);
if (toolbar.getChildCount() > 1) {
for (int i = 1; i <= toolbar.getChildCount(); i++) {
toolbar.removeViewAt(1);
}
}
return toolbar;
}
In my each fragment
//Create your custom view based on requirement
View view = Utility.addRemoveViewFromToolbar(getActivity(), R.layout.toolbar_search_view);
if (view != null) {
edtCategory1 = (EditText) view.findViewById(R.id.edtCategory1);
edtCategory1.setOnClickListener(this);
}
Hope this explanation help you :)

I'm not sure if I understood your description of the your app correctly, but I recently did what I think you described.
My activity layout was a DrawerLayout with an included CoordinatorLayout/AppBar layout with a single toolbar and a FrameLayout below. The menu.xml contained all the items I needed in my toolbar for all the fragments. Items clicked in the nav menu would swap out fragments in the FrameLayout. My onNavigationItemSelected() called on this method to swap out the fragments and handle the backstack:
public void switchView(int id, int optArg) {
if (currentView != id) {
currentView = id; //currentView keeps track of which fragment is loaded
FragmentTransaction transaction = getFragmentManager().beginTransaction();
//Fragment contentFragment is the current fragment in the FrameLayout
switch (id) {
case 0: //menu item 1
contentFragment = new Nav_Item1_Fragment();
transaction.replace(R.id.fragment_container, contentFragment, "");
break;
case 1: //menu item 2
contentFragment = new Nav_Item2_Fragment();
transaction.replace(R.id.fragment_container, contentFragment, "");
break;
case 2: //menu item 3
contentFragment = new Nav_Item3_Fragment();
transaction.replace(R.id.fragment_container, contentFragment, "");
break;
}
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
// transaction.replace(R.id.fragment_container, contentFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
}
and in each fragment's onPrepareOptionsMenu() I setVisible() hid/showed the menu items in the toolbar related to that fragment. Each item had an method in the activity pointed to by the menu item's onClick attribute that knew what fragment it was from and what views were passed to it.
The drawer was setup in the onCreate() of the activity with a ActionBarDrawerToggle like so:
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
activity xml:
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer_layout"
...>
<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:fitsSystemWindows="true"
.../>
</android.support.v4.widget.DrawerLayout>
app_bar_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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"
...>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
...>
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:gravity="top"
.../>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/fragment_container"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>
So...One Nav menu, one App/Tool Bar, multiple fragments

Why do you specifically want a separate toolbar for each fragment?
You can easily change the toolbar view for each fragment.
In your function to switch fragments -
public void selectDrawerItem(MenuItem item) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction;
switch (item.getItemId()) {
case R.id.nav_home :
getSupportActionBar().setCustomView(R.layout.home_nav_bar);
fragmentClass = HomeFragment.class;
break;
case R.id.nav_settings :
getSupportActionBar().setCustomView(R.layout.settings_nav_bar);
fragmentClass = SettingsFragment.class;
break;
}
fragment = (Fragment) fragmentClass.newInstance();
fragmentManager.popBackStack(null,
FragmentManager.POP_BACK_STACK_INCLUSIVE);
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
So you can easily use the same toolbar and customize it according to your requirements for each fragment.

It can be done in a quite straightforward way.
First create an activity with a drawerlayout.
Second create a container viewpager inside the activity to hold
the fragments
Third implement a listener on your viewpager that will set the
relevant toolbar based on the fragment on display.
Let me illustrate by relevant XMLs and code
First the Drawerlayout XML for the main activity
<?xml version="1.0" encoding="utf-8"?>
<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_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="#layout/app_bar_landing_page"
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_landing_page"
app:menu="#menu/activity_landing_page_drawer" />
</android.support.v4.widget.DrawerLayout>
Please note the container layout app_bar_landing_page. Now the XML for this
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.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"
tools:context="me.veganbuddy.veganbuddy.ui.LandingPage">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:logo="#drawable/vegan_buddy_menu_icon"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/container_for_fragments"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
Note the viewpager which will act as container for fragments. Now the OnPageChangeListener on the viewpager.
mViewPager = (ViewPager) findViewById(R.id.container_for_fragments);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
switch (position+1){
case 0:setSupportActionBar(aToolbar);
break;
case 1:setSupportActionBar(bToolbar);
break;
case 2:setSupportActionBar(cToolbar);;
break;
case 3:setSupportActionBar(dToolbar);
break;
default:
break;
}
}
Let me know if any further clarification is needed

The simplest approach I would suggest is to use callbacks to activity. Whenever each fragment loads in the activity, arrange a callback to the activity and load the appropriate toolbar in the activity.
Have separate toolbar xmls in your layout folder. Use the include tag to put the toolbars in your activity. Keep only 1 toolbar visible at a time. When the fragment callbacks come to your activity make the necessary one visible.

It's very simple. Besides the onclick action for the Category fragment is taking you into a new activity, not a Fragment. Now, since drawer layout is in parent activity with navigation view and without toolbar then in the first drawer fragment is a tablayout having four tabs with viewpager and a toolbar on the top and inside one tab i.e HOME is the TOP CHARTS, CATEGORIES, EDITORS. Each toolbar must be implemented in each fragment layout and not in the activity layout since you want different toolbars for each fragment. Note that Toolbar is not a property of Fragment but it's a property of ActionBarActivity or AppCompatActivity, then in the onCreateView, of the fragment that's holding the HOME, GAMES, MOVIES, MUSIC, put down these codes.
public class Drawer1Fragment extends Fragment{
public Drawer1Fragment () {}
TabLayout tabLayout;
Toolbar toolbar;
DrawerLayout drawerLayout;
ViewPager viewPager;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View myChildRoot = inflater.inflate(R.layout.child_fragment_attachment, container, false);
tabLayout = myChildRoot.findViewById(R.id.tab_layout);
viewPager= myChildRoot.findViewById(R.id.container_viewPager);
toolbar = myChildRoot.findViewById(R.id.toolbar);
drawerLayout = getActivity().findViewById(R.id.drawer_layout);
((AppCompatActivity)requireActivity()).setSupportActionBar(toolbar);
((AppCompatActivity)requireActivity()).getSupportActionBar().setTitle(getActivity().getResources().getString(R.string.app_name));
((AppCompatActivity)requireActivity()).getSupportActionBar().setHomeButtonEnabled(true);
((AppCompatActivity)getParentFragment().requireActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(getActivity(),drawerLayout,toolbar,R.drawable.icons,R.string.app_name);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
// The back arrow of a toolbar in fragment is implemented below
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
if(!drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.openDrawer(GravityCompat.START);
} else {
getActivity().finish();
}
}
});
return myChildRoot;
}
}

Related

How to fix overlapping of previous fragment's collapsing toolbar and current fragment's content?

I'm new to android, and want to find solution for the following situation:
I have implemented fragment called profile, In which I have collapsing toolbar and TabLayout. Whenever I clicked on any of the button of current fragment, It will display next page as a new fragment accordingly.Next fragment have it's own toolbar.
Problem: Whenever I scroll the content, previous fragment Collapsing Toolbar appears on top. It overlaps the current fragment.
I have tried the solution using Framelayout and "fitSystemWindows = true".Another solution I have tried is giving "clickable=true" to next fragment. None of them helped me. Where I made a mistake?
Here's the overview of my code:
ProfileFragment is loaded from MainActivity which has bottom navigation view.
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_profile:
ProfileFragment f5=new ProfileFragment();
FragmentTransaction ft5= getSupportFragmentManager().beginTransaction();
ft5.replace(R.id.fragment_container,f5,"");
ft5.commit();
return true;
}
return false;
}
};
activity_main.xml
<LinearLayout
android:id="#+id/container"
tools:context="com.work.workapp.MainActivity">
<FrameLayout
android:id="#+id/fragment_container">
</FrameLayout>
<android.support.design.widget.BottomNavigationView/>
</LinearLayout>
profile_fragment.xml
<android.support.design.widget.CoordinatorLayout
android:id="#+id/profile_main">
<android.support.design.widget.AppBarLayout
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:fitsSystemWindows="true"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<LinearLayout
android:fitsSystemWindows="true"
app:layout_collapseMode="parallax">
<ImageView/>
<TextView/>
</LinearLayout>
<android.support.v7.widget.Toolbar>
<RelativeLayout>
<!-- Settings Button -->
<!-- Edit Button -->
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
<android.support.design.widget.TabLayout/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
<FrameLayout
android:id="#+id/container_profile"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.design.widget.CoordinatorLayout>
profile-toolbar
collapse toolbar - Tab post
tab_post and tab_work Adapter files:
/* Button click event from post Tab of tablayout*/
myViewHolder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
RequestsFragment req_list = new RequestsFragment();
FragmentTransaction ft = ((FragmentActivity)mContext).getSupportFragmentManager().beginTransaction();
ft.replace(R.id.container_profile, req_list, "");
ft.addToBackStack(null).commit();
}
});
When Click on "5" - button on Post tab, following fragment displayed:
Button click on Post tab
When scroll on above fragment, previous fragment's collapsed toolbar appears on new fragment:
content and toolbar overlaps
No error message appears. App is successfully running. I want to remove this Overlapping.

fragment of fragments toolbar title setting

I have one Activity and lots of fragments switch between this Activity, i set the toolbar title just in this Activity , like this :
this Activity:
#Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.logIn){
switchFragment(LogInFragment.newInstance());
//when i switch fragment , i change the tile by this code
toolbar.setTitle(R.string.pageLogIn);
drawerLayout.closeDrawer(GravityCompat.START);
}
if (id == R.id.singUp){
switchFragment(SignUp.newInstance());
toolbar.setTitle(R.string.singUp);
drawerLayout.closeDrawer(GravityCompat.START);
}
}
private void switchFragment(Fragment fragment) {
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.mainFrame, fragment, null);
//transaction.addToBackStack(null);
transaction.commit();
}
and this my Activity layout:
<android.support.v4.widget.DrawerLayout 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:id="#+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.user.taiwandigestionsociety_v11.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF">
<android.support.v7.widget.Toolbar
android:id="#+id/toolBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:theme="#style/ToolBarStyle"
android:background="#drawable/actionbar">
</android.support.v7.widget.Toolbar>
<FrameLayout
android:id="#+id/mainFrame"
android:layout_gravity="end"
android:layout_width="match_parent"
android:layout_height="match_parent">
</FrameLayout>
</android.support.design.widget.AppBarLayout>
<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="#android:color/transparent"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
My question is one of fragments has a button that it will switch to new fragment, i can't switch the toolbar title by the Activity java .
I try another way to set the function to call the Activity switch function, the app will crash .
I try like this:
public class Welcome extends Fragment implements View.OnClickListener {
#Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.welcomeLogin){
MainActivity mainActivity=new MainActivity();
mainActivity.switchFragment(ActivityHomePage.newInstance());
}
}
}
How can i set the fragment toolbar title like those fragments ?
Create One Method in Activity :
public void setToolBar(String title) {
getSupportActionBar().setTitle(title);
}
And call this method in onCreateView of Fragment :
((MainActivity) getActivity()).setToolBar(title);
Do not create instance of Activity like this! Rather pass your context of MainActivity to the Fragment then use that to change.
- MainActivity mainActivity=new MainActivity();
- mainActivity.switchFragment(ActivityHomePage.newInstance());
First of defined main activity
private HomeActivity activity;
after set values "onCreate" method
activity = (HomeActivity) getActivity();
set toolbar values:
HeaderBar headerBar;
headerBar = (HeaderBar) view.findViewById(R.id.headerBar);
Example i hv set right side image in tital bar:
headerBar.ivRight.setImageResource(R.mipmap.save);

Android- FragmentTransaction.replace() works only once

I'm using a navigation drawer along with a SwipeRefreshLayout for the main content and when the user selects a menu item in the navigation drawer, I want to replace the fragment inside the SwipeRefreshLayout with another fragment.
This is what my onNavigationItemSelected() looks like:
// Handle navigation view item clicks here.
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
selectedNavItem = item.getItemId();
if(selectedNavItem == R.id.nav_files){
filesFragment = new FilesFragment();
fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.swipeLayout,filesFragment,"files");
transaction.commit();
} else if(selectedNavItem == R.id.nav_accounts){
accountsFragment = new AccountsFragment();
fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
transaction.replace(R.id.swipeLayout,accountsFragment,"accounts");
transaction.commit();
}
return true;
But this never works. When I click an item in the nav drawer, the fragment is replaced by a blank screen. My onCreate method also uses FragmentTransaction.replace() but that seems to work fine.
I also tried FragmentTransaction.remove() and then FragmentTransaction.add() but even that doesn't seem to work.
Edit: Layout files:
Layout of the content view of the navigation drawer:
<android.support.v4.widget.SwipeRefreshLayout
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:context="com.harshallele.cloudpool.MainActivity"
tools:showIn="#layout/app_bar_main"
android:id="#+id/swipeLayout">
</android.support.v4.widget.SwipeRefreshLayout>
This is included inside another layout file which contains a CoordinatorLayout containing the toolbar.That file, in turn, is inside the main layout file of the activity inside a android.support.v4.widget.DrawerLayout
(Basically, this is the Navigation Drawer Activity provided by Android Studio when adding an Activity)
Layout for FilesFragment:
<FrameLayout 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"
tools:context=".fragments.FilesFragment">
<android.support.v7.widget.RecyclerView
android:id="#+id/fileListView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
/>
<ProgressBar
android:id="#+id/itemsLoadingProgress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
style="?android:attr/progressBarStyleHorizontal"
android:indeterminateOnly="true"
android:visibility="invisible"
/>
</FrameLayout>
Layout for AccountsFragment(this is just the default blank fragment, because i haven't finished this yet):
<FrameLayout 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"
tools:context="com.harshallele.cloudpool.fragments.AccountsFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="#string/hello_blank_fragment" />
</FrameLayout>
Edit 2:
AccountsFragment:
public class AccountsFragment extends Fragment {
public AccountsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_accounts, container, false);
}
}
With just this bit of code we can't help you so much. The problem can be that:
The FilesFragment and AccountsFragment aren't initialized in the right way;
The Layout with id swipeLayout can have visibility = gone;
The Layout of FilesFragment and AccountsFragment can be empty;
This are just some of the infinite reason why your code doesn't work properly so please share more code about the two Fragments and relative XML.

Collapsing Toolbar Layout using same toolbar on differents fragments depending on behaviour

I've trying to update my app by giving some Material Design behaviour. Until now my app have a navigation drawer and a MainActivity that loads the desire fragment based on the item click in the drawer menu (as follows:)
When you click in "Consejos" it replace the fragment with the desire content as follows
MainActivity
private void selectItem(String title, int id) {
Bundle args = new Bundle();
args.putString(PlaceholderFragment.ARG_SECTION_TITLE, title);
Fragment fragment = PlaceholderFragment.newInstance(title);
fragment.setArguments(args);
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager
.beginTransaction()
.replace(R.id.main_content, fragment)
.commit();
switch (id) {
case R.id.nav_localizacion:
//Snackbar.make(mSnackBarView, R.string.menu_localization, Snackbar.LENGTH_SHORT).show();
mCurrentSelectedPosition = 0;
LocalizacionFragment fragment_localizacion = new LocalizacionFragment();
// fragmentManager = getSupportFragmentManager();
// Snackbar.make(mSnackBarView, R.string.menu_localization, Snackbar.LENGTH_SHORT).show();
fragmentManager
.beginTransaction()
.replace(R.id.main_content, fragment_localizacion)
.commit();
break;
case R.id.nav_productos:
Snackbar.make(mSnackBarView, R.string.menu_productos, Snackbar.LENGTH_SHORT).show();
mCurrentSelectedPosition = 1;
fragmentManager
.beginTransaction()
.replace(R.id.main_content, fragment)
.commit();
break;
case R.id.nav_consejos:
Snackbar.make(mSnackBarView, R.string.menu_consejos, Snackbar.LENGTH_SHORT).show();
mCurrentSelectedPosition = 3;
ConsejosFragment fragment_consejo = new ConsejosFragment();
// final Fragment fragment_consejo = new ConsejosFragment();
fragmentManager
.beginTransaction()
.replace(R.id.main_content, fragment_consejo)
.commit();
// getSupportFragmentManager().beginTransaction().add(R.id.main_content, fragment_consejo).commit();
break;
default:
break;
}
drawerLayout.closeDrawers(); // Cerrar drawer
setTitle(title); // título actual
}
It opens this:
Then, if you click on "Recetas" again replaces the fragment with the desire content:
But here is the thing, if you click on a item I want to open another fragment and use the AppBarLayout along with CollapsingToolbarLayout to show an image with the recipe.
This is the layout of the recipe content description:
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/main_content_recetas"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="#dimen/detail_backdrop_height"
android:fitsSystemWindows="true"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="#+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="#drawable/redono_ternera_mechado"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar_view"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingTop="24dp">
<include layout="#layout/card_layout" />
<include layout="#layout/card_layout" />
<include layout="#layout/card_layout" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
This is the code of the RecipeDescription Fragment
public class RecetaViewFragment extends Fragment {
private Context context;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/* Inflamos el layout */
View v = inflater.inflate(R.layout.recetas_descripcion_layout, container, false);
ImageView imageView = (ImageView) v.findViewById(R.id.backdrop);
Picasso.with(context).load(R.drawable.sopa_goulash_ternera).into(imageView);
Toolbar toolbar = (Toolbar) v.findViewById(R.id.toolbar_view);
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
if (toolbar != null) {
toolbar.setSubtitle("Descripción");
}
context = v.getContext();
return v;
}
But this is what happend when running the app:
It has the collapse toolbar embedded in the original toolbar, my question is if my approach isn't the right approach. I mean, I have to only have one toolbar and then applied or not the collapsing behaviour whether I need it or not, or I have to find a way for hiding the original toolbar and using this one (but what happens when I want to give proper back navigation to my app?)
Thank you, please ask me for more code if need it
In my case I am having a similar problem.
MY CASE:
I want a Toolbar in the Activity, since I have a Navigation Drawer, but also want to use the Collapsing Toolbar in Fragment.
I just did one change which I am happy with.
In the Fragment Toolbar I added this:
android:layout_height="0dp"

Using navigationView with tabLayout

So I've recently been working on updating my app to use the new material design support library. My application has one main activity with a drawerLayout and navigation view. The main content of app is shown in a frameLayout, through fragments. However, I am trying now to add material tabs to one of the navigation drawer's fragments. However, I am not sure how to implement this while keeping my fragments in the nav drawer functioning. A good example of what I am trying to achieve is shown below:
In this app (Google play music), only some of the navigation drawer's items have tabs while others do not. So my question is, how would I implement this? (Not looking for code, just an overview of how my layout should be organized)
To recap/clarify:
I have a main layout with a frameLayout (for my app's content), and a navigationView (for navigating the different item fragments). I then have a listener which replaces the main layout's frameLayout with the item's respective fragment. Now, I need to add tabs to just one of these fragments (to navigate between 4 other fragments). I am also using a toolbar which I include as a separate layout.
Any advice is appreciated. I'm sorry if my description is a little confusing; I will clarify any necessary details.
Ok suppose your NavigationView has two options, the first one displays the fragment with tabs (tab layout) and the second one displays just a fragment with a toolbar. You have two options then:
You can have a main layout with just a frame layout and replace it with all what you want
You can have a main layout with coordinator layout -> app bar -> toolbar -> tab layout and a frame layout to put content
I prefer the second option to avoid having to always configure the toolbar so this is what I did once:
<!-- layout_main -->
<android.support.v4.widget.DrawerLayout
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:fitsSystemWindows="true">
<android.support.design.widget.CoordinatorLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways"/>
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:tabGravity="fill"
app:tabMode="fixed" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
<!-- The NavigationView -->
<fragment
android:id="#+id/navigation_fragment"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:name="some.path.to.the.NavigationViewFragment"
tools:layout="#layout/fragment_navigation_view" />
</android.support.v4.widget.DrawerLayout>
As you see I change the visibility of TabLayout to "gone" so that the fragment with tabs take care to set as visible. The Fragment with the tabs just have the ViewPager in the Layout:
<!-- fragment_with_tabs -->
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Now the fragment with tabs initialize the ViewPager with the fragments for each page:
#Override
public onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// The getChildFragmentManager() is Very important! Because fragments inside fragments are
// not supported with the tipical fragmentManager, it requires NestedFragments and those
// uses a childFragmentManager(). In other case a strange behaviour occurs
ViewPagerAdapter adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(new TabOneFragment(), "Tab 1");
adapter.addFragment(new TabTwoFragment(), "Tab 2");
viewPager.setAdapter(adapter);
tabLayout = (TabLayout) getActivity().findViewById(R.id.tab_layout);
tabLayout.setVisibility(View.VISIBLE);
tabLayout.setupWithViewPager(viewPager);
}
And finally do whatever you want in your TabFragments, this works fine for me and I hope this be useful for you too. Sorry for some problem with code syntax, I develop android with Kotlin and not with Java.
I can't recommend what Yiyo suggested. If you are going to have Fragments with different layouts, you should let the Fragments customize these layouts in the XML. This is why the introduction of Toolbar made so much sense for Android development. In the future, you might even have more requirements that differ between each Fragment. Some of them might not want a Toolbar, some of them might need another View above the Toolbar, some of them will have a RecyclerView that you would like to be accessible to the CoordinatorLayout and AppBar so that the scrolling behavior works properly.
I recommend you to put only a FrameLayout as the content of your DrawerLayout (as Yiyo mentioned in point 1). Here you will load each Fragment from the callbacks of the NavigationView.
<android.support.v4.widget.DrawerLayout
...
android:fitsSystemWindows="true"
>
<FrameLayout
android:id="#+id/drawer_content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.NavigationView
...
/>
</android.support.v4.widget.DrawerLayout>
In each Fragment's XML you will put, if required by that Fragment, a Toolbar. In your tabbed Fragment's XML you will put the TabLayout, and if you so wish, the CoordinatorLayout and AppBarLayout. From each Fragment that has a Toolbar, you will set the Toolbar as the ActionBar:
Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.setSupportActionBar(toolbar);
That's all there is to it. Of course you don't want to repeat yourself in every Fragment, so you can, for example, put this code in a DrawerFragment and subclass it for fragments with a Toolbar. You will also want to put your Toolbar XML configuration in a single file and include it in the Fragment's XML <include layout="#layout/toolbar" />. Or you might want to remove the Toolbar from some fragments, or change its color, theme, etc.
You can do it like this. I have checked by doing it myself and it works very well
Step 1 : Create a layout of your main activity like this
<android.support.design.widget.AppBarLayout
android:id="#+id/appBarLayout" android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar" android:layout_width="match_parent"
android:layout_height="wrap_content" android:background="#color/blue"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:titleTextAppearance="#style/TextAppearance.AppCompat.Small"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="#+id/tab_layout" style="#style/FreeWiFiTabLayout"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_gravity="center" android:background="#color/blue"
android:visibility="gone" android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/wifi_type_pager" android:layout_width="match_parent"
android:layout_height="match_parent" android:clipToPadding="false"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
<fragment android:id="#+id/navigation_drawer"
android:name="com.easyway.freewifi.NavigationDrawerFragment"
android:layout_width="wrap_content" android:layout_height="match_parent"
android:layout_gravity="start|bottom" android:layout_marginTop="?attr/actionBarSize"
tools:layout="#layout/navigation_drawer_fragment" />
Step 2 :
In your activity you need to set onpagechangelistener on your viewpager:
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if(position ==0){
tabLayout.setVisibility(View.GONE);
}else{
tabLayout.setVisibility(View.VISIBLE);
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
After this you need to add
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
Step 3 :
This is how you can make your adapter for viewpager :
public class WiFiPagerAdapter extends FragmentPagerAdapter {
private final List registeredFragments = new ArrayList<>();
public WiFiPagerAdapter(final FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(final int pos) {
Fragment fragment;
fragment = WiFiFragment.newInstance(pos);
registeredFragments.add(pos, fragment);
return fragment;
}
#Override
public int getCount() {
return tabLayout.getTabCount();
}
public List<Fragment> getRegisteredFragmentsList() {
return registeredFragments;
}
#Nullable
public Fragment getRegisteredFragment(final int position) {
final Fragment wr = registeredFragments.get(position);
if (wr != null) {
return wr;
} else {
return null;
}
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
for (int i = 0; i < registeredFragments.size(); i++) {
WiFiFragment wiFiFragment = ((WiFiFragment) registeredFragments.get(i));
wiFiFragment.setWiFiFragmentRecyclerViewAdapter();
}
}
}

Categories

Resources