I have implemented bottom navigation in Xamarin Android. I need to show different screens when clicking each icon in bottom navigation bar.
I is working fine in main activity but on Selection on bottom navigation item, how to show new screen while keeping bottom navigation visible.
When clicking icon in bottom navigation bar I setContent again so bottom navigation bar hides(as new content is loaded that does not have bottom navigation bar).
I have very little experience in Xamarin Android so don't know if there is anything like layout page which can hold bottom navigation.
I read about Framelayout and fragments but don't know how to implement with bottom navigation. Any help would be really appreciated.
The bottom bar is added to the first activity . If you change the activity, on selection the bottom bar would disappear.
You need to add view pager with fragment to achieve it
You can check out this tutorial
You can also see this code sample
Since you are changing the ContentView of your Activity it is disappearing:
You can follow the below steps to achieve a BottomNavigationView:
Since we are dealing with Fragments, I will change my MainActivity base class to Android.Support.V7.App.AppCompatActivity, and yes we will be using Android Support library V4.Since I am dealing with Fragments, I will change my MainActivity base class to Android.Support.V7.App.AppCompatActivity, and yes we will be using Android Support library V4 and V7. Check this blog for understanding support libraries
public class MainActivity : Android.Support.V7.App.AppCompatActivity
Create a layout for our MainActivity, We will add a FrameLayout to hold our Fragment, a ViewPager, and a BottomNavigationView from the Android.Support.Design library, Something like below:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/fragment_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottom_navigation" />
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/bottom_navigation" />
<android.support.design.widget.BottomNavigationView
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_gravity="start"
android:layout_alignParentBottom="true"
android:background="#android:color/white"
app:menu="#menu/navigation_main" />
</RelativeLayout>
Create a layout for Fragment as well. I will keep it simple with an icon and a label, you can keep whatever you desire here:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageView"
android:src="#drawable/abc_ic_star_black_48dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Fragment"
android:textAlignment="center"
android:textSize="#dimen/abc_text_size_display_1_material"
android:layout_below="#id/imageView"
android:layout_centerVertical="false" />
</RelativeLayout>
Let’s get to that bottom navigation. First, we need the navigation items (tabs) for the BottomNavigationView, we will add a navigation menu for this.
navigation_main.xml //Name of xml file
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:orderInCategory="0"
android:id="#+id/menu_genres"
android:enabled="true"
android:title="Genres"
android:icon="#drawable/tab_genres"
app:showAsAction="always" />
<item
android:orderInCategory="1"
android:id="#+id/menu_titles"
android:enabled="true"
android:title="Titles"
android:icon="#drawable/tab_titles"
app:showAsAction="always" />
<item
android:orderInCategory="2"
android:id="#+id/menu_stream"
android:enabled="true"
android:title="Stream"
android:icon="#drawable/tab_stream"
app:showAsAction="always" />
<item
android:orderInCategory="3"
android:id="#+id/menu_showtimes"
android:enabled="true"
android:title="Showtimes"
android:icon="#drawable/tab_showtimes"
app:showAsAction="always" />
</menu>
Notice the orderInCategory, this is the order of tab items from left to right.
Alright, Now We have put together the views we will be working with. Now let’s get to that BottomNavigationView.
In MainActivity get hold of the BottomNavigationView and set it up.
bottomNavigationView= FindViewById<BottomNavigationView>(Resource.Id.bottom_navigation);
Also, the BottomNavigationView hides the labels if the tabs grow more than 3. So, let’s change that. Add this helper method to your code and call it when setting up the BottomNavigationView like this,
RemoveShiftMode(_navigationView);//Below the FindViewById
private void RemoveShiftMode(BottomNavigationView view) // a Method in the Activity
{
var menuView = (BottomNavigationMenuView) view.GetChildAt(0);
try
{
var shiftingMode = menuView.Class.GetDeclaredField("mShiftingMode");
shiftingMode.Accessible = true;
shiftingMode.SetBoolean(menuView, false);
shiftingMode.Accessible = false;
for (int i = 0; i < menuView.ChildCount; i++)
{
var item = (BottomNavigationItemView)menuView.GetChildAt(i);
item.SetShiftingMode(false);
// set checked value, so view will be updated
item.SetChecked(item.ItemData.IsChecked);
}
} catch (System.Exception ex) {
System.Diagnostics.Debug.WriteLine((ex.InnerException??ex).Message);
}
}
And now, we should be okay. And that’s it. we are done with setting up the BottomNavigationView. We have not implemented the fragments for each tab yet, so tapping on the tabs won’t present anything. We will present the fragments inside the ViewPager.
Now, let’s set up the ViewPager. First, the adapter,
public class ViewPagerAdapter : FragmentPagerAdapter
{
Fragment[] _fragments;
public ViewPagerAdapter(FragmentManager fm, Fragment[] fragments) : base(fm)
{
_fragments = fragments;
}
public override int Count => _fragments.Length;
public override Fragment GetItem(int position) => _fragments[position];
}
Then, the ViewPager,
// find the view
_viewPager = FindViewById<ViewPager>(Resource.Id.viewpager);
// set the adapter
_viewPager.Adapter = new ViewPagerAdapter(SupportFragmentManager, _fragments);
and that should be it for setting up the ViewPager.
When the user slides between ViewPager views, ViewPager.PageSelected event is fired. Similarly, when the user taps on a tab (navigation menu item) in the BottomNavigationView, the BottomNavigationView.NavigationItemSelected event is fired. We have to link these two events to make the BottomNavigationView and ViewPager dance in sync. Here’s how we’re going to do it.
Declare an event handler for BottomNavigationView and ViewPager as follows,
// wireup the page selection event
_viewPager.PageSelected += ViewPager_PageSelected;
// wire up the selection event
_navigationView.NavigationItemSelected += NavigationView_NavigationItemSelected;
When the ViewPager page is selected, we notify the BottomNavigationView and vice versa. Like this,
private void ViewPager_PageSelected(object sender, ViewPager.PageSelectedEventArgs e)
{
var item = _navigationView.Menu.GetItem(e.Position);
_navigationView.SelectedItemId = item.ItemId;
}
void NavigationView_NavigationItemSelected(object sender,
BottomNavigationView.NavigationItemSelectedEventArgs e)
{
_viewPager.SetCurrentItem(e.Item.Order, true);
}
And that’s it. Now the BottomNavigationView and ViewPager are displaying the selected fragment/page/tab and updating each other with a smooth transition.
One last thing, load fragments for these tabs.
void InitializeTabs()
{
_fragments = new Fragment[] {
TheFragment.NewInstance("Genres", "tab_genres"),
TheFragment.NewInstance("Titles", "tab_titles"),
TheFragment.NewInstance("Stream", "tab_stream"),
TheFragment.NewInstance("Showtimes", "tab_showtimes")
};
}
Related
I'm using Jetpack Navigation version 1.0.0-alpha04 with bottom navigation. It works but the navigation doesn't happen correctly. For example, if I have tab A and tab B and from tab A I go to Page C and from there I go to tab B and come back to tab A again, I will see root fragment in the tab A and not page C which does not what I expect.
I'm looking for a solution to have a different stack for each tab, so the state of each tab is reserved when I come back to it, Also I don't like to keep all this fragment in the memory since it has a bad effect on performance, Before jetpack navigation, I used this library https://github.com/ncapdevi/FragNav, That does exactly what, Now I'm looking for the same thing with jetpack navigation.
EDIT 2: Though still no first class support (as of writing this), Google has now updated their samples with an example of how they think this should be solved for now: https://github.com/googlesamples/android-architecture-components/tree/master/NavigationAdvancedSample
The major reason is you only use one NavHostFragment to hold the whole back stack of the app.
The solution is that each tab should hold its own back stack.
In your main layout, wrap each tab fragment with a FrameLayout.
Each tab fragment is a NavHostFragment and contains its own navigation graph in order to make each tab fragment having its own back stack.
Add a BottomNavigationView.OnNavigationItemSelectedListener to BottomNavigtionView to handle the visibility of each FrameLayout.
This also takes care of your "...I don't like to keep all this fragment in memory...", because a Navigation with NavHostFragment by default uses fragmentTransaction.replace(), i.e. you will always only have as many fragments as you have NavHostFragments. The rest is just in the back stack of your navigation graph.
Edit: Google is working on a native implementation https://issuetracker.google.com/issues/80029773#comment25
More in detail
Let's say you have a BottomNavigationView with 2 menu choices, Dogs and Cats.
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/dogMenu"
.../>
<item android:id="#+id/catMenu"
.../>
</menu>
Then you need 2 navigation graphs, say dog_navigation_graph.xml and cat_navigation_graph.xml.
The dog_navigation_graph might look like
<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/dog_navigation_graph"
app:startDestination="#id/dogMenu">
</navigation>
and the corresponding for cat_navigation_graph.
In your activity_main.xml, add 2 NavHostFragments
<FrameLayout
android:id="#+id/frame_dog"
...>
<fragment
android:id="#+id/dog_navigation_host_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="#navigation/dog_navigation_graph"
app:defaultNavHost="true"/>
</FrameLayout>
and underneath add the corresponding for your cat NavHostFragment. On your cat frame layout, set android:visibility="invisible"
Now, in your MainActivity's onCreateView you can
bottom_navigation_view.setOnNavigationItemSelectedListener { item ->
when (item.itemId) {
R.id.dogMenu -> showHostView(host = 0)
R.id.catMenu -> showHostView(host = 1)
}
return#setOnNavigationItemSelectedListener true
}
All that showHostView() is doing is toggling the visibility of your FrameLayouts that are wrapping the NavHostFragments. So make sure to save them in some way, e.g. in onCreateView
val hostViews = arrayListOf<FrameLayout>() // Member variable of MainActivity
hostViews.apply {
add(findViewById(R.id.frame_dog))
add(findViewById(R.id.frame_cat))
}
Now it's easy to toggle which hostViews should be visible and invisible.
The issue has been resolved by the Android team in the latest version 2.4.0-alpha01 multiple backstacks along with bottom navigation support is now possible without any workaround.
https://developer.android.com/jetpack/androidx/releases/navigation
First, I want to make an edit to #Algar's answer. The frame that you want to hide should have android:visibility="gone" instead of invisible. The reason for that in your main layout you would have something like this:
<LinearLayout 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:orientation="vertical"
tools:context=".ui.activity.MainActivity">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar_base" />
<FrameLayout
android:id="#+id/frame_home"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
>
<fragment
android:id="#+id/home_navigation_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/home_nav" />
</FrameLayout>
<FrameLayout
android:id="#+id/frame_find"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:visibility="gone">
<fragment
android:id="#+id/find_navigation_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/find_nav" />
</FrameLayout>
...
</LinearLayout>
If you wrap your main in a LinearLayout, setting the frame to invisible still make that frame counts, so the BottomNavigation wont appear.
Second, you should create a NavHostFragment instance (ie: curNavHostFragment) to keep track of which NavHostFragment is being visible when a tab in BottomNavigation is clicked. Note: you may want to restore this curNavHostFragment when the activity is destroyed by configuration's changes. This is an example:
#Override
protected void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
//if this activity is restored from previous state,
//we will have the ItemId of botnav the has been selected
//so that we can set up nav controller accordingly
switch (bottomNav.getSelectedItemId()) {
case R.id.home_fragment:
curNavHostFragment = homeNavHostFragment;
...
break;
case R.id.find_products_fragment:
curNavHostFragment = findNavHostFragment;
...
break;
}
curNavController = curNavHostFragment.getNavController();
I have two activities with same bottom bar.
The problem is when i call to startActivity from Activity A to Activity B has some blink and is not looking so smooth.
for example what I want is like Activity with a container with two fragments and the activity has the bottom bar so this will not change the bottom bar.
I know Activity with Fragments can help me with that but is too complicated to change it on my project so is the last option for me.
I find one more option to do it with SharedElements transition but is supported only from api 21 (Lollipop).
This is my activities and I need the LinearLayout on bottom stay sticky when i change it to Activity B.
You can set up activity animations:
startActivity();
overridePendingTransition(R.anim.hold, R.anim.fade_in);
Please, refer to this answer: stackoverflow
you can remove the defulat transtion between activites.
try this under yourProject/res/values/styles.xml:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowAnimationStyle">#null</item>
</style>
If you want the same instance you will have to use fragments.
If not you could just put that LinearLayout to both layout files.
Which one do you want?
You need create a layout and include ex. bottombar.xml in layout folder and create the layout.
<include layout="#layout/bottombar"/>
if you dont want look delay in change you need use fragments.
To manage fragment, i recommended use FragNav
With this library manage fragments its very easy, remove animation is not solution to your problem
I have made an Activity with two fragments.
In Activity class ,I have write this code for commonBottomSheet :-
BottomSheetBehavior mBottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.bottom_pannel_layout));
mBottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
mBottomSheetBehavior.setBottomSheetCallback(mBottomSheetCallback);
In Activity xml file in Co-ordinator layout I have included below layout :-
<include layout="#layout/bottom_sheet_pannel"/>
In CommonBottomSheetFragment, you can create your layout .
And my xml file (bottom_sheet_pannel) for bottomSheet is like this :-
<?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:id="#+id/bottom_pannel_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:behavior_peekHeight="45dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior">
<ImageView
android:id="#+id/grabber_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="#drawable/ic_vector_slider_grabber"
android:tint="#color/colorTint" />
<fragment
android:id="#+id/rf_common_details_fragment"
android:layout_marginTop="#dimen/margin_10"
android:name="com.fragment.CommonBottomSheetFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
you can change state of bottomSheet with below callBack :-
private BottomSheetBehavior.BottomSheetCallback mBottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() {
#Override
public void onStateChanged(View bottomSheet, int newState) {
// do what you want on state change
}
#Override
public void onSlide(View bottomSheet, float slideOffset) {
}
};
So, I have an activity with navigation view. By click on its item I change fragment in activity. All fragment have the same toolbar. But one have this toolbar and TabLayout to it. I would like to know what is better to declare toolbar once on activity like this
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/toolbar" />
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar" />
</RelativeLayout>
or declare it in each fragment.
The disadvantage of the first method is default toolbar shadow. When I add tabs in fragment, shadow looks like
When I tried 2 solution. All my toolbar was with back icon instead drawer animated logo.
Thanks.
I had the exact same problem. This is how I solved it:
Move the toolbars to the fragments like you suggested (so you won't have a shadow separating the two). This allows for a way more flexible way to implement (different) toolbars in your layouts too.
Replace the Toolbar's navigation icon by a custom one like this:
toolbar.setNavigationIcon(R.drawable.ic_action_menu);
(I used the Android Asset Studio to easily create an icon with the preferred color)
Now open the NavigationView with the new menu(home) icon. You can do this through the MainActivity (the one with the NavigationView). Create a public method in that Activity that opens the drawer:
public void openDrawer(){
mDrawerLayout.openDrawer(Gravity.LEFT);
}
Now call this method in the OnOptionsItemSelected in your fragments like this:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// handle item selection
switch (item.getItemId()) {
case android.R.id.home: //Menu icon
((MainActivity)getActivity()).openDrawer();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
That's it. Of course the downside is that you must implement the Toolbar in each Fragment. However, this is the only way (that I know of) that enables you to have the Toolbar (+TabLayout) in a Fragment and still be able to control your NavigationView.
You can use AppBarLayout from design support library like:
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
...
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
...
/>
</android.support.design.widget.AppBarLayout>
and then you can change visibility of tablayout.
For more information about desing layout library : link
I've started to change from using ActionBarActivity to AppCompatActivity, but I've also started using the Toolbar as well instead of a standard ActionBar.
However, in one of my activities which has a swiping tab type of layout, the following line seems to be deprecated:
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
Although I have looked at some other answers on Stack Overflow regarding this, is there any built-in way of changing this to support using the Toolbar. If so, could you explain exactly how I would go about changing it? How would deprecated methods like onTabSelected be changed?
Also, I've noticed that the Google Play Music app has what looks like an extended toolbar/section underneath the tabs (see this image for what I am talking about). How would I be able to have that type of layout?
Thanks in advance.
So after a few days of lots of research, and looking through GitHub, I finally managed to solve my problem.
Steps to updating the ActionBar tabs to Toolbar tabs using AppCompatActivity:
UPDATE: After Friday 29th May 2015:
Thankfully, using a TabLayout with the Toolbar has become much simpler since the announcement of the Android Design Support Library in Google I/O 2015.
We no longer need to download custom view classes, and this is something Google really should have done a long time ago.
From the Android Developers' Blogspot post on the Android Design Support Library:
Tabs:
Switching between different views in your app via tabs is not a new concept to material design and they are equally at home as a top level navigation pattern or for organizing different groupings of content within your app (say, different genres of music).
The Design library’s TabLayout implements both fixed tabs, where the view’s width is divided equally between all of the tabs, as well as scrollable tabs, where the tabs are not a uniform size and can scroll horizontally. Tabs can be added programmatically:
TabLayout tabLayout = ...;
tabLayout.addTab(tabLayout.newTab().setText("Tab 1"));
However, if you are using a ViewPager for horizontal paging between tabs, you can create tabs directly from your PagerAdapter’s getPageTitle() and then connect the two together using setupWithViewPager(). This ensures that tab selection events update the ViewPager and page changes update the selected tab.
Prior to Google I/O 2015:
Firstly, I downloaded the SlidingTabLayout.java and SlidingTabStrip.java files from Google's I/O Conference app on GitHub. These would be the views that would be used in the tab layout, so I created a folder with my other Java activities called 'view' and placed them there.
Next, I edited my activity layout .xml to look a bit like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ads="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.mycompany.myapp.MyActivity" >
<!-- This is the Toolbar with the tabs underneath -->
<LinearLayout android:id="#+id/detail_headerBar"
style="#style/HeaderBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include android:id="#+id/detail_toolbar" layout="#layout/toolbar" />
<com.mycompany.myapp.view.SlidingTabLayout
android:id="#+id/sliding_tabs"
android:background="?attr/colorPrimary"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- This is the ViewPager (which I had used before) and
it would be responsible for the swiping to change layouts -->
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/detail_headerBar"
android:layout_above="#+id/detail_adView" />
<!-- I also had an AdView in my layout,
but this is not necessary for creating tab layouts -->
<com.google.android.gms.ads.AdView
android:id="#+id/detail_adView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
ads:adSize="SMART_BANNER"
ads:adUnitId="#string/banner_ad_unit_id" >
</com.google.android.gms.ads.AdView>
</RelativeLayout>
The line which references the Toolbar (<include android:id="#+id/detail_toolbar" layout="#layout/toolbar" />), is referencing the following layout (for those who aren't sure how to use the Toolbar yet):
<android.support.v7.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_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
And in both of the .xml layout files above, ?attr/colorPrimary, refers to the primary colour of my app (which I had defined in a style).
Also, in the first layout, the style I had mentioned as #style/HeaderBar refers to the following:
<style name="HeaderBar">
<item name="android:background">?colorPrimary</item>
<item name="android:elevation">4dp</item>
<!-- You may have to override this in a v21 version of this file -->
</style>
Before I started setting up the layouts in Java, I had to make sure to change the package names in SlidingTabLayout.java and SlidingTabStrip.java corresponding to where they were placed. In my case, I used: package com.mycompany.myapp.view; in both of these files.
Now, in my Activity (which was extending AppCompatActivity), I first added the following in the onCreate method:
Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar);
setSupportActionBar(toolbar);
This would be reponsible for displaying the Toolbar.
Then I setup the ViewPager and SlidingTabLayout parts:
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mViewPager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
mSlidingTabLayout = (SlidingTabLayout) findViewById(R.id.sliding_tabs);
mSlidingTabLayout.setSelectedIndicatorColors(getResources().getColor(R.color.tab_line));
mSlidingTabLayout.setDistributeEvenly(true);
mSlidingTabLayout.setViewPager(mViewPager);
The colour 'tab_line' was a colour I had declared in color.xml which would be the colour of the tab line indicator. Also note that the variables above were global which I defined previously in this activity:
SlidingTabLayout mSlidingTabLayout;
ViewPager mViewPager;
The final thing to do was to setup the ViewPagerAdapter which I had called eariler. This would be responsible for changing the page depending on which tab was selected. I used the following:
public class ViewPagerAdapter extends FragmentPagerAdapter {
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
// Returns the number of tabs
return 3;
}
#Override
public Fragment getItem(int position) {
// Returns a new instance of the fragment
switch (position) {
case 0:
return new FragmentOne();
case 1:
return new FragmentTwo();
case 2:
return new FragmentThree();
}
return null;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
I hope this was a thorough enough answer for those who are having the same trouble as I did, when switching from ActionBarActivity to AppCompatActivity and starting to use Toolbar instead of ActionBar. If there is anything that is unclear, feel free to comment below.
I'm adding a Navigation Drawer to this app that I am developing and I have scoured the internet; forums, stackoverflow, android developer documentation, and still have not found a great answer for this.
I know that it is possible to do this without using either of these things. What I am wondering is how. The NsMenuAdapter model uses a title, and then there are these functions
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
Which are clearly looking for an action bar. I tried a couple of models that didn't work, the big one I just got done trying is located here How to Add icons adjacent to titles for Android Navigation Drawer (which is related to the link I have below, the project is from gitHub here https://github.com/gabrielemariotti/androiddev/tree/master/NavigationDrawer). Now the key thing is, I am using a custom layout (i.e. Relative Layouts mixed in with Linear Layouts) and I'm really lost on what my next step should be in order to get this to work.
Sidenote: When I only have the ListView in my main_activity.xml (the implementation for the Navigation Drawer) it does properly slide out like it is suppose to. But I cannot for the life of me figure out how to populate it with data. I basically need 3 headers with that will have clickable navigation elements in them, with icons next to the elements.
I turned to this model for most of my insight on how to do this via Relative Layouts http://gmariotti.blogspot.com/2013/05/creating-navigation-drawer.html But they use action/title bars which is what is really throwing me for a loop.
It's quite simple actually. Easier than with ActionBar. I'm writing the answer with almost simplest of layouts
make your xml something like this:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- This is how your main page will look, just 2 buttons -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:onClick="onLeft"
android:text="left" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:onClick="onRight"
android:text="right" />
</RelativeLayout>
<!-- Left Drawer -->
<RelativeLayout
android:id="#+id/whatYouWantInLeftDrawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start" >
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/background_dark" />
<!-- you can have many more widgets here like buttons or labels -->
</RelativeLayout>
<!-- Right Drawer -->
<RelativeLayout
android:id="#+id/whatYouWantInRightDrawer"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="right" >
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_green_light" />
<!-- you can have many more widgets here like buttons or labels -->
</RelativeLayout>
</android.support.v4.widget.DrawerLayout>
Then make your activity something like this:
public class MainActivity extends Activity {
RelativeLayout leftRL;
RelativeLayout rightRL;
DrawerLayout drawerLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// I'm removing the ActionBar.
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
leftRL = (RelativeLayout)findViewById(R.id.whatYouWantInLeftDrawer);
rightRL = (RelativeLayout)findViewById(R.id.whatYouWantInRightDrawer);
drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
}
public void onLeft(View view) {
drawerLayout.openDrawer(leftRL);
}
public void onRight(View view) {
drawerLayout.openDrawer(rightRL);
}
}
That's it. Hope it helps.
I know that it is possible to do this without using either of these things. What I am wondering is how.
Step #1: Follow the instructions for using DrawerLayout, such as the steps in this training guide, skipping anything related to the action bar.
Step #2: There is no step #2.
While DrawerLayout can work with the action bar, it is not required, and actually requires additional setup.
I was trying to add navigation drawer to an already existing activity (Which was without action bar) solution for me was to remove the line:
android:fitsSystemWindows="true"
from <android.support.v4.widget.DrawerLayout in my Activity's xml file.