问题
I am using the new Jetpack Android Navigation in combination with a Drawer Layout. Everything is working as expected when using the same IDs in the Drawer XML in combination with Fragments in the Navigation Graph. I set everything up with:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val navController = findNavController(R.id.navigation_host_fragment)
setupActionBarWithNavController(navController, find(R.id.drawer_layout))
val navigationView = findViewById<NavigationView>(R.id.nav_view)
navigationView.setupWithNavController(findNavController(R.id.navigation_host_fragment))
}
I would now like to also trigger custom action/code and not do a fragment transaction when clicking an item in my Drawer-Menu. I have the following menu and would like to logout the user when clicked "Logout":
回答1:
I found a solution:
val navigationView = findViewById<NavigationView>(R.id.nav_view)
val logoutItem = navigationView.menu.findItem(R.id.nav_logout)
logoutItem.setOnMenuItemClickListener {
toast("Log me out")
true
}
回答2:
I found a solution too.
First, you need create Custom NavigationUI.
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.navigation.NavigationView;
import java.lang.ref.WeakReference;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
import androidx.navigation.ui.NavigationUI;
public class CustomNavigationUI {
public static void setupWithNavController(@NonNull final NavigationView navigationView,
@NonNull final NavController navController,
@Nullable final NavigationView.OnNavigationItemSelectedListener customListener) {
navigationView.setNavigationItemSelectedListener(
item -> {
boolean handled = NavigationUI.onNavDestinationSelected(item, navController);
if (handled) {
ViewParent parent = navigationView.getParent();
if (parent instanceof DrawerLayout) {
((DrawerLayout) parent).closeDrawer(navigationView);
} else {
BottomSheetBehavior bottomSheetBehavior =
findBottomSheetBehavior(navigationView);
if (bottomSheetBehavior != null) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
}
} else {
if (customListener != null) {
customListener.onNavigationItemSelected(item);
}
}
return handled;
});
final WeakReference<NavigationView> weakReference = new WeakReference<>(navigationView);
navController.addOnDestinationChangedListener(
new NavController.OnDestinationChangedListener() {
@Override
public void onDestinationChanged(@NonNull NavController controller,
@NonNull NavDestination destination, @Nullable Bundle arguments) {
NavigationView view = weakReference.get();
if (view == null) {
navController.removeOnDestinationChangedListener(this);
return;
}
Menu menu = view.getMenu();
for (int h = 0, size = menu.size(); h < size; h++) {
MenuItem item = menu.getItem(h);
item.setChecked(matchDestination(destination, item.getItemId()));
}
}
});
}
static BottomSheetBehavior findBottomSheetBehavior(@NonNull View view) {
ViewGroup.LayoutParams params = view.getLayoutParams();
if (!(params instanceof CoordinatorLayout.LayoutParams)) {
ViewParent parent = view.getParent();
if (parent instanceof View) {
return findBottomSheetBehavior((View) parent);
}
return null;
}
CoordinatorLayout.Behavior behavior = ((CoordinatorLayout.LayoutParams) params)
.getBehavior();
if (!(behavior instanceof BottomSheetBehavior)) {
// We hit a CoordinatorLayout, but the View doesn't have the BottomSheetBehavior
return null;
}
return (BottomSheetBehavior) behavior;
}
@SuppressWarnings("WeakerAccess") /* synthetic access */
static boolean matchDestination(@NonNull NavDestination destination,
@IdRes int destId) {
NavDestination currentDestination = destination;
while (currentDestination.getId() != destId && currentDestination.getParent() != null) {
currentDestination = currentDestination.getParent();
}
return currentDestination.getId() == destId;
}
}
Second, call this CustomNavigationUI instead of NavigationUI in Activity
/* NavigationUI.setupWithNavController(binding.navigationView, navController); */
CustomNavigationUI.setupWithNavController(binding.navigationView, navController, item -> {
switch (item.getItemId()){
case R.id.sign_out:
//todo sign out
break;
}
return true;
});
That's all!
来源:https://stackoverflow.com/questions/52699935/android-jetpack-navigation-custom-action-with-drawer-item