I want to define a single nav drawer I can use throughout my application. I followed the instructions of the chosen answer here as my first approach: Same Navigation Drawer in different Activities
I made a few modifications, namely calling onCreateDrawer from inside an overridden onCreate. I updated my subsequent activity to extend DashboardActivity ("base activity" from the example). When I launch my second activity I get a null pointer exception complaining that the nav UI doesn't exist when onCreateDrawer tries to set the toggle listened on the drawer.
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.widget.DrawerLayout.setDrawerListener(android.support.v4.widget.DrawerLayout$DrawerListener)' on a null object reference
Here are the base (dashboard) and subsequent (log workout) activity - please ask if there is other code you want to see. The code for the UI of the drawer and associated activity are what came out of the box when creating a new Nav Drawer Activity in Android Studio.
DashboardActivity.java
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
onCreateDrawer();
Realm realm = Realm.getDefaultInstance();
RealmQuery<Exercise> query = realm.where(Exercise.class);
RealmResults<Exercise> result = query.findAll();
Log.d(TAG, "There are " + result.size() + " exercises ready for use.");
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent logWorkoutIntent = new Intent(getApplicationContext(), LogWorkoutActivity.class);
startActivity(logWorkoutIntent);
}
});
//TODO: Remove this sign out button
Button signOutButton = (Button) findViewById(R.id.button_sign_out);
signOutButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseAuth.getInstance().signOut();
Intent intent = new Intent(getApplicationContext(), LoginActivity.class);
startActivity(intent);
Toast.makeText(getApplicationContext(), "Signed out", Toast.LENGTH_LONG).show();
}
});
//TODO: Remove this data tester
updateUserName();
}
//#Override
protected void onCreateDrawer() {
Log.d(TAG, "onCreateDrawer called");
//super.onCreate(savedInstanceState);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, mDrawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
mDrawerLayout.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
...
-
LogWorkoutActivity.java
public class LogWorkoutActivity extends DashboardActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_log_workout);
setContentView(R.layout.activity_log_workout);
super.onCreateDrawer();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
//getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
}
I think you are missing a drawer with id drawer_layout in your activity_log_workout layout.
In order for this approach to work, you must have a DrawerLayout with id drawer_layout in all your activity layouts that should have the drawer.
I also noticed something peculiar with your code. In every activity that extends DashboardActivity you are first setting setContentView(R.id.activity_dashboard), then calling onCreateDrawer(), then you are changing the content view and creating the drawer again. I think this a very suboptimal approach.
I suggest you create a BaseDrawerActivity class to encapsulate the drawer creation and UI binding logic. Then you just extend it in the activities where you need a drawer. You can do it like this:
public abstract class BaseDrawerActivity extends AppCompatActivity {
// move all your drawer related fields here
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate();
setContentView(getLayoutResId());
// the same method you have right now
onCreateDrawer();
}
/*
* Extending activities use this class to supply the
* id of their layout file. This way you can set the view
* only once and there is no need to create the drawer twice.
*/
#LayoutResId
public abstract int getLayoutResId();
}
Related
I would add event in nav_header_menu.
I added login and register section then when user click I would show the relative layout page:
https://ibb.co/wwmFzSk
I added fragment_layout_user.xml and ActivityLoginUser class with code:
public class ActivityLoginUser extends AppCompatActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_login_user);
ActionBar ab = getSupportActionBar();
ab.setDisplayHomeAsUpEnabled(true);
}}
How can I implement this event in drawer menu?
You can follow below code to access the view of header.
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
View headerview = navigationView.getHeaderView(0);
TextView login= (TextView) headerview.findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Your code here
}
});
I solved it also with #SumitSingh suggestion. I paste here the correct way to solve that.
We need to add this code in the activity class where we added navigation view.
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
View headerview = navigationView.getHeaderView(0);
TextView login= (TextView) headerview.findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Your code here
}
});
Replace // Your code here with:
Intent loginUserIntent = new Intent(getContext(), ActivityLoginUser.class);
/* Start the new activity */
startActivity(loginUserIntent);
If you get error for getContext() please replace it with MainActivity.this
It works for me.
I'm trying to implement the Navigation Drawer Activity on my Dashboard Activity. In my application, I have created a Theme where the 'Toolbar/ActionBar' is removed and just put an ImageView for my burger menu on a custom layout and include it on my dashboard layout. What I wanted is that when this ImageView is clicked the sliding drawer will display.
What I tried to do is add an Navigation Drawer Activity by com.project.projectname -> New -> activity -> 'Navigation Drawer Activity' and automatically it adds NavigationActivity class , activity_navigation.xml
app_bar_navigation.xml, etc.
But I was wondering how can I open the drawer?
In my Dashboard Activity I added this
public class DashboardActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dashboard);
View side_tab = findViewById(R.id.side_tab);
expanded_menu = (ImageView) side_tab.findViewById(R.id.expanded_menu);
expanded_menu.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
// open drawer here
}
});
Also, in NavigationActivity it uses ActionBarDrawerToggle, I must not use this because I don't apply an ActionBar. But what alternative can I use?
Here is my NavigationActivity
public class NavigationActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
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);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.navigation, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
Intent goToSreen;
if (id == R.id.nav_dashboard) {
goToSreen = new Intent(NavigationActivity.this, DashboardActivity.class);
startActivity(goToSreen);
} else if (id == R.id.nav_others) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
Thank you for your kind help.
Update
So in my Dashboard Activity I added the following
NavigationActivity navigationActivity;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dashboard);
View side_tab = findViewById(R.id.side_tab);
expanded_menu = (ImageView) side_tab.findViewById(R.id.expanded_menu);
expanded_menu.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
navigationActivity = new NavigationActivity() ;
navigationActivity.drawer.openDrawer(GravityCompat.START);
}
});
And in my Navigation Activity I add a global variable
public class NavigationActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
DrawerLayout drawer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
I have managed to call the drawer in my Dashboard Activity but the sliding menu still doesn't display when I clicked my burger menu. The app crashes and displays java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.widget.DrawerLayout.openDrawer(int)' on a null object reference
Add this in your NavigationActivity
public class NavigationActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
//Add this line
public static DrawerLayout drawer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
.......
And next change this
expanded_menu.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
// open drawer here
NavigationActivity. drawer.openDrawer(GravityCompat.START);
}
});
Try this hope it will solve your problrm.
Add the following code in NavigationActivity:
DrawerLayout mDrawerLayout; // Declare globally
In onCreate() :
mDrawerLayout = (DrawerLayout) findViewById(R.id.nav_drawer);
expanded_menu = (ImageView) side_tab.findViewById(R.id.expanded_menu);
expanded_menu.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
// open drawer here
mDrawerLayout.openDrawer(Gravity.LEFT);
}
});
If the drawer is open, close it onBackPressed():
#Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
mDrawerLayout.closeDrawer(Gravity.LEFT);
return;
}
}
Hope this helps.
I extend my NavigationActivity to my DashboardActivity like below
public class DashboardActivity extends NavigationActivity {
side_tab = findViewById(R.id.side_tab);
expanded_menu = (ImageView) side_tab.findViewById(R.id.expanded_menu);
expanded_menu.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
side_tab.setVisibility(View.INVISIBLE);
drawer.openDrawer(GravityCompat.START);
}
});
and then follow the said answered by #Hassan Usman and #tahsinRupam
after that I added the DrawerLayout in my dashboard.xml
I have seen many examples around, but I could not understand how to have the navigation drawer, always open in the tablet. I'm using this navigation drawer https://github.com/kanytu/android-material-drawer-template. I will have to create another xml file? and in OnCreate () what kind of code I need to add?
public class MainActivity extends AppCompatActivity implements NavigationDrawerCallbacks {
private Toolbar mToolbar;
private NavigationDrawerFragment mNavigationDrawerFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
mNavigationDrawerFragment = (NavigationDrawerFragment) getFragmentManager().findFragmentById(R.id.fragment_drawer);
mNavigationDrawerFragment.setup(R.id.fragment_drawer, (DrawerLayout) findViewById(R.id.drawer), mToolbar);
}
#Override
public void onNavigationDrawerItemSelected(int position) {
FragmentManager fragmentManager = getFragmentManager();
..
..
}
#Override
public void onBackPressed() {
if (mNavigationDrawerFragment.isDrawerOpen())
mNavigationDrawerFragment.closeDrawer();
else
super.onBackPressed();
}
public void onResume() {
super.onResume();
}
}
I do not have the precise knowledge but a workaround could be to make a different xml file for large devices without the DrawerLayout so when it runs on a tablet it will return null and no other boolean will be neede in the code and this will make the coding part very simple :-) kudos !
I have two navigation fragments in the DrawerLayout. One navigation fragment in on the left and second is on the right.
In some cases I need to open left navigation fragment and lock it.
When I had only left navigation fragment I used drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
But when I have added second navigation fragment on the right, this method started to open and lock both panels.
How to open and lock only left navigation view in this case?
Change you code like this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawer_layout);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mLeftDrawerList = (ListView) findViewById(R.id.left_drawer);
mRightDrawerList = (ListView) findViewById(R.id.right_drawer);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,R.drawable.ic_drawer, R.string.drawer_open,R.string.drawer_close) {
public void onDrawerOpened(View view){
if(view.equals(mRightDrawerList)) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mLeftDrawerList);
} else {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, mRightDrawerList);
}
invalidateOptionsMenu();
}
public void onDrawerClosed(View view) {
if(view.equals(mRightDrawerList)) {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, mLeftDrawerList);
} else {
mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, mRightDrawerList);
}
invalidateOptionsMenu();
}
});
mDrawerLayout.setDrawerListener(mDrawerToggle);
}
This should work.
I've looked up quite a few of the questions asked about the navigation drawer and buttons and many of them are geared towards the button used for the navigation drawer itself. My question is that I can't get a button move to the next activity from the main activity that has a navigation drawer. It creates the button but the clicker doesn't move to the following activity, nor will it throw a toast to let me know that the clicker is working.
I used the template that eclipse gives you when you create a new navigation drawer.
public class UserMain extends Activity implements NavigationDrawerFragment.NavigationDrawerCallbacks {
Button one;
private NavigationDrawerFragment mNavigationDrawerFragment;
private CharSequence mTitle;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_main);
one = (Button) findViewById(R.id.button1);
System.out.println("Button1");
one.setOnClickListener(new View.OnClickListener() {
//There is a problem here!!!
#Override
public void onClick(View v) {
System.out.println(v.toString());
System.out.println("Button 1 pressed!");
// TODO Auto-generated method stub
Context context = getApplicationContext();
CharSequence text = "ONE";
int duration = Toast.LENGTH_SHORT;
Toast passwordToast = Toast.makeText(context, text, duration);
passwordToast.show();
}
});
mNavigationDrawerFragment = (NavigationDrawerFragment) getFragmentManager()
.findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
}
}