How to Display Navigation Drawer in all activities? - java

I have a Navigation Drawer which should appear in all my activities.
I saw many questions similar to this & found a solution like Extending the MainActivity with the Other Activities .
So i extended My Main Activity to my Second Activity.But the Drawer is not being showed in the Second Activity
MainActivity
public class MainActivity extends ActionBarActivity
{
private ListView mDrawerList;
private DrawerLayout mDrawer;
private CustomActionBarDrawerToggle mDrawerToggle;
private String[] menuItems;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
supportRequestWindowFeature(WindowCompat.FEATURE_ACTION_BAR);
// getSupportActionBar().hide();
setContentView(R.layout.activity_main_drawer);
// enable ActionBar app icon to behave as action to toggle nav drawer
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
// set a custom shadow that overlays the main content when the drawer
// opens
mDrawer.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
_initMenu();
mDrawerToggle = new CustomActionBarDrawerToggle(this, mDrawer);
mDrawer.setDrawerListener(mDrawerToggle);
}
private void _initMenu()
{
NsMenuAdapter mAdapter = new NsMenuAdapter(this);
// Add Header
mAdapter.addHeader(R.string.ns_menu_main_header);
// Add first block
menuItems = getResources().getStringArray(R.array.ns_menu_items);
String[] menuItemsIcon = getResources().getStringArray(R.array.ns_menu_items_icon);
int res = 0;
for (String item : menuItems)
{
int id_title = getResources().getIdentifier(item, "string", this.getPackageName());
int id_icon = getResources().getIdentifier(menuItemsIcon[res], "drawable", this.getPackageName());
NsMenuItemModel mItem = new NsMenuItemModel(id_title, id_icon);
// if (res==1) mItem.counter=12; //it is just an example...
// if (res==3) mItem.counter=3; //it is just an example...
mAdapter.addItem(mItem);
res++;
}
mAdapter.addHeader(R.string.ns_menu_main_header2);
mDrawerList = (ListView) findViewById(R.id.drawer);
if (mDrawerList != null)
mDrawerList.setAdapter(mAdapter);
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
}
#Override
protected void onPostCreate(Bundle savedInstanceState)
{
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.control_menu, menu);
return super.onCreateOptionsMenu(menu);
}
/* Called whenever we call invalidateOptionsMenu() */
#Override
public boolean onPrepareOptionsMenu(Menu menu)
{
// If the nav drawer is open, hide action items related to the content
// view
boolean drawerOpen = mDrawer.isDrawerOpen(mDrawerList);
menu.findItem(R.id.action_keyboard).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
/*
* The action bar home/up should open or close the drawer.
* ActionBarDrawerToggle will take care of this.
*/
if (mDrawerToggle.onOptionsItemSelected(item))
{
return true;
}
// Handle your other action bar items...
return super.onOptionsItemSelected(item);
}
private class CustomActionBarDrawerToggle extends ActionBarDrawerToggle
{
public CustomActionBarDrawerToggle(Activity mActivity, DrawerLayout mDrawerLayout)
{
super(mActivity, mDrawerLayout, R.drawable.ic_drawer, R.string.ns_menu_open, R.string.ns_menu_close);
}
#Override
public void onDrawerClosed(View view)
{
getSupportActionBar().setTitle(getString(R.string.ns_menu_close));
supportInvalidateOptionsMenu(); // creates call to
// onPrepareOptionsMenu()
}
#Override
public void onDrawerOpened(View drawerView)
{
getSupportActionBar().setTitle(getString(R.string.ns_menu_open));
supportInvalidateOptionsMenu(); // creates call to
// onPrepareOptionsMenu()
}
}
private class DrawerItemClickListener implements ListView.OnItemClickListener
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Intent intent = new Intent(MainActivity.this, Tutorial.class);
startActivity(intent);
}
}
}
SecondActivity
public class Tutorial extends MainActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.help);
}
}

Here is my implementation.. hope it help
FIRST, this POST is concept.
SECOND, this is also the KEY one.
FINALLY, Here is combination of all answer in one place
BASE ACTIVITY
This is a base activity for all other activity
You can extends Activity or FragmentActivity or etc. base on your requirement.
Navigation Drawer setup here for one time.
public class BaseActivity extends FragmentActivity {
protected DrawerLayout mDrawer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.base_layout);
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
//This is about creating custom listview for navigate drawer
//Implementation for NavigateDrawer HERE !
ArrayList<DrawerListItem> drawerListItems = new ArrayList<DrawerListItem>();
drawerListItems.add(new DrawerListItem(0,"AIRĀ° DEVICES"));
drawerListItems.add(new DrawerListItem(1,"A/C Device [1]"));
drawerListItems.add(new DrawerListItem(1,"A/C Device [2]"));
drawerListItems.add(new DrawerListItem(1,"A/C Device [3]"));
drawerListItems.add(new DrawerListItem(0,"AIRĀ° FEATURES"));
drawerListItems.add(new DrawerListItem(2,"SLEEP MODE"));
drawerListItems.add(new DrawerListItem(2,"TRACKING MODE"));
drawerListItems.add(new DrawerListItem(2,"SETTINGS"));
DrawerAdapter mDrawerAdapter = new DrawerAdapter(this, R.layout.drawer_list_header, drawerListItems);
ListView mDrawerList = (ListView) findViewById(R.id.left_drawer);
mDrawerList.setAdapter(mDrawerAdapter);
}
}
BASE ACTIVITY XML
This xml layout is for Navigation Drawer
<?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>
<!-- The navigation drawer -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="left"
android:scrollingCache="false"
android:background="#drawable/drawer_bg"
android:divider="#null"
android:choiceMode="singleChoice"/>
</android.support.v4.widget.DrawerLayout>
ALL OTHERS ACTIVITY
Other Activity just extends BaseActivity and define code as below.
The Navigation Drawer will appear for particular activity.
mDrawer is form BaseActivity. it's a protected variable.
public class Screen1 extends BaseActivity
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//inflate your activity layout here!
View contentView = inflater.inflate(R.layout.screen1, null, false);
mDrawer.addView(contentView, 0);
//Do the rest as you want for each activity
}
SCREEN 1 XML SAMPLE
Design as you wish it each activity. no more Navigation Drawer Layout !
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
NOTE
In this implementation, The Navigation Drawer doesn't bind with Action Bar. If you wish to do that do it in BaseActivity.Also, This guide is not cover all requirement. It's just a sample.

in onCreate of TutorialActivity don't call setContentView instead do this:
#Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(R.layout.help, null, false);
mDrawer.addView(contentView, 0);
}
make mDrawer in MainActivity protected. and in R.layout.activity_main_drawer just keep drawer tag and the element with gravity left(or right).

I made a BaseActivity activity which extends SherlockActivity (or ActionBarActivity if is your case)
public class BaseActivity extends SherlockActivity
Then, make all your activities extends BaseActivity, like:
public class GlossaryActivity extends BaseActivity
Later, you must replace the activity layout with the one that correspond to your activity, I made a method in BaseActivity like that:
protected void replaceContentLayout(int sourceId, int destinationId) {
View contentLayout = findViewById(destinationId);
ViewGroup parent = (ViewGroup) contentLayout.getParent();
int index = parent.indexOfChild(contentLayout);
parent.removeView(contentLayout);
contentLayout = getLayoutInflater().inflate(sourceId, parent, false);
parent.addView(contentLayout, index);
}
I called this method on the onCreate method in each activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.replaceContentLayout(R.layout.activity_glossary, super.CONTENT_LAYOUT_ID);
}
super.CONTENT_LAYOUT_ID is the FrameLayout of the BaseActivity, and other param is the layout you want replace with

You omitted the #Override from your derived class onCreate.
UPDATE: I'm not sure what the effects are of calling setContentView twice but that could be the problem. Separate out the code that sets up the drawer, and call that from both of the onCreate methods.

I had this problem too. This is my implementation:
activity_main.xml - the child at index 1 in the CoordinatorLayout is the content_main.xml, this I can change in code.
<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">
<android.support.design.widget.CoordinatorLayout
android:id="#+id/coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<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"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
**<include layout="#layout/content_main" />**
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:src="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main"
app:menu="#menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
I've created a class that uses inflates the others activities UI:
public class MyLayoutInflater {
public void inflate(Activity activity, int LayoutResource, android.app.ActionBar getSupportActionBar, Intent getIntent){
CoordinatorLayout coordinatorLayout = (CoordinatorLayout) activity.findViewById(R.id.coordinator);
android.view.LayoutInflater inflater = (android.view.LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(LayoutResource, null, false);
//change i so that it suits the child number in you coordinator layout
int i = 1;
coordinatorLayout.removeViewAt(i);
coordinatorLayout.addView(contentView, i);
getSupportActionBar.setTitle(actionBarTitle);
}
public void inflate(Activity activity, int LayoutResource, android.support.v7.app.ActionBar getActionBar, String actionBarTitle){
CoordinatorLayout coordinatorLayout = (CoordinatorLayout) activity.findViewById(R.id.coordinator);
android.view.LayoutInflater inflater = (android.view.LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View contentView = inflater.inflate(LayoutResource, null, false);
//change i so that it suits the child number in you coordinator layout
int i = 1;
coordinatorLayout.removeViewAt(i);
coordinatorLayout.addView(contentView, i);
getActionBar.setTitle(actionBarTitle);
}
}
Now on the other activities all you have to do is extend the MainActivity and call this method and give it the necessary parameters:
public class AnotherActivity extends MainActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new MyLayoutInflater().inflate(this,R.layout.content_activity_another, getSupportActionBar(), getIntent());
}
}

Ok here is hacky way to do this, I use it only for special kind of debug build to set properties of views in realtime (design tool).
It has advantage that you can use your child activities as usual without, special behavior that is required in different answers.
so in BaseActvity you can add:
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// WARNING: Hacky, use carefully!!!
ViewGroup androidBaseView = (ViewGroup) findViewById(android.R.id.content);
//this one in what child activity has just set in setContentView()
ViewGroup childContent = (ViewGroup) androidBaseView.getChildAt(0);
View drawerView = LayoutInflater.from(this)
.inflate(R.layout.base_activity_drawer, androidBaseView, false);
FrameLayout frameLayout = (FrameLayout) drawerView.findViewById(R.id.content);
androidBaseView.removeView(childContent);
frameLayout.addView(childContent);
androidBaseView.addView(drawerView);
}
and xml for drawer is just:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/nav_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<FrameLayout
android:id="#+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:id="#+id/drawer_for_components"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:orientation="vertical"
android:fitsSystemWindows="true"
/>
</android.support.v4.widget.DrawerLayout>

Here is a simple and fast way to do it in android studio:
Create a new activity (Navigation drawer activity) from the gallery, and name it whatever you want, android studio will create everything for you (the class and the xml files that you can customize it later)
In other activities you should extend your Navigation drawer activity, and make sure these other activities has "no action bar" in the manifests file (android:theme="#style/AppTheme.NoActionBar")
You should modify your other activities as follows:
public class Mainactivity extends NavActivity
{
super.onCreate(savedInstanceState);
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//inflate your activity layout here!
View contentView = inflater.inflate(R.layout.activity_main, null, false);
drawer.addView(contentView, 0);
}
Note: the mainactivity will extend the action bar of the NavActivity, the NavActivity has a full functional action bar that will call the navigation drawer
I hope it will work with you

Nowadays you should use Single-Activity App Architecture (source).
Then simple add Navigation Drawer to Main Activity

you can simply use <include/>
By creating a nav drawer
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
and then include the layout in it
<include
layout="#layout/activity_accounts"
android:layout_width="match_parent"
android:layout_height="match_parent" />
in your main activity make setContentView(R.layout.your_drawer_activity)
take note that if you use this method you have to create a nav drawer layout for every activity you have, unless you found a way to do includes programmatically.

Related

TabLayout swiping does not change Tab focus

I have a tabLayout and a viewPager underneath it. When I click on the tab, it switches tabs perfectly fine. However, when I swipe, the viewPage swipes over, but the tab does not change focus. I have to manually click on the corresponding tab in order to change the focus (viewPager does not change).
For example, if I'm on the 4th slide, and I swipe left, the viewPage goes to the 3rd slide, but the tab isn't focused over. I have to manually tap on the 3rd tab in order to change the focus.
I'm wondering how I can let the tabs follow the swiping when I swipe from view to view in the viewPager.
fragment XML:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.tabs.TabLayout
android:layout_height="wrap_content"
android:id="#+id/tab_layout"
android:layout_width="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toTopOf="#id/pager"/>
<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
PagerFragment:
public class PagerFragment extends Fragment {
ViewPagerAdapter pagerAdapter;
ViewPager pager;
TabLayout tl;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pagerAdapter = new ViewPagerAdapter(this.getContext(), getChildFragmentManager(), 4, getActivity());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = super.onCreateView(inflater, container, savedInstanceState);
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_pager, null);
pager = root.findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
tl = root.findViewById(R.id.tab_layout);
tl.addTab(tl.newTab().setText("1"));
tl.addTab(tl.newTab().setText("2"));
tl.addTab(tl.newTab().setText("3"));
tl.addTab(tl.newTab().setText("4"));
tl.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
pager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
tl.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(pager));
return root;
}
}
Adapter:
public class ViewPagerAdapter extends FragmentPagerAdapter {
private Context myContext;
int totalTabs;
public ViewPagerAdapter(Context context, FragmentManager fm, int totalTabs, FragmentActivity fa) {
super(fm);
myContext = context;
this.totalTabs = totalTabs;
}
public Fragment getItem(int position) {
graph_test gt = new graph_test(String.valueOf(position), position);
return gt;
}
#Override
public int getCount() {
return totalTabs;
}
}
Note: I know that FragmentPagerAdapter is deprecated. I was asked to do it this way.
Thanks.
Using the androidx.viewpager.widget.ViewPager you have to set also the ViewPager.OnPageChangeListener with TabLayout.TabLayoutOnPageChangeListener like the below:
pager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tl));
By doing the above you should be able to change the Tab focus when swiping the ViewPager left or right.
onViewCreated() use
TabLayoutMediator(tabLayout, viewPager){ tab, position ->
// set tab text by given *position*
tab.text = "Tab_{position}" // for example
}.atach()
to link TabLayout and ViewPager and atach it

How to Load fragment when the app launches

I have created an app which basically has navigation drawer and I wish to load an fragment "home" whenever the activity launches instead of main activity.
Any idea how to do it.
You can call this method to view Fragments. In your case call this method on your onCreate()
//Fragment Changer
public void changeFragment(Fragment targetfragment) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_fragment, targetfragment, "fragment")
.setTransitionStyle(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.addToBackStack(null)
.commitAllowingStateLoss();
}
Example Usage
changeFragment(new YourFragment());
Basic solution can be implementing something like the below code in your onCreate method.
// get fragment manager
FragmentManager fm = getFragmentManager();
// replace
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.main_layout, new HomeFragment());
ft.commit();
Your Activity:
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
}
public String getHelloMessage() {
return "Hello!";
}
}
Your View:
public class MainView extends Fragment {
// Declarations
private Button testButton;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.main_view, container, false);
// Getting the reference of controller from Application
MainController mainController = Application.getInstance().getMainController();
// Initializing view objects
testButton = view.findViewById(R.id.test_button);
// Setting actions
testButton.setOnClickListener(mainController.getTestAction());
return view;
}
// Reference to the view Object
public Button getTestButton() {
return testButton;
}
Your main_activity.xm lto connect the fragment
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/containerMainView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/mainView"
android:name="com.template.views.MainView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Your main_view.xml file your final view definition
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/test_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="#string/say_hello" />
</RelativeLayout>

How can I nest fragments with a navigation drawer?

I've been trying for the last few hours to search around SO, but I couldn't find a solution outside of trying to create a workaround. I'm trying to create a navigation drawer for my app, but to do so I had to end up trying to change my base activity into a fragment. This is the result:
public class ToolReaderActivity extends Fragment implements ToolListFragment.OnToolSelectedListener, CompatActionBarNavListener, OnClickListener {
boolean mIsDualPane = false;
Context c;
ToolListFragment mToolListFragment;
InfoFragment mInfoFragment;
Fragment mContent;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
c = getActivity();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.onepane_with_bar, container, false);
// find our fragments
mToolListFragment = (ToolListFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.toolList);
mInfoFragment = (InfoFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.toolInfo);
FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.toolList, mToolListFragment).commit();
FragmentTransaction transaction2 = getActivity().getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.toolInfo, mInfoFragment).commit();
mToolListFragment.setContext(c);
mToolListFragment.setOnToolSelectedListener(this);
View infoView = getView().findViewById(R.id.toolInfo);
mIsDualPane = infoView != null && infoView.getVisibility() == View.VISIBLE;
int catIndex = savedInstanceState == null ? 0 : savedInstanceState.getInt("catIndex", 0);
setUpActionBar(mIsDualPane, catIndex);
mToolListFragment.setSelectable(mIsDualPane);
restoreSelection(savedInstanceState);
if (savedInstanceState != null) {
//Restore the fragment's instance
mContent = getActivity().getSupportFragmentManager().getFragment(savedInstanceState, "mContent");
}
return rootView;
}
...
...
...
}
The intended output is a activity with a navigation drawer and thus a fragment. The fragment contains this main activity ToolReaderActivity (named so because it was formerly an activity) which has 1-2 fragments inside of it. It's a ListFragment with a fragment showing the selected items information (as either another fragment if mDualPane is true or launched as a seperate activity otherwise).
I can't figure out a way to get this to work, I've tired changing the order that things are done using onCreate, onCreateView, onActivityCreated, but the error I keep getting is that mToolsListFragment is null at mToolsListFragment.setContext(c);
You can simply create NavigationDrawer with the code below.
public class MainActivity extends AppCompatActivity
{
private NavigationView mNavigationView;
private DrawerLayout mDrawerLayout;
private Toolbar toolbar;
private ActionBarDrawerToggle mDrawerToggle;
private FragmentActivity fragment;
private FragmentManager fragmentManager;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initDrawerNavigation();
fragmentManager = getFragmentManager();
}
public void initDrawerNavigation()
{
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(R.string.app_name);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener()
{
#Override
public boolean onNavigationItemSelected(MenuItem item)
{
item.setChecked(true);
switch (item.getItemId())
{
case R.id.st_menu:
fragment = new FirstFragment();
break;
case R.id.nd_menu:
fragment = new Second Fragment();
break;
}
fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
mDrawerLayout.closeDrawers();
return true;
}
});
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open,
R.string.drawer_close)
{
// Called when a drawer has settled in a completely closed state.
public void onDrawerClosed(View view)
{
super.onDrawerClosed(view);
}
// Called when a drawer has settled in a completely open state.
public void onDrawerOpened(View drawerView)
{
super.onDrawerOpened(drawerView);
}
};
mDrawerLayout.addDrawerListener(mDrawerToggle);
}
#Override
protected void onPostCreate(Bundle savedInstanceState)
{
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId())
{
case android.R.id.home:
mDrawerLayout.openDrawer(GravityCompat.START); // OPEN DRAWER
return true;
}
return super.onOptionsItemSelected(item);
}
}
Here you have activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<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_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:theme="#style/ThemeOverlay.AppCompat.ActionBar" />
<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:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MainActivity">
<include
layout="#layout/your_layout" />
<android.support.design.widget.NavigationView
android:id="#+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
app:menu="#menu/navigation_items" />
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
your_layout can be anything you want. Now you define your FirstFragment class like here:
public class FirstFragment extends Fragment
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.target_layout, container, false);
return view;
}
}
You can also refer to this question Navigation Drawer to switch between activities if you want to switch between activities and not fragments. Hope this helps.

invalidateOptionsMenu() not working when "restarting" activity

I have an activity, let's call it FirstActivity.java, which has an actionBar with a navigation drawer instantiated via fragment. In this fragment, NavigationDrawerFragment.java, I've put the methods onCreateOptionsMenu(Menu menu, MenuInflater inflater), onOptionsItemSelected(MenuItem item) and onPrepareOptionsMenu(Menu menu) as anyone normally would in order to instantiate the actionBar. On the right side of the actionBar, I have a button with a "messages" icon that leads to the user's inbox fragment. When a new message incomes, I call invalidateOptionsMenu() inside my FirstActivity and change the icon to a brighter one in onPrepareOptionsMenu(Menu menu). Everything works fine so far.
The problem is: I can leave the FirstAcitivty via one of the options in the navigation drawer. I do it via Intent. Let's call it SecondActivity.java.
Intent myIntent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(myIntent);
finish();
When I call the FirstAcitivity again, also via Intent, the invalidateOptionsMenu() method stops working. It does not trigger the methods onCreateOptionsMenu nor onPrepareOptionsMenu. I have also tried supportInvalidateOptionsMenu() with no luck.
Only when I hit the MENU BUTTON (on the left side of the actionBar) is that these methods are called and the messages icon is changed. Does anyone know the reason for this strange behavior?
Better yet, does anyone know a solution for my problem? : )
FirstActivity.java
public class FirstActivity extends ActionBarActivity impements NavigationDrawerFragment.NavigationDrawerCallbacks {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.first_activity);
// When a new message arrives
if (thereIsAnIncomingMessage) {
invalidateOptionsMenu();
}
}
}
first_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" android:id="#+id/first_activity_layout">
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstActivity">
<!-- As the main content view, the view below consumes the entire
space available using match_parent in both dimensions. -->
<FrameLayout android:id="#+id/container" android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- android:layout_gravity="start" tells DrawerLayout to treat
this as a sliding drawer on the left side for left-to-right
languages and on the right side for right-to-left languages.
If you're not building against API 17 or higher, use
android:layout_gravity="left" instead. -->
<!-- The drawer is given a fixed width in dp and extends the full height of
the container. -->
<fragment android:id="#+id/navigation_drawer"
android:layout_width="#dimen/navigation_drawer_width" android:layout_height="match_parent"
android:layout_gravity="start"
android:name="com.example.Controller.Main.NavigationBar.NavigationDrawerFragment"
tools:layout="#layout/fragment_navigation_drawer" />
</android.support.v4.widget.DrawerLayout>
</LinearLayout>
NavigationDrawerFragment.java
public class NavigationDrawerFragment extends Fragment {
private RelativeLayout relativeLayout;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
relativeLayout = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
return relativeLayout;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
inflater.inflate(R.menu.menu_main, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_menu) {
// Open navigation drawer menu
return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
} else if (item.getItemId == R.id.action_chat) {
// Open messages fragment
MessagesFragment messagesFragment = new MessagesFragment();
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container, messagesFragment, "MESSAGES_FRAGMENT");
fragmentTransaction.addToBackStack("chatFrag");
fragmentTransaction.commit();
}
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if (FirstActivity.thereIsAnIncomingMessage) {
menu.getItem(0).setIcon(R.drawable.new_message_icon);
} else {
menu.getItem(0).setIcon(R.drawable.message_icon);
}
}
public interface NavigationDrawerCallbacks {
void onNavigationDrawerItemSelected(int position);
}
}
The problem is that the OnCreate method of FirstActivity is not called when you hit the back button. Instead, you can put your code in OnResume, as follows:
#Override
public void onResume(){
super.onResume();
if(thereIsAnIncomingMessage)
invalidateOptionsMenu();
}
See the official Activity Lifecycle documentation.

Navigation drawer for multiple activities not working

I'm trying to get the same navigation drawer for multiple activities. At the moment I have a BaseActivity that holds the navigation drawer and a MainActivity that extends the BaseActivity class. It works fine when i run the BaseActivity first but instead if i run MainActivity first (Which is what I want to do) the navigation drawer doesn't work when i swipe the screen from left to right. I've been stuck on this for while now and can't seem to figure out what I am missing. Any help would be appreciated.
HomeActivity Class
public class HomeActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
}
}
BaseActivity Class
public class BaseActivity extends ActionBarActivity {
private String[] menuList;
private DrawerLayout drawerLayout;
private ListView listView;
private ActionBarDrawerToggle drawerToggle;
private CharSequence drawerTitle;
private CharSequence title;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
// Initialize drawer's list of items. Get the array for the list
menuList = getResources().getStringArray(R.array.menuItems);
// Get the drawers layout
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// Get the list view
listView = (ListView) findViewById(R.id.list_view);
// Creating an ArrayAdapter to add items to the listview listView
listView.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1,
menuList));
// Set listener for the list item clicks
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView adapterView, View view, int i, long l) {
}
});
}
activity_base.xml
<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">
<!-- The main content view -->
<FrameLayout
android:id="#+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView
android:id="#+id/list_view"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="10dp" />
</android.support.v4.widget.DrawerLayout>

Categories