Improve settings navigation layout

This commit is contained in:
ajp_anton
2026-06-18 09:24:52 +00:00
parent 28cc72b7ea
commit 978346624e
4 changed files with 190 additions and 31 deletions
@@ -5,7 +5,9 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle; import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
@@ -22,10 +24,16 @@ import se.ajpanton.statusbartweak.R;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private static final String EXTRA_OPEN_NAV_ITEM = "open_nav_item"; private static final String EXTRA_OPEN_NAV_ITEM = "open_nav_item";
private static final float PERMANENT_SIDEBAR_FOLDED_WIDTH_MULTIPLIER = 1.1f;
private SafeInsetDrawerLayout drawerLayout; private SafeInsetDrawerLayout drawerLayout;
private NavigationView navigationView; private NavigationView drawerNavigationView;
private Integer navigationBasePaddingLeft; private NavigationView permanentNavigationView;
private MaterialToolbar toolbar;
private ActionBarDrawerToggle drawerToggle;
private Integer drawerNavigationBasePaddingLeft;
private Integer permanentNavigationBasePaddingLeft;
private boolean permanentSidebar;
public static Intent newOpenDebugIntent(Context context) { public static Intent newOpenDebugIntent(Context context) {
Intent intent = new Intent(context, MainActivity.class); Intent intent = new Intent(context, MainActivity.class);
@@ -39,24 +47,42 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
MaterialToolbar toolbar = findViewById(R.id.toolbar); toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
drawerLayout = findViewById(R.id.drawer_layout); drawerLayout = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.nav_view); drawerNavigationView = findViewById(R.id.nav_view_drawer);
navigationView.setNavigationItemSelectedListener(this); permanentNavigationView = findViewById(R.id.nav_view_permanent);
navigationView.getMenu().setGroupCheckable(0, true, true); setupNavigationView(drawerNavigationView);
setupNavigationView(permanentNavigationView);
applyNavigationDrawerInsets(); applyNavigationDrawerInsets();
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( drawerToggle = new ActionBarDrawerToggle(
this, this,
drawerLayout, drawerLayout,
toolbar, toolbar,
R.string.nav_open, R.string.nav_open,
R.string.nav_close R.string.nav_close
); );
drawerLayout.addDrawerListener(toggle); drawerLayout.addDrawerListener(drawerToggle);
toggle.syncState(); drawerToggle.syncState();
toolbar.setNavigationOnClickListener(v -> {
if (!permanentSidebar) {
drawerLayout.openDrawer(GravityCompat.START);
}
});
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
@Override
public void handleOnBackPressed() {
if (!permanentSidebar && drawerLayout.isDrawerOpen(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
return;
}
setEnabled(false);
getOnBackPressedDispatcher().onBackPressed();
setEnabled(true);
}
});
if (savedInstanceState == null) { if (savedInstanceState == null) {
int initialItemId = resolveInitialItemId(getIntent()); int initialItemId = resolveInitialItemId(getIntent());
@@ -77,7 +103,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
@Override @Override
public boolean onNavigationItemSelected(@NonNull android.view.MenuItem item) { public boolean onNavigationItemSelected(@NonNull android.view.MenuItem item) {
navigateTo(item.getItemId()); navigateTo(item.getItemId());
if (!permanentSidebar) {
drawerLayout.closeDrawer(GravityCompat.START); drawerLayout.closeDrawer(GravityCompat.START);
}
return true; return true;
} }
@@ -149,6 +177,11 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
} }
private void syncDrawerSelection(int itemId) { private void syncDrawerSelection(int itemId) {
syncNavigationSelection(drawerNavigationView, itemId);
syncNavigationSelection(permanentNavigationView, itemId);
}
private void syncNavigationSelection(NavigationView navigationView, int itemId) {
if (navigationView == null) { if (navigationView == null) {
return; return;
} }
@@ -167,6 +200,17 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
navigationView.invalidate(); navigationView.invalidate();
} }
private void setupNavigationView(NavigationView navigationView) {
if (navigationView == null) {
return;
}
navigationView.setNavigationItemSelectedListener(this);
navigationView.getMenu().setGroupCheckable(0, true, true);
navigationView.addOnLayoutChangeListener((view, left, top, right, bottom,
oldLeft, oldTop, oldRight, oldBottom) ->
updateNavigationHeaderHeight(navigationView));
}
private int resolveInitialItemId(Intent intent) { private int resolveInitialItemId(Intent intent) {
int requested = resolveOpenItemId(intent); int requested = resolveOpenItemId(intent);
return requested != -1 ? requested : R.id.nav_layout; return requested != -1 ? requested : R.id.nav_layout;
@@ -195,6 +239,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
private void applyNavigationDrawerMarginsFromRootInsets() { private void applyNavigationDrawerMarginsFromRootInsets() {
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(drawerLayout); WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(drawerLayout);
if (insets == null) { if (insets == null) {
applyNavigationDrawerSafeArea(0, 0);
return; return;
} }
Insets safeInsets = insets.getInsetsIgnoringVisibility( Insets safeInsets = insets.getInsetsIgnoringVisibility(
@@ -206,10 +251,25 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
int safeLeft = Math.max(Math.max(0, leftInset), Math.max(0, drawerLayout.getPaddingLeft())); int safeLeft = Math.max(Math.max(0, leftInset), Math.max(0, drawerLayout.getPaddingLeft()));
int safeRight = Math.max(Math.max(0, rightInset), Math.max(0, drawerLayout.getPaddingRight())); int safeRight = Math.max(Math.max(0, rightInset), Math.max(0, drawerLayout.getPaddingRight()));
drawerLayout.setDrawerSafeInsets(safeLeft, safeRight); drawerLayout.setDrawerSafeInsets(safeLeft, safeRight);
if (navigationBasePaddingLeft == null) { drawerNavigationBasePaddingLeft = applyNavigationLeftPadding(
navigationBasePaddingLeft = navigationView.getPaddingLeft(); drawerNavigationView,
drawerNavigationBasePaddingLeft,
safeLeft);
permanentNavigationBasePaddingLeft = applyNavigationLeftPadding(
permanentNavigationView,
permanentNavigationBasePaddingLeft,
0);
updatePermanentSidebarMode();
} }
int leftPadding = navigationBasePaddingLeft + safeLeft;
private Integer applyNavigationLeftPadding(NavigationView navigationView,
Integer basePaddingLeft,
int safeLeft) {
if (navigationView == null) {
return basePaddingLeft;
}
int base = basePaddingLeft != null ? basePaddingLeft : navigationView.getPaddingLeft();
int leftPadding = base + safeLeft;
if (navigationView.getPaddingLeft() != leftPadding if (navigationView.getPaddingLeft() != leftPadding
|| Math.round(navigationView.getTranslationX()) != 0) { || Math.round(navigationView.getTranslationX()) != 0) {
navigationView.setTranslationX(0f); navigationView.setTranslationX(0f);
@@ -220,5 +280,72 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
navigationView.getPaddingBottom()); navigationView.getPaddingBottom());
navigationView.requestLayout(); navigationView.requestLayout();
} }
return base;
}
private void updatePermanentSidebarMode() {
int rootWidth = drawerLayout.getWidth();
if (rootWidth <= 0) {
return;
}
int drawerWidth = getResources().getDimensionPixelSize(R.dimen.sbt_navigation_drawer_width);
int foldedPortraitWidth = getResources().getDimensionPixelSize(R.dimen.sbt_folded_portrait_width);
boolean shouldUsePermanentSidebar = rootWidth >= drawerWidth
+ Math.round(foldedPortraitWidth * PERMANENT_SIDEBAR_FOLDED_WIDTH_MULTIPLIER);
if (permanentSidebar != shouldUsePermanentSidebar) {
permanentSidebar = shouldUsePermanentSidebar;
drawerToggle.setDrawerIndicatorEnabled(!permanentSidebar);
toolbar.setVisibility(permanentSidebar ? View.GONE : View.VISIBLE);
if (permanentSidebar) {
permanentNavigationView.setVisibility(View.VISIBLE);
drawerLayout.closeDrawer(GravityCompat.START, false);
} else {
drawerNavigationView.setVisibility(View.VISIBLE);
drawerLayout.closeDrawer(GravityCompat.START, false);
permanentNavigationView.setVisibility(View.GONE);
drawerNavigationView.requestLayout();
}
drawerToggle.syncState();
}
updateNavigationHeaderHeight(drawerNavigationView);
updateNavigationHeaderHeight(permanentNavigationView);
}
private void updateNavigationHeaderHeight(NavigationView navigationView) {
if (navigationView == null || navigationView.getHeaderCount() == 0) {
return;
}
int navigationHeight = navigationView.getHeight();
if (navigationHeight <= 0) {
return;
}
int menuRows = countVisibleMenuRows(navigationView.getMenu());
int menuHeight = menuRows * getResources().getDimensionPixelSize(R.dimen.sbt_navigation_menu_item_height);
int minHeaderHeight = getResources().getDimensionPixelSize(R.dimen.sbt_drawer_header_min_height);
int maxHeaderHeight = getResources().getDimensionPixelSize(R.dimen.sbt_drawer_header_max_height);
int desiredHeaderHeight = Math.max(
minHeaderHeight,
Math.min(maxHeaderHeight, navigationHeight - menuHeight));
View header = navigationView.getHeaderView(0);
if (header == null || header.getLayoutParams() == null
|| header.getLayoutParams().height == desiredHeaderHeight) {
return;
}
header.getLayoutParams().height = desiredHeaderHeight;
header.requestLayout();
}
private int countVisibleMenuRows(Menu menu) {
if (menu == null) {
return 0;
}
int count = 0;
for (int i = 0; i < menu.size(); i++) {
MenuItem item = menu.getItem(i);
if (item != null && item.isVisible()) {
count++;
}
}
return count;
} }
} }
+24 -2
View File
@@ -9,8 +9,28 @@
android:fitsSystemWindows="true"> android:fitsSystemWindows="true">
<LinearLayout <LinearLayout
android:id="@+id/main_shell"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="horizontal">
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view_permanent"
android:layout_width="@dimen/sbt_navigation_drawer_width"
android:layout_height="match_parent"
android:background="@color/sbt_surface"
android:fitsSystemWindows="true"
android:visibility="gone"
app:headerLayout="@layout/drawer_header"
app:itemBackground="@drawable/drawer_item_background"
app:itemTextColor="@color/drawer_item_text_color"
app:menu="@menu/drawer_menu" />
<LinearLayout
android:id="@+id/main_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"> android:orientation="vertical">
<com.google.android.material.appbar.MaterialToolbar <com.google.android.material.appbar.MaterialToolbar
@@ -30,9 +50,11 @@
</LinearLayout> </LinearLayout>
</LinearLayout>
<com.google.android.material.navigation.NavigationView <com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view" android:id="@+id/nav_view_drawer"
android:layout_width="wrap_content" android:layout_width="@dimen/sbt_navigation_drawer_width"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="start" android:layout_gravity="start"
android:background="@color/sbt_surface" android:background="@color/sbt_surface"
+2 -2
View File
@@ -2,11 +2,11 @@
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="172dp" android:layout_height="@dimen/sbt_drawer_header_height"
android:background="@drawable/sbt_drawer_header_background" android:background="@drawable/sbt_drawer_header_background"
android:gravity="bottom" android:gravity="bottom"
android:orientation="vertical" android:orientation="vertical"
android:padding="20dp"> android:padding="@dimen/sbt_drawer_header_padding">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="sbt_navigation_drawer_width">216dp</dimen>
<dimen name="sbt_folded_portrait_width">360dp</dimen>
<dimen name="sbt_navigation_menu_item_height">48dp</dimen>
<dimen name="sbt_drawer_header_height">86dp</dimen>
<dimen name="sbt_drawer_header_min_height">86dp</dimen>
<dimen name="sbt_drawer_header_max_height">172dp</dimen>
<dimen name="sbt_drawer_header_padding">16dp</dimen>
</resources>