I am using this example for navigation drawer. When clicking on of item of left drawer listview it shows some images but drawerLayout closes not smoothly.
What should I
I don't use threads, because i need to update UI after close the navigation menu.
Following code works for me.
i am using fragment as member variable of class to update ui
setFragment() function use to assign fragment to fragment variable
In onDrawerClosed() event, i update ui.
mDrawerList.setOnItemClickListener(new ListView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
setFragment(position);
}
});
// for getting fragment
protected void setFragment(int p)
{
fragment = null;
switch (position)
{
case 1:
fragment = new DashboardFragment();
break;
}
if (fragment != null)
{
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(p);
mDrawerLayout.closeDrawer(mDrawerList);
}
}
// on close draw , fragment is loaded on screen
public void onDrawerClosed(View view)
{
getSupportActionBar().setTitle(mTitle);
invalidateOptionsMenu();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
}
Please review my MainActivity to make smooth DrawerLayout (open/close) with a custom topBar layout.
public class MainActivity extends BaseActivity
implements NavigationView.OnNavigationItemSelectedListener {
Fragment fragment = null;
Class fragmentClass = null;
FrameLayout frameLayout;
TextView topTilte;
DrawerLayout drawer;
NavigationView navigationView;
private boolean isDrawerOpen = false;
@Override
protected void onCreateFinished() {
setContentView(R.layout.activity_main);
drawer = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.nav_view);
topTilte = findViewById(R.id.toolbar_title);
fragmentClass = HomeFragment.class;
topTilte.setText(R.string.menu_home);
setFragment();
drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View view, float slideOffset) {
if(slideOffset > .55 && !isDrawerOpen){
onDrawerOpened(view);
isDrawerOpen = true;
} else if(slideOffset < .45 && isDrawerOpen) {
onDrawerClosed(view);
isDrawerOpen = false;
}
}
@Override
public void onDrawerOpened(@NonNull View view) {
}
@Override
public void onDrawerClosed(@NonNull View view) {
}
@Override
public void onDrawerStateChanged(int i) {
}
});
navigationView.setNavigationItemSelectedListener(this);
}
@Override
protected void afterInjection() {
}
public void openMenu(View v) {
drawer.openDrawer(Gravity.LEFT);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_home) {
topTilte.setText(R.string.menu_home);
fragmentClass = HomeFragment.class;
setFragment();
} else if (id == R.id.nav_profile) {
}
return true;
}
private void setFragment() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();
drawer.closeDrawer(GravityCompat.START);
}
}, 200);
}
}
Not sure this is the best route, but the way I solved this was to create a pending Runnable that runs in onDrawerClosed
. Eg:
private void selectItem(final int position) {
mPendingRunnable = new Runnable() {
@Override
public void run() {
// update the main content by replacing fragments
Fragment fragment = new PlanetFragment();
Bundle args = new Bundle();
args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
fragment.setArguments(args);
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
}
});
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
setTitle(mPlanetTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
@Override
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
invalidateOptionsMenu();
// If mPendingRunnable is not null, then add to the message queue
if (mPendingRunnable != null) {
mHandler.post(mPendingRunnable);
mPendingRunnable = null;
}
}
Just posting the drawerLayout.closeDrawer() on the message queue using the handler, with a minimal delay solved my problem. Handler.postDelayed() is the key here.
public void selectItem(int position)
{
switch (position)
{
case 0:
DashboardFragment dashboardFragment = new DashboardFragment();
Bundle args = new Bundle();
args.putInt(dashboardFragment.ARG_SCREEN_NUMBER, position);
dashboardFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragmentLayout, dashboardFragment, TAG_DASHBOARD);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
getSupportFragmentManager().executePendingTransactions();
break;
default:
break;
}
// Highlight the selected item, update the title, and close the drawer
drawerList.setItemChecked(position, true);
setTitle(mScreenTitles[position]);
mPendingRunnable = new Runnable()
{
@Override
public void run()
{
drawerLayout.closeDrawer(GravityCompat.START);
}
};
mHandler.postDelayed(mPendingRunnable,50);
}
Works perfect
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
mDrawerLayout.closeDrawer(mDrawerList);
mDrawerLayout.postDelayed(new Runnable() {
@Override
public void run() {
selectItem(position);
}
}, 300);
}
}