I recently use AHBottomNavigation which have 5 item in bottom bar for example when
I click Home Button it goes to homeActivty which I have 3 tab bar. Everything until here is ok but I realize when we use AHBottomNavigation we should use fragment but
I need to use activities with bars and show AHBottomNavigation in all of them.
I use AHBottomNavigation in all of my activities to handle this and it work's and all of my activities have AHBottomNavigation but when i change activities,
AHBottomNavigation doesnt work as good as normal and it seems that there is a delay in it.
Is there any better solution for this or please inform me if I'm doing something wrong ?
HomeActivity.class
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
if (drawer != null) {
drawer.setDrawerListener(toggle);
}
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
//[START Tab ]
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
//[*End Tab]
//[Start Bottom N]
bottomNavigation();
}
private void setupViewPager(ViewPager viewPager){
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment1(),"Tab1");
adapter.addFragment(new Fragment2() , "Tab2");
adapter.addFragment(new Fragment3() , "Tab3");
viewPager.setAdapter(adapter);
}
public void bottomNavigation(){
// [START BottomNavigation]
// TODO add other activitys to setOnTabSelectedListener (HOME , SEARCH , ...)
AHBottomNavigation bottomNavigation = (AHBottomNavigation) findViewById(R.id.bottom_navigation);
// Create items
AHBottomNavigationAdapter navigationAdapter = new AHBottomNavigationAdapter(this, R.menu.bottom_navigation);
navigationAdapter.setupWithBottomNavigation(bottomNavigation);
bottomNavigation.setBehaviorTranslationEnabled(true);
bottomNavigation.setAccentColor(Color.parseColor("#3498db"));
bottomNavigation.setCurrentItem(0);
bottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() {
#Override
public boolean onTabSelected(int position, boolean wasSelected) {
switch (position){
case 0 :
break;
case 1 :
// Add
Intent goToAddStuff = new Intent(HomeActivity.this , AddStuffActivity.class);
startActivity(goToAddStuff);
finish();
break;
case 2 :
// Search
break;
case 3:
// Activity's
//My AONActivity have 2 tab too
Intent goToAON = new Intent(HomeActivity.this , AONActivity.class);
startActivity(goToAON);
finish();
break;
case 4:
//Account
break;
}
return true;
}
});
// [*END BottomNavigation]
}
content_home.xml
<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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".HomeActivity"
android:id="#+id/content_id"
tools:showIn="#layout/activity_home">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".HomeActivity">
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</RelativeLayout>
<FrameLayout
android:id="#+id/contentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/bottomBar" />
<include layout="#layout/bottom_navigation" />
</android.support.design.widget.CoordinatorLayout>
bottom_navigation.xml
<com.aurelhubert.ahbottomnavigation.AHBottomNavigation
android:id="#+id/bottom_navigation"
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="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_gravity="bottom">
</com.aurelhubert.ahbottomnavigation.AHBottomNavigation>
I also use AHBottomNavigation but you need due to Google Material Design you need to use Fragments, otherwise you implement it incorrect.
Here how it should be :
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:id="#+id/framelayout_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<com.aurelhubert.ahbottomnavigation.AHBottomNavigation
android:id="#+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
This is some code just to show how is better to work with fragments if you have no idea, just I do not know your background and maybe you do not use it because you feel confused with this.
#Override
public void onTabSelected(int position, boolean wasSelected) {
Log.d(TAG, "Position " + position + " was selected" + wasSelected);
if(!wasSelected) {
getSupportFragmentManager()
.beginTransaction()
.replace(FRAME_LAYOUT,
createFragment(position),
createItemDescription(position))
.addToBackStack(null)
.commit();
}
}
private void createBottomNavigationMenu(int defaultCurrentItem){
for(int i = 0; i<5; i++){
// Create bottom navigation item
AHBottomNavigationItem item =
new AHBottomNavigationItem(createItemDescription(i),
createPicture(i));
// Add bottom navigation item
mBottomNavigation.addItem(item);
}
// Set current item programmatically
mBottomNavigation.setCurrentItem(defaultCurrentItem, true);
// Set background color
mBottomNavigation.setDefaultBackgroundColor(Color.parseColor("#56ABF8"));
// Disable the translation inside the CoordinatorLayout
mBottomNavigation.setBehaviorTranslationEnabled(false);
// Set listener
mBottomNavigation.setOnTabSelectedListener(this);
}
// Factory-method patterns
private Fragment createFragment(int position){
switch (position) {
case 1:
return new SettingsFragment_();
case 2:
return new StatisticsFragment_();
case 3:
return new MainFragment_();
case 4:
return new ForthFragment_();
case 5:
return new ReminderFragment_();
}
throw new IllegalArgumentException();
}
private String createItemDescription(int position){
switch (position){
case 1:
return BOT_NAV_ITEM_SETTINGS;
case 2:
return BOT_NAV_ITEM_STATISTICS;
case 3:
return BOT_NAV_ITEM_MAIN;
case 4:
return BOT_NAV_ITEM_FORTH;
case 5:
return BOT_NAV_ITEM_REMINDERS;
}
throw new IllegalArgumentException();
}
private int createPicture(int position){
switch (position){
case 1:
return R.mipmap.ic_settings;
case 2:
return R.mipmap.ic_statistics;
case 3:
return R.mipmap.ic_water;
case 4:
return R.mipmap.ic_launcher;
case 5:
return R.mipmap.ic_reminders;
}
throw new IllegalArgumentException();
}
I found the Solution :
I create HomeFragment which extent fragment like this :
HomeFragment.class
public class HomeFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
private static int currentItem = 0;
AdapterFragment adapter;
public static HomeFragment newInstance(int someInt) {
HomeFragment frag = new HomeFragment();
Bundle args = new Bundle();
args.putInt("tab", someInt);
frag.setArguments(args);
return frag;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("currentItem", viewPager.getCurrentItem());
}
public static HomeFragment newInstance() {
HomeFragment frag = new HomeFragment();
return frag;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
adapter= new AdapterFragment(getChildFragmentManager());
currentItem=getArguments() != null ? getArguments().getInt("tab") : 0;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/**
*Inflate tab_layout and setup Views.
*/
View rootView = inflater.inflate(R.layout.fragment_home,container,false);
tabLayout = (TabLayout) rootView.findViewById(R.id.tablayout);
viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
/**
*Set an Adapter for the View Pager
*/
if (adapter==null) adapter=new AdapterFragment(getChildFragmentManager());
viewPager.setAdapter(adapter);
viewPager.setCurrentItem( currentItem);
/**
* Now , this is a workaround ,
* The setupWithViewPager dose't works without the runnable .
* Maybe a Support Library Bug .
*/
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return rootView;
}
public class AdapterFragment extends FragmentPagerAdapter {
public AdapterFragment(FragmentManager fm) {
super(fm);
}
/**
* Return fragment with respect to Position .
*/
#Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return new Tab1Fragment();
case 1 : return new Tab2Fragment();
case 2 : return new Tab3Fragment();
}
return null;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "Tab1";
case 1 :
return "Tab2";
case 2 :
return "Tab3";
}
return null;
}
}
And in my
MainActivity
bottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() {
#Override
public boolean onTabSelected(int position, boolean wasSelected) {
switch (position){
case 0 :
// Home
HomeFragment homeFragment = new HomeFragment();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_id, homeFragment)
.commit();
break;
case 1:
break;
}
return true;
}
});
I hope this will help you
Related
I have a tab setup with a VeiwPager and a MainActivity. When one particular tab, "B" is selected I want to Show Fragment B user interface and start doing something.
The method I have found to do this is to use a LocalBroadcastReceiver in Fragment "B" and have it call a method. The broadcast is sent from Main Activity inside the onTabSelected method.
Is this a good approach?
Activity.xml
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
app:tabGravity="fill"
app:tabMode="fixed" />
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Activity.class
TabLayout tabLayout;
ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab);
tabLayout = findViewById(R.id.tabLayout);
viewPager = findViewById(R.id.viewPager);
setUpviewPager();
tabLayout.setupWithViewPager(viewPager);
}
private void setUpviewPager() {
ViewPagerAdpater viewPagerAdapter = new ViewPagerAdpater(getSupportFragmentManager());
viewPager.setAdapter(viewPagerAdapter);
}
private class ViewPagerAdpater extends FragmentPagerAdapter {
ViewPagerAdpater(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new FirsFrag();
case 1:
return new FirsFrag();
case 2:
return new FirsFrag();
default:
return null;
}
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "First Tab";
case 1:
return "Second Tab";
case 2:
return "Third Tab";
default:
return "";
}
}
#Override
public int getCount() {
return 3;
}
#Override
public boolean isViewFromObject(#NonNull View view, #NonNull Object object) {
return view == object;
}
}
Thanks, just run this code, this adapter is FragmentPagerAdpater
so i have the classic viewpager in a tablayout that looks something like this:
My viewPagerAdapter class looks like this:
public class HomePagerAdapter extends FragmentPagerAdapter {
int mNumOfTabs;
public HomePagerAdapter(FragmentManager fm, int NumOfTabs) {
super(fm);
this.mNumOfTabs = NumOfTabs;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabHomeFragment tab1 = new TabHomeFragment();
return tab1;
case 1:
TabShopFragment tab2 = new TabShopFragment();
return tab2;
case 2:
TabMeFragment tab3 = new TabMeFragment();
return tab3;
default:
return null;
}
}
#Override
public int getCount() {
return mNumOfTabs;
}
}
So now on one of the tabs i need to add a fragment on top of it. so its a search fragment really. i do a search in the tab bar and i want the back end search results to appear in only ONE of the tabs (the first one). but i want the search results displayed in a fragment called searchFragmentResults and i want it to be laid out on top of the first tab. Then when user hits the back button it will just go back to the original content in the first tab. Is this possible with view pager ?
so visually when i hit the search icon on the first tabs tabBar it should bring up a searchView and when i search for the users query it should bring up a another fragment with the results but only in the tab that it started from. Here is an example:
i cant call fragtransaction.replace(somecontentview, somefragment); (or its add method) because i did not add them to a contentview. i let the viewpager do it for me. So how is this achieved ?
i figured out how to do this. The tab should be a fragment who's purpose is to only contain other fragments. the idea is based off of this SO. But i had a need to do it for a viewPager. Lets go through the steps. first the viewpager adapter:
public class HomePagerAdapter extends FragmentStatePagerAdapter {
//integer to count number of tabs
int tabCount;
private Fragment mCurrentFragment;
private String[] tabTitles = new String[]{"tab0", "tab1", "tab2", "tab3"};
//Constructor to the class
public HomePagerAdapter(FragmentManager fm, int tabCount) {
super(fm);
this.tabCount = tabCount;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
TabHomeContainerFragment tab1 = new Tab0ContainerFragment();
return tab1;
case 1:
TabShopFragment tab2 = new Tab1ContainerFragment();
return tab2;
case 2:
TabMeFragment tab3 = new Tab2ContainerFragment();
return tab3;
case 3:
TabBagFragment tab4 = new Tab3ContainerFragment();
return tab4;
default:
return null;
}
}
//Overriden method getCount to get the number of tabs
#Override
public int getCount() {
return tabCount;
}
public Fragment getCurrentFragment() {
return mCurrentFragment;
}
//* this is key to get the current tab to pop the fragments afterwards**/
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
if (getCurrentFragment() != object) {
mCurrentFragment = ((Fragment) object);
}
super.setPrimaryItem(container, position, object);
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
Lets go into a container to see how it would look:
add this to your xml for all the containers (along with anything else you want visually but they ALL must have the same id of container_framelayout:
<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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout android:id="#+id/container_framelayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android" />
</android.support.design.widget.CoordinatorLayout>
you dont have to put it in a coordinatorLayout i just find it fixes some bugs and works well.
In your fragments base class i copied almost the same code from the SO i mentioned above but slight modification if you want to add tag or not:
public void replaceFragment(Fragment fragment, boolean addToBackStack,String tag) {
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.container_framelayout, fragment,tag);
transaction.commit();
getChildFragmentManager().executePendingTransactions();
}
public boolean popFragment() {
Log.e("test", "pop fragment: " + getChildFragmentManager().getBackStackEntryCount());
boolean isPop = false;
if (getChildFragmentManager().getBackStackEntryCount() > 0) {
isPop = true;
getChildFragmentManager().popBackStack();
}
return isPop;
}
Now lets look at the activities layout:
<?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="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white"/>
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabTextColor="#color/black"
app:tabSelectedTextColor="#android:color/darker_gray"
/>
Now i'll show you how to set up the tablayout in the activity hosting the tablayout:
its standard:
public class HomePageActivity implements TabLayout.OnTabSelectedListener {
private final int NUM_OF_TABS = 4;
#BindView(R.id.pager)
public ViewPager viewPager;
public HomePagerAdapter adapter;
#BindView(R.id.tabLayout)
TabLayout tabLayout;
#NonNull
#Override
public HomePagePresenter createPresenter() {
return new HomePagePresenter();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_homepage);
ButterKnife.bind(this);
initView();
}
private void initView() {
for (int i = 0; i < NUM_OF_TABS; i++)
tabLayout.addTab(tabLayout.newTab());
adapter = new HomePagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
//Adding adapter to pager
viewPager.setAdapter(adapter);
tabLayout.addOnTabSelectedListener(this);
tabLayout.setupWithViewPager(viewPager);
// configure tab icons
int[] imageTabResId = {
R.drawable.welcome1,
R.drawable.welcome2,
R.drawable.welcome3,
R.drawable.welcome1};
for (int i = 0; i < imageTabResId.length; i++) {
tabLayout.getTabAt(i).setIcon(imageTabResId[i]);
}
}
/** this is key. we get the current fragment showing and pop it **/
#Override
public void onBackPressed() {
boolean isPopFragment = false;
isPopFragment = ((BaseFragment) adapter.getCurrentFragment()).popFragment();
if (!isPopFragment) {
finish();
}
}
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
}
I guess the major part is onBackPress getting the current fragment.
My app has an activity with NavigationView and for different items in the navigation drawer UI is changed by changing the fragment. One such fragment has TabLayout implemented in it.
When the app starts the fragment with TabLayout is loaded and it works fine but when I switch between different items in the navigation drawer and then come back to the item which has the TabLayout, now on swiping the tabs the indicator gets stuck in between tabs and the content on one tab is not even displayed. I have no clue regarding what mistake I might have did. I am using
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support:design:24.2.1'
compile 'com.android.support:support-v4:24.2.1'
This is the activity which has the NavigationView (activity_start.xml)
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
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_start"
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_start"
app:menu="#menu/start_menu" />
</android.support.v4.widget.DrawerLayout>
This is the code for app_bar_start.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:fitsSystemWindows="true"
tools:context="com.optimilia.readaloud.Start">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay"
app:elevation="0dp">
<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/AppTheme.PopupOverlay"/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="#+id/frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
This is the fragment which has the TabLayout (fragment_home.xml)
<?xml version="1.0" encoding="utf-8"?>
<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:id="#+id/activity_home"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.optimilia.readaloud.HomeFragment">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="#dimen/custom_tab_layout_height"
app:tabMode="fixed"
app:tabGravity="fill"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</LinearLayout>
Start.java
public class Start extends AppCompatActivity {
private NavigationView navigationView;
private DrawerLayout drawer;
private Toolbar toolbar;
private Fragment homeFragment = null;
// index to identify current nav menu item
public static int navItemIndex = 0;
// tags used to attach the fragments
private static final String TAG_HOME = "Home";
private static final String TAG_STORE = "Store";
private static final String TAG_ABOUT = "About";
private static final String TAG_SETTINGS = "Settings";
private static final String TAG_HELP = "Help";
public static String CURRENT_TAG = TAG_HOME;
// toolbar titles respected to selected nav menu item
private String[] activityTitles;
private Handler mHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mHandler = new Handler(this.getMainLooper());
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
navigationView = (NavigationView) findViewById(R.id.nav_view);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
// load toolbar titles from string resources
activityTitles = getResources().getStringArray(R.array.nav_item_activity_titles);
// initializing navigation menu
setUpNavigationView();
if (savedInstanceState == null) {
navItemIndex = 0;
CURRENT_TAG = TAG_HOME;
loadFragment(true);
}
}
private void loadFragment(boolean selectNavMenu) {
if (selectNavMenu) {
selectNavMenu();
}
// set toolbar title
setToolbarTitle();
// if user select the current navigation menu again, don't do anything
// just close the navigation drawer
if (getSupportFragmentManager().findFragmentByTag(CURRENT_TAG) != null) {
drawer.closeDrawers();
return;
}
// Sometimes, when fragment has huge data, screen seems hanging
// when switching between navigation menus
// So using runnable, the fragment is loaded with cross fade effect
Runnable mPendingRunnable = new Runnable() {
#Override
public void run() {
// update the main content by replacing fragments
Fragment fragment = getFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
fragmentTransaction.replace(R.id.frame, fragment, CURRENT_TAG);
fragmentTransaction.commit();
}
};
// If mPendingRunnable is not null, then add to the message queue
if (mPendingRunnable != null) {
mHandler.post(mPendingRunnable);
}
drawer.closeDrawers();
invalidateOptionsMenu();
}
private Fragment getFragment() {
switch (navItemIndex) {
case 0:
if (homeFragment == null) {
homeFragment = new HomeFragment();
}
return homeFragment;
case 1:
SettingsFragment settingsFragment = new SettingsFragment();
return settingsFragment;
// case 2:
// // movies fragment
// MoviesFragment moviesFragment = new MoviesFragment();
// return moviesFragment;
// case 3:
// // notifications fragment
// NotificationsFragment notificationsFragment = new NotificationsFragment();
// return notificationsFragment;
//
// case 4:
// // settings fragment
// SettingsFragment settingsFragment = new SettingsFragment();
// return settingsFragment;
default:
return new HomeFragment();
}
}
private void setToolbarTitle() {
getSupportActionBar().setTitle(activityTitles[navItemIndex]);
}
private void selectNavMenu() {
try {
navigationView.getMenu().getItem(navItemIndex).setChecked(true);
}
catch (Exception ex){}
}
private void setUpNavigationView() {
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
// This method will trigger on item Click of navigation menu
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
//Check to see which item was being clicked and perform appropriate action
switch (menuItem.getItemId()) {
//Replacing the main content with ContentFragment Which is our Inbox View;
case R.id.nav_home:
navItemIndex = 0;
CURRENT_TAG = TAG_HOME;
break;
case R.id.nav_settings:
navItemIndex = 1;
CURRENT_TAG = TAG_SETTINGS;
break;
case R.id.nav_store:
navItemIndex = 2;
CURRENT_TAG = TAG_STORE;
break;
case R.id.nav_help:
navItemIndex = 3;
CURRENT_TAG = TAG_HELP;
break;
case R.id.nav_about:
navItemIndex = 4;
CURRENT_TAG = TAG_ABOUT;
break;
default:
navItemIndex = 0;
}
//Checking if the item is in checked state or not, if not make it in checked state
if (menuItem.isChecked()) {
menuItem.setChecked(false);
} else {
menuItem.setChecked(true);
}
menuItem.setChecked(true);
loadFragment(false);
return true;
}
});
}
#Override
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawers();
return;
}
super.onBackPressed();
}
}
HomeFragment.java
public class HomeFragment extends Fragment {
private View currView;
private TabLayout tabLayout;
private ViewPager viewPager;
private int[] tabIcons = {
R.drawable.ic_start,
R.drawable.ic_recent,
R.drawable.ic_reading_list
};
public HomeFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
currView = inflater.inflate(R.layout.fragment_home, container, false);
viewPager = (ViewPager) currView.findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) currView.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
setupTabIcons();
return currView;
}
private void setupViewPager(ViewPager viewPager) {
HomeFragment.ViewPagerAdapter adapter = new HomeFragment.ViewPagerAdapter(getFragmentManager());
adapter.addFragment(new StartFragment(), "Start");
adapter.addFragment(new RecentFragment(), "Recent");
adapter.addFragment(new ReadingListFragment(), "Reading list");
viewPager.setAdapter(adapter);
}
private void setupTabIcons() {
tabLayout.getTabAt(0).setIcon(tabIcons[0]);
tabLayout.getTabAt(1).setIcon(tabIcons[1]);
tabLayout.getTabAt(2).setIcon(tabIcons[2]);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
In HomeFragment.java was using getFragmentManager() for ViewPagerAdapter and this was causing the problem. On switching to getChildFragmentManager() it started working perfectly.
Actually i new in Android and got stuck in Navigation Drawer..
i have successfully designed material designed navigation drawer and their menu items .
But when i clicked on that menu it open a independent fragment while i want it to open it in particular tabs inside Tab Layout.
i have made separate Tab layout with custom Adapter. mytablayout .xml file is as
<?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="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
app:tabGravity="fill"
app:tabMode="fixed"
app:elevation="0dp"
android:background="#6ec6c5"
app:tabIndicatorColor="#000000"
app:tabSelectedTextColor="#color/textColor"
app:tabTextColor="#A8DCDC"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize">
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
</LinearLayout>
my Tabfragment class are there:
public class TabFragment extends Fragment {
public static TabLayout tabLayout;
public static ViewPager viewPager;
public static int int_items = 3;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/**
*Inflate tab_layout and setup Views.
*/
View x = inflater.inflate(R.layout.fragment_tab, null);
tabLayout = (TabLayout) x.findViewById(R.id.tabs);
viewPager = (ViewPager) x.findViewById(R.id.viewpager);
/**
*Set an Apater for the View Pager
*/
viewPager.setAdapter(new MyAdapter(getChildFragmentManager(),int_items ));
/**
* Now , this is a workaround ,
* The setupWithViewPager dose't works without the runnable .
* Maybe a Support Library Bug .
*/
tabLayout.post(new Runnable() {
#Override
public void run() {
tabLayout.setupWithViewPager(viewPager);
}
});
return x;
}
}
MyAdapter is :
public class MyAdapter extends FragmentPagerAdapter {
int int_items;
public MyAdapter(FragmentManager fm,int int_items) {
super(fm);
this.int_items = int_items;
}
/**
* Return fragment with respect to Position .
*/
#Override
public Fragment getItem(int position)
{
switch (position){
case 0 : return new ProductFragment();
case 1 : return new ProductFragment();
case 2 : return new ProductFragment();
}
return null;
}
#Override
public int getCount() {
return int_items;
}
/**
* This method returns the title of the tab according to the position.
*/
#Override
public CharSequence getPageTitle(int position) {
switch (position){
case 0 :
return "PRODUCTS";
case 1 :
return "FEATURED";
case 2 :
return "FAVOURITES";
}
return null;
}
}
My SplitviewActivity is shown like this:
public class SplitViewActivity extends AppCompatActivity {
private DrawerLayout mDrawerLayout;
private NavigationView navigationView;
FragmentManager mFragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_split_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.menu);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
navigationView = (NavigationView) findViewById(R.id.navigation_view);
getSupportFragmentManager().beginTransaction().replace(R.id.frame_container, new TabFragment()).commit();
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
menuItem.setChecked(true);
mDrawerLayout.closeDrawers();
switch (menuItem.getItemId()) {
case R.id.navigation_item_products:
getSupportFragmentManager().beginTransaction().replace(R.id.frame_container, new TabFragment()).commit();
Toast.makeText(SplitViewActivity.this, "Navigation Sub Item 01 Clicked", Toast.LENGTH_SHORT).show();
// updateDisplay(new AttachmentFragment());
break;
case R.id.navigation_item_new_Releases:
getSupportFragmentManager().beginTransaction().replace(R.id.frame_container, new ProductFragment()).commit();
/* FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.frame_container,new ProductFragment()).commit();*/
Toast.makeText(SplitViewActivity.this, "Navigation Sub Item 01 Clicked", Toast.LENGTH_SHORT).show();
// updateDisplay(new ImageFragment());
break;
case R.id.navigation_item_favorites:
getSupportFragmentManager().beginTransaction().replace(R.id.frame_container, new TabFragment()).commit();
Toast.makeText(SplitViewActivity.this, "Navigation Sub Item 01 Clicked", Toast.LENGTH_SHORT).show();
// updateDisplay(new MyLocationFragment());
break;
case R.id.navigation_item_about_us:
Toast.makeText(SplitViewActivity.this, "Navigation Sub Item 01 Clicked", Toast.LENGTH_SHORT).show();
// updateDisplay(new MyLocationFragment());
break;
case R.id.navigation_item_notification:
Toast.makeText(SplitViewActivity.this, "Navigation Sub Item 01 Clicked", Toast.LENGTH_SHORT).show();
// updateDisplay(new MyLocationFragment());
break;
case R.id.navigation_sub_item_01:
Toast.makeText(SplitViewActivity.this, "Navigation Sub Item 01 Clicked", Toast.LENGTH_SHORT).show();
break;
case R.id.navigation_sub_item_02:
Toast.makeText(SplitViewActivity.this, "Navigation Sub Item 02 Clicked", Toast.LENGTH_SHORT).show();
break;
}
return true;
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_splash_screen, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case android.R.id.home:
mDrawerLayout.openDrawer(GravityCompat.START);
return true;
case R.id.action_settings:
return true;
}
return super.onOptionsItemSelected(item);
}
}
my navigation menu item.xml file are as :
<?xml version="1.0" encoding="utf-8"?>
<group android:checkableBehavior="single">
<item
android:id="#+id/navigation_item_products"
android:checked="true"
android:title="Products" />
<item
android:id="#+id/navigation_item_new_Releases"
android:title="New Releases" />
<item
android:id="#+id/navigation_item_favorites"
android:title="favorites" />
<item
android:id="#+id/navigation_item_about_us"
android:title="About Us" />
<item
android:id="#+id/navigation_item_notification"
android:title="Notifications" />
</group>
<item android:title="">
<menu>
<item
android:id="#+id/navigation_sub_item_01"
android:title="Configure" />
<item
android:id="#+id/navigation_sub_item_02"
android:title="Logout" />
</menu>
</item>
Everything is work fine except.All three tabs has been Shown.navigation drawer also work well.
Only thing that i couldn't understand that how can i open a fragment in tab on click of navigation menuitems.At present when i click on menu item,it open an independent fragment not in tab.How can i achieve this ..Any help would be Appreciated in advanced..
just check on drawer onClick the clicked position and check against each viewpager tabs which tab is what u want and use Viewpager.setCurrentItem(posiition)
to navigate to that tab.
public void setStartTab(String topTab) {
LocalLog.e("TOPTAB",topTab+"");
if(topTab==null){
mViewPager.setCurrentItem(0);
}else{
for(int i=0;i<mTabs.size();i++){
LocalLog.e("TOPTAB",mTabs.get(i).name);
if(mTabs.get(i).name.equalsIgnoreCase(topTab)){
LocalLog.e("TOPTAB",i+"true");
mViewPager.setCurrentItem(i);
}
}
}
}
activity_main.xml
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
MainActivity
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new OneFragment(), "ONE");
adapter.addFragment(new TwoFragment(), "TWO");
adapter.addFragment(new ThreeFragment(), "THREE");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
its works for me
I am stuck in a problem with the view pager.The view pager works fine initially,the adapter calls the getItem(int pos) method and the pages get setup properly.
Now the problem arises when i try to replace a page in the view pager.The pagefragment is getting replaced but showing a blank screen.
I am not getting what to do next.
Tried calling `notifyDatasetChanged() but still no effect.
Heres the code`
public class BaseActivity extends FragmentActivity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private CharSequence mDrawerTitle;
private CharSequence mTitle;
private String[] mActions;
private static final int NUM_PAGES = 2;
private ViewPager mPager;
private PagerAdapter mPagerAdapter;
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.common_layout);
// Instantiate a ViewPager and a PagerAdapter.
fragmentManager = getSupportFragmentManager();
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
mTitle = mDrawerTitle = getTitle();
mActions = getResources().getStringArray(R.array.actions);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
// set up the drawer's list view with items and pclick listener
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mActions));
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
}
// The click listener for ListView in the navigation drawer
private class DrawerItemClickListener implements
ListView.OnItemClickListener {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
selectItem(position);
}
}
private void selectItem(int position) {
switch (position) {
case 0:
replaceFragment(new DashFragment());
break;
case 1:
replaceFragment(new SearchFragment());
break;
case 2:
replaceFragment(new UploadFragment());
break;
default:
replaceFragment(new DashFragment());
break;
}
mDrawerList.setItemChecked(position, true);
setTitle(mActions[position]);
Toast.makeText(this, "Title is=" + getTitle(), 1).show();
mDrawerLayout.closeDrawer(mDrawerList);
}
private void replaceFragment(Fragment newContentFragment) {
// TODO Auto-generated method stub
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
fragmentTransaction.replace(R.id.pager, newContentFragment);
fragmentTransaction.addToBackStack(String.valueOf(newContentFragment
.getId()));
fragmentTransaction.commit();
}
#Override
public void onBackPressed() {
if (mPager.getCurrentItem() == 0) {
// If the user is currently looking at the first step, allow the
// system to handle the
// Back button. This calls finish() on this activity and pops the
// back stack.
super.onBackPressed();
} else {
// Otherwise, select the previous step.
mPager.setCurrentItem(mPager.getCurrentItem() - 1);
}
}
private class ScreenSlidePagerAdapter extends FragmentPagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new DashFragment();
case 1:
return new SearchFragment();
default:
return new DashFragment();
}
}
#Override
public int getCount() {
return NUM_PAGES;
}
}
}
Here's my common_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<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" >
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:focusable="true"
android:focusableInTouchMode="true" />
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#111"
android:choiceMode="singleChoice" />
</android.support.v4.widget.DrawerLayout>
Here are the solutions of your problem .These have the good explanation as well ..
first
second
keep it DRY :)
Let me know if you need further explanation.