Merge branch 'refactor-set-controller-pattern-to-navigation' into refactor-navigation-and-bottom-sheet

This commit is contained in:
Tomás Villegas
2026-03-07 18:33:20 -03:00
5 changed files with 460 additions and 127 deletions

View File

@@ -0,0 +1,44 @@
package com.cappielloantonio.tempo.navigation;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.OptIn;
import androidx.appcompat.app.AppCompatActivity;
import androidx.media3.common.util.UnstableApi;
import androidx.navigation.NavController;
import com.cappielloantonio.tempo.navigation.NavigationHelper;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
public class NavigationController {
NavigationHelper helper;
public NavigationController(@NonNull NavigationHelper helper) {
this.helper = helper;
}
public void syncWithBottomSheetBehavior(BottomSheetBehavior<View> bottomSheetBehavior,
NavController navController) {
helper.syncWithBottomSheetBehavior(bottomSheetBehavior, navController);
}
public void setNavbarVisibility(boolean visibility) {
helper.setBottomNavigationBarVisibility(visibility);
}
public void setDrawerLock(boolean visibility) {
helper.setNavigationDrawerLock(visibility);
}
public void toggleDrawerLockOnOrientation(AppCompatActivity activity) {
helper.toggleNavigationDrawerLockOnOrientationChange(activity);
}
public void setSystemBarsVisibility(AppCompatActivity activity, boolean visibility) {
helper.setSystemBarsVisibility(activity, visibility);
}
}

View File

@@ -0,0 +1,167 @@
package com.cappielloantonio.tempo.navigation;
import android.content.Context;
import android.content.res.Configuration;
import android.view.View;
import android.view.Window;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.OptIn;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.view.WindowCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.media3.common.util.UnstableApi;
import androidx.navigation.NavController;
import androidx.navigation.NavDestination;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.NavigationUI;
import com.cappielloantonio.tempo.R;
import com.cappielloantonio.tempo.ui.activity.MainActivity;
import com.cappielloantonio.tempo.util.Preferences;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.navigation.NavigationView;
import org.jetbrains.annotations.Contract;
import java.util.Objects;
public class NavigationHelper {
/* UI components */
private BottomNavigationView bottomNavigationView;
private FrameLayout bottomNavigationViewFrame;
private DrawerLayout drawerLayout;
/* Navigation components */
private NavigationView navigationView;
private NavHostFragment navHostFragment;
/* States that need to be remembered */
// -- //
/* Private constructor */
public NavigationHelper(@NonNull BottomNavigationView bottomNavigationView,
@NonNull FrameLayout bottomNavigationViewFrame,
@NonNull DrawerLayout drawerLayout,
@NonNull NavigationView navigationView,
@NonNull NavHostFragment navHostFragment) {
this.bottomNavigationView = bottomNavigationView;
this.bottomNavigationViewFrame = bottomNavigationViewFrame;
this.drawerLayout = drawerLayout;
this.navigationView = navigationView;
this.navHostFragment = navHostFragment;
}
public void syncWithBottomSheetBehavior(@NonNull BottomSheetBehavior<View> bottomSheetBehavior,
@NonNull NavController navController) {
navController.addOnDestinationChangedListener(
(controller, destination, arguments) -> {
// React to the user clicking one of these on bottom-navbar/drawer
boolean isTarget = isTargetDestination(destination);
int currentState = bottomSheetBehavior.getState();
if (isTarget && currentState == BottomSheetBehavior.STATE_EXPANDED) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
});
NavigationUI.setupWithNavController(bottomNavigationView, navController);
NavigationUI.setupWithNavController(navigationView, navController);
}
@Contract(pure = true)
private static boolean isTargetDestination(NavDestination destination) {
int destId = destination.getId();
return destId == R.id.homeFragment ||
destId == R.id.libraryFragment ||
destId == R.id.downloadFragment ||
destId == R.id.albumCatalogueFragment ||
destId == R.id.artistCatalogueFragment ||
destId == R.id.genreCatalogueFragment ||
destId == R.id.playlistCatalogueFragment;
}
/*
Clean public methods
Removes the need to invoke the activity on the fragment
*/
public void setBottomNavigationBarVisibility(boolean visible) {
int visibility = visible
? View.VISIBLE
: View.GONE;
bottomNavigationView.setVisibility(visibility);
bottomNavigationViewFrame.setVisibility(visibility);
}
public void setNavigationDrawerLock(boolean locked) {
int mode = locked
? DrawerLayout.LOCK_MODE_LOCKED_CLOSED
: DrawerLayout.LOCK_MODE_UNLOCKED;
drawerLayout.setDrawerLockMode(mode);
}
@OptIn(markerClass = UnstableApi.class)
public void toggleNavigationDrawerLockOnOrientationChange(
AppCompatActivity activity) {
int orientation = activity.getResources().getConfiguration().orientation;
boolean isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE;
if (Preferences.getEnableDrawerOnPortrait()) {
setNavigationDrawerLock(false);
return;
}
setNavigationDrawerLock(!isLandscape);
}
/*
All of these are the "backward compatible" changes that don't break the assumption
that everything was defined on the activity and is gobally available
*/
@NonNull
public BottomNavigationView getBottomNavigationView() {
return bottomNavigationView;
}
@NonNull
public FrameLayout getBottomNavigationViewFrame() {
return bottomNavigationViewFrame;
}
@NonNull
public DrawerLayout getDrawerLayout() {
return drawerLayout;
}
/*
Auxiliar functions, could be moved somewhere else
*/
@OptIn(markerClass = UnstableApi.class)
public void setSystemBarsVisibility(AppCompatActivity activity, boolean visibility) {
WindowInsetsControllerCompat insetsController;
Window window = activity.getWindow();
View decorView = window.getDecorView();
insetsController = new WindowInsetsControllerCompat(window, decorView);
if (visibility) {
WindowCompat.setDecorFitsSystemWindows(window, true);
insetsController.show(WindowInsetsCompat.Type.navigationBars());
insetsController.show(WindowInsetsCompat.Type.statusBars());
insetsController.setSystemBarsBehavior(
WindowInsetsControllerCompat.BEHAVIOR_DEFAULT);
} else {
WindowCompat.setDecorFitsSystemWindows(window, false);
insetsController.hide(WindowInsetsCompat.Type.navigationBars());
insetsController.hide(WindowInsetsCompat.Type.statusBars());
insetsController.setSystemBarsBehavior(
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
}
}
}

View File

@@ -4,7 +4,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
@@ -31,7 +30,6 @@ import androidx.media3.common.Player;
import androidx.media3.common.util.UnstableApi;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.NavigationUI;
import com.cappielloantonio.tempo.App;
import com.cappielloantonio.tempo.BuildConfig;
@@ -39,8 +37,12 @@ import com.cappielloantonio.tempo.R;
import com.cappielloantonio.tempo.broadcast.receiver.ConnectivityStatusBroadcastReceiver;
import com.cappielloantonio.tempo.databinding.ActivityMainBinding;
import com.cappielloantonio.tempo.github.utils.UpdateUtil;
import com.cappielloantonio.tempo.navigation.NavigationController;
import com.cappielloantonio.tempo.navigation.NavigationHelper;
import com.cappielloantonio.tempo.service.MediaManager;
import com.cappielloantonio.tempo.ui.activity.base.BaseActivity;
import com.cappielloantonio.tempo.ui.controller.BottomSheetController;
import com.cappielloantonio.tempo.ui.controller.BottomSheetHelper;
import com.cappielloantonio.tempo.ui.dialog.ConnectionAlertDialog;
import com.cappielloantonio.tempo.ui.dialog.GithubTempoUpdateDialog;
import com.cappielloantonio.tempo.ui.dialog.ServerUnreachableDialog;
@@ -70,10 +72,12 @@ public class MainActivity extends BaseActivity {
private NavHostFragment navHostFragment;
private BottomNavigationView bottomNavigationView;
private FrameLayout bottomNavigationViewFrame;
public NavController navController;
private DrawerLayout drawerLayout;
private NavigationView navigationView;
private BottomSheetBehavior bottomSheetBehavior;
public NavController navController;
private NavigationController navigationController;
private BottomSheetController bottomSheetController;
public BottomSheetBehavior bottomSheetBehavior;
public boolean isLandscape = false;
private AssetLinkNavigator assetLinkNavigator;
private AssetLinkUtil.AssetLink pendingAssetLink;
@@ -81,6 +85,10 @@ public class MainActivity extends BaseActivity {
ConnectivityStatusBroadcastReceiver connectivityStatusBroadcastReceiver;
private Intent pendingDownloadPlaybackIntent;
public ActivityMainBinding getBinding() {
return bind;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
SplashScreen.installSplashScreen(this);
@@ -147,7 +155,6 @@ public class MainActivity extends BaseActivity {
}
public void init() {
fragmentManager = getSupportFragmentManager();
initBottomSheet();
initNavigation();
@@ -162,49 +169,74 @@ public class MainActivity extends BaseActivity {
}
// BOTTOM SHEET/NAVIGATION
private void initBottomSheet() {
bottomSheetBehavior = BottomSheetBehavior.from(findViewById(R.id.player_bottom_sheet));
bottomSheetBehavior.addBottomSheetCallback(bottomSheetCallback);
fragmentManager.beginTransaction().replace(R.id.player_bottom_sheet, new PlayerBottomSheetFragment(), "PlayerBottomSheet").commit();
private void initNavigation() {
// We link the nav_graph.xml with our navigationController
NavHostFragment navHostFragment = (NavHostFragment) this
.getSupportFragmentManager()
.findFragmentById(R.id.nav_host_fragment);
navController = Objects.requireNonNull(navHostFragment).getNavController();
/*
navController is currently global since some legacy code still invokes it directly
the MainActivity methods that use it must be converted to NavigationHelper methods
*/
checkBottomSheetAfterStateChanged();
// Helper
NavigationHelper navigationHelper =
new NavigationHelper(
findViewById(R.id.bottom_navigation),
findViewById(R.id.bottom_navigation_frame),
findViewById(R.id.drawer_layout),
findViewById(R.id.nav_view),
navHostFragment
);
// Controller
navigationController = new NavigationController(navigationHelper);
navigationController.syncWithBottomSheetBehavior(bottomSheetBehavior, navController);
}
private void initBottomSheet() {
FragmentManager fragmentManager = getSupportFragmentManager();
View bottomSheetView = findViewById(R.id.player_bottom_sheet);
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetView);
/*
bottomSheetBehavior is currently global since some legacy code still invokes it directly
the MainActivity methods that use it must be converted to BottomSheetHelper methods
*/
// Helper
BottomSheetHelper bottomSheetHelper =
new BottomSheetHelper(
bottomSheetBehavior,
bottomSheetView,
fragmentManager
);
// Controller
bottomSheetController = new BottomSheetController(bottomSheetHelper);
bottomSheetController.addCallback(bottomSheetCallback);
bottomSheetController.replaceFragment(R.id.player_bottom_sheet);
bottomSheetController.checkAfterStateChanged(mainViewModel);
}
public void setBottomSheetInPeek(Boolean isVisible) {
if (isVisible) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
bottomSheetController.setStateInPeek(isVisible);
}
public void setBottomSheetVisibility(boolean visibility) {
if (visibility) {
findViewById(R.id.player_bottom_sheet).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.player_bottom_sheet).setVisibility(View.GONE);
}
}
private void checkBottomSheetAfterStateChanged() {
final Handler handler = new Handler();
final Runnable runnable = () -> setBottomSheetInPeek(mainViewModel.isQueueLoaded());
handler.postDelayed(runnable, 100);
bottomSheetController.setVisibility(visibility);
}
public void collapseBottomSheetDelayed() {
final Handler handler = new Handler();
final Runnable runnable = () -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
handler.postDelayed(runnable, 100);
bottomSheetController.collapseDelayed();
}
public void expandBottomSheet() {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
bottomSheetController.expand();
}
public void setBottomSheetDraggableState(Boolean isDraggable) {
bottomSheetBehavior.setDraggable(isDraggable);
bottomSheetController.setDraggable(isDraggable);
}
private final BottomSheetBehavior.BottomSheetCallback bottomSheetCallback =
@@ -217,7 +249,7 @@ public class MainActivity extends BaseActivity {
switch (state) {
case BottomSheetBehavior.STATE_HIDDEN:
resetMusicSession();
resetMusicSession(); // I can't put the callback inside BottomSheetHelper because of this line
break;
case BottomSheetBehavior.STATE_COLLAPSED:
if (playerBottomSheetFragment != null)
@@ -241,12 +273,7 @@ public class MainActivity extends BaseActivity {
};
private void animateBottomSheet(float slideOffset) {
PlayerBottomSheetFragment playerBottomSheetFragment = (PlayerBottomSheetFragment) getSupportFragmentManager().findFragmentByTag("PlayerBottomSheet");
if (playerBottomSheetFragment != null) {
float condensedSlideOffset = Math.max(0.0f, Math.min(0.2f, slideOffset - 0.2f)) / 0.2f;
playerBottomSheetFragment.getPlayerHeader().setAlpha(1 - condensedSlideOffset);
playerBottomSheetFragment.getPlayerHeader().setVisibility(condensedSlideOffset > 0.99 ? View.GONE : View.VISIBLE);
}
bottomSheetController.animate(slideOffset);
}
private void animateBottomNavigation(float slideOffset, int navigationHeight) {
@@ -261,117 +288,52 @@ public class MainActivity extends BaseActivity {
bind.bottomNavigation.setTranslationY(slideY);
}
private void initNavigation() {
bottomNavigationView = findViewById(R.id.bottom_navigation);
bottomNavigationViewFrame = findViewById(R.id.bottom_navigation_frame);
navHostFragment = (NavHostFragment) fragmentManager.findFragmentById(R.id.nav_host_fragment);
navController = Objects.requireNonNull(navHostFragment).getNavController();
// This is the lateral slide-in drawer
drawerLayout = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.nav_view);
/*
* In questo modo intercetto il cambio schermata tramite navbar e se il bottom sheet è aperto,
* lo chiudo
*/
navController.addOnDestinationChangedListener((controller, destination, arguments) -> {
if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED && (
destination.getId() == R.id.homeFragment ||
destination.getId() == R.id.libraryFragment ||
destination.getId() == R.id.downloadFragment ||
destination.getId() == R.id.albumCatalogueFragment ||
destination.getId() == R.id.artistCatalogueFragment ||
destination.getId() == R.id.genreCatalogueFragment ||
destination.getId() == R.id.playlistCatalogueFragment)
) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
}
});
NavigationUI.setupWithNavController(bottomNavigationView, navController);
NavigationUI.setupWithNavController(navigationView, navController);
}
public void setBottomNavigationBarVisibility(boolean visibility) {
if (visibility) {
bottomNavigationView.setVisibility(View.VISIBLE);
bottomNavigationViewFrame.setVisibility(View.VISIBLE);
} else {
bottomNavigationView.setVisibility(View.GONE);
bottomNavigationViewFrame.setVisibility(View.GONE);
}
navigationController.setNavbarVisibility(visibility);
}
public void toggleBottomNavigationBarVisibilityOnOrientationChange() {
float displayDensity = getResources().getDisplayMetrics().density;
// Ignore orientation change, bottom navbar always hidden
if (Preferences.getHideBottomNavbarOnPortrait()) {
setBottomNavigationBarVisibility(false);
setPortraitPlayerBottomSheetPeekHeight(56);
setSystemBarsVisibility(!isLandscape);
navigationController.setNavbarVisibility(false);
bottomSheetController.setPeekHeight(56, displayDensity);
navigationController.setSystemBarsVisibility(this, !isLandscape);
return;
}
if (!isLandscape) {
// Show app navbar + show system bars
setPortraitPlayerBottomSheetPeekHeight(136);
setBottomNavigationBarVisibility(true);
setSystemBarsVisibility(true);
bottomSheetController.setPeekHeight(136, displayDensity);
navigationController.setNavbarVisibility(true);
navigationController.setSystemBarsVisibility(this, true);
} else {
// Hide app navbar + hide system bars
setPortraitPlayerBottomSheetPeekHeight(56);
setBottomNavigationBarVisibility(false);
setSystemBarsVisibility(false);
bottomSheetController.setPeekHeight(56, displayDensity);
navigationController.setNavbarVisibility(false);
navigationController.setSystemBarsVisibility(this, false);
}
}
public void setNavigationDrawerLock(boolean locked) {
int mode = locked
? DrawerLayout.LOCK_MODE_LOCKED_CLOSED
: DrawerLayout.LOCK_MODE_UNLOCKED;
drawerLayout.setDrawerLockMode(mode);
navigationController.setDrawerLock(locked);
}
public void toggleNavigationDrawerLockOnOrientationChange() {
// Ignore orientation check, drawer always unlocked
if (Preferences.getEnableDrawerOnPortrait()) {
setNavigationDrawerLock(false);
return;
}
if (!isLandscape) {
setNavigationDrawerLock(true);
} else {
setNavigationDrawerLock(false);
}
navigationController.toggleDrawerLockOnOrientation(this);
}
public void setSystemBarsVisibility(boolean visibility) {
WindowInsetsControllerCompat insetsController;
View decorView = getWindow().getDecorView();
insetsController = new WindowInsetsControllerCompat(getWindow(), decorView);
if (visibility) {
WindowCompat.setDecorFitsSystemWindows(getWindow(), true);
insetsController.show(WindowInsetsCompat.Type.navigationBars());
insetsController.show(WindowInsetsCompat.Type.statusBars());
insetsController.setSystemBarsBehavior(
WindowInsetsControllerCompat.BEHAVIOR_DEFAULT);
} else {
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
insetsController.hide(WindowInsetsCompat.Type.navigationBars());
insetsController.hide(WindowInsetsCompat.Type.statusBars());
insetsController.setSystemBarsBehavior(
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
}
navigationController.setSystemBarsVisibility(this, visibility);
}
private void setPortraitPlayerBottomSheetPeekHeight(int peekHeight) {
FrameLayout bottomSheet = findViewById(R.id.player_bottom_sheet);
BottomSheetBehavior<FrameLayout> behavior =
BottomSheetBehavior.from(bottomSheet);
int newPeekPx = (int) (peekHeight * getResources().getDisplayMetrics().density);
behavior.setPeekHeight(newPeekPx);
}
/*
There are only 4 init functions that must exist up to here
1. init()
2. initNavigation()
3. initBottomSheet()
4. bottomSheetCallback = new BottomSheetBehavior.BottomSheetCallback() { ... }
*/
private void initService() {
MediaManager.check(getMediaBrowserListenableFuture());
@@ -407,7 +369,7 @@ public class MainActivity extends BaseActivity {
}
private void goToHome() {
bottomNavigationView.setVisibility(View.VISIBLE);
setBottomNavigationBarVisibility(true);
if (Objects.requireNonNull(navController.getCurrentDestination()).getId() == R.id.landingFragment) {
navController.navigate(R.id.action_landingFragment_to_homeFragment);
@@ -657,4 +619,4 @@ public class MainActivity extends BaseActivity {
MediaManager.playDownloadedMediaItem(getMediaBrowserListenableFuture(), mediaItem);
}
}
}

View File

@@ -0,0 +1,63 @@
package com.cappielloantonio.tempo.ui.controller;
import androidx.annotation.NonNull;
import com.cappielloantonio.tempo.viewmodel.MainViewModel;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
public class BottomSheetController {
BottomSheetHelper helper;
public BottomSheetController(@NonNull BottomSheetHelper bottomSheetPlayerHelper) {
this.helper = bottomSheetPlayerHelper;
}
public void expand() {
helper.setState(BottomSheetBehavior.STATE_EXPANDED);
}
public void hide() {
helper.setState(BottomSheetBehavior.STATE_HIDDEN);
}
public void setStateInPeek(boolean isVisible) {
helper.setStateInPeek(isVisible);
}
public void setVisibility(boolean visibility) {
helper.setVisibility(visibility);
}
public void addCallback(BottomSheetBehavior.BottomSheetCallback callback) {
helper.addCallback(callback);
}
public void replaceFragment(int playerBottomSheet) {
helper.replaceFragment(playerBottomSheet);
}
public void checkAfterStateChanged(MainViewModel mainViewModel) {
helper.checkAfterStateChanged(mainViewModel);
}
public void collapseDelayed() {
helper.collapseDelayed();
}
public void setDraggable(Boolean isDraggable) {
helper.setDraggable(isDraggable);
}
public int getState() {
return helper.getState();
}
public void animate(float slideOffset) {
helper.animate(slideOffset);
}
public void setPeekHeight(int peekHeight, float displayDensity) {
helper.setPeekHeight(peekHeight, displayDensity);
}
}

View File

@@ -0,0 +1,97 @@
package com.cappielloantonio.tempo.ui.controller;
import android.os.Handler;
import android.view.View;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentManager;
import com.cappielloantonio.tempo.R;
import com.cappielloantonio.tempo.ui.fragment.PlayerBottomSheetFragment;
import com.cappielloantonio.tempo.viewmodel.MainViewModel;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
public class BottomSheetHelper {
BottomSheetBehavior<View> bottomSheetBehavior;
View bottomSheetView;
FragmentManager fragmentManager; // Of the entire activity
PlayerBottomSheetFragment playerBottomSheetFragment;
public void setState(int state) {
bottomSheetBehavior.setState(state);
}
public BottomSheetHelper(@NonNull BottomSheetBehavior<View> bottomSheetBehavior,
@NonNull View bottomSheetView,
@NonNull FragmentManager fragmentManager) {
this.bottomSheetBehavior = bottomSheetBehavior;
this.bottomSheetView = bottomSheetView;
this.fragmentManager = fragmentManager;
this.playerBottomSheetFragment = new PlayerBottomSheetFragment();
}
public void addCallback(BottomSheetBehavior.BottomSheetCallback callback) {
bottomSheetBehavior.addBottomSheetCallback(callback);
}
public void setStateInPeek(boolean isVisible) {
if (isVisible) {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
} else {
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_HIDDEN);
}
}
public void setVisibility(boolean visibility) {
if (visibility) {
bottomSheetView.setVisibility(View.VISIBLE);
} else {
bottomSheetView.setVisibility(View.GONE);
}
}
public void replaceFragment(int playerBottomSheet) {
fragmentManager
.beginTransaction()
.replace(
playerBottomSheet,
playerBottomSheetFragment,
"PlayerBottomSheet")
.commit();
}
public void checkAfterStateChanged(MainViewModel mainViewModel) {
final Handler handler = new Handler();
final Runnable runnable = () -> setStateInPeek(mainViewModel.isQueueLoaded());
handler.postDelayed(runnable, 100);
}
public void collapseDelayed() {
final Handler handler = new Handler();
final Runnable runnable = () -> bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
handler.postDelayed(runnable, 100);
}
public void setDraggable(Boolean isDraggable) {
bottomSheetBehavior.setDraggable((isDraggable));
}
public int getState() {
return bottomSheetBehavior.getState();
}
public void animate(float slideOffset) {
if (playerBottomSheetFragment != null) {
float condensedSlideOffset = Math.max(0.0f, Math.min(0.2f, slideOffset - 0.2f)) / 0.2f;
playerBottomSheetFragment.getPlayerHeader().setAlpha(1 - condensedSlideOffset);
playerBottomSheetFragment.getPlayerHeader().setVisibility(condensedSlideOffset > 0.99 ? View.GONE : View.VISIBLE);
}
}
public void setPeekHeight(int peekHeight, float displayDensity) {
int newPeekPx = (int) (peekHeight * displayDensity);
bottomSheetBehavior.setPeekHeight(newPeekPx);
}
}