mirror of
https://github.com/antebudimir/tempus.git
synced 2026-04-15 16:27:26 +00:00
wip: added fab, need to implement actions
This commit is contained in:
parent
97d1b408e1
commit
38fb2c69f1
2 changed files with 228 additions and 40 deletions
|
|
@ -39,6 +39,20 @@ public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
|||
|
||||
private InnerFragmentPlayerQueueBinding bind;
|
||||
|
||||
private com.google.android.material.floatingactionbutton.FloatingActionButton fabMenuToggle;
|
||||
private com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton fabClearQueue;
|
||||
private com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton fabShuffleQueue;
|
||||
|
||||
|
||||
private com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton fabSaveToPlaylist;
|
||||
private com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton fabDownloadAll;
|
||||
private com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton fabSaveQueue;
|
||||
private com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton fabLoadQueue;
|
||||
|
||||
private boolean isMenuOpen = false;
|
||||
private final int ANIMATION_DURATION = 250;
|
||||
private final float FAB_VERTICAL_SPACING_DP = 70f;
|
||||
|
||||
private PlayerBottomSheetViewModel playerBottomSheetViewModel;
|
||||
private PlaybackViewModel playbackViewModel;
|
||||
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||
|
|
@ -53,6 +67,24 @@ public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
|||
playerBottomSheetViewModel = new ViewModelProvider(requireActivity()).get(PlayerBottomSheetViewModel.class);
|
||||
playbackViewModel = new ViewModelProvider(requireActivity()).get(PlaybackViewModel.class);
|
||||
|
||||
fabMenuToggle = bind.fabMenuToggle;
|
||||
fabClearQueue = bind.fabClearQueue;
|
||||
fabShuffleQueue = bind.fabShuffleQueue;
|
||||
|
||||
fabSaveToPlaylist = bind.fabSaveToPlaylist;
|
||||
fabDownloadAll = bind.fabDownloadAll;
|
||||
fabSaveQueue = bind.fabSaveQueue;
|
||||
fabLoadQueue = bind.fabLoadQueue;
|
||||
|
||||
fabMenuToggle.setOnClickListener(v -> toggleFabMenu());
|
||||
fabClearQueue.setOnClickListener(v -> handleClearQueueClick());
|
||||
fabShuffleQueue.setOnClickListener(v -> handleShuffleQueueClick());
|
||||
|
||||
fabSaveToPlaylist.setOnClickListener(v -> handleSaveToPlaylistClick());
|
||||
fabDownloadAll.setOnClickListener(v -> handleDownloadAllClick());
|
||||
fabSaveQueue.setOnClickListener(v -> handleSaveQueueClick());
|
||||
fabLoadQueue.setOnClickListener(v -> handleLoadQueueClick());
|
||||
|
||||
initQueueRecyclerView();
|
||||
|
||||
return view;
|
||||
|
|
@ -109,8 +141,8 @@ public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
|||
mediaBrowserListenableFuture.addListener(() -> {
|
||||
try {
|
||||
MediaBrowser mediaBrowser = mediaBrowserListenableFuture.get();
|
||||
initShuffleButton(mediaBrowser);
|
||||
initCleanButton(mediaBrowser);
|
||||
// initShuffleButton(mediaBrowser);
|
||||
// initCleanButton(mediaBrowser);
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
|
@ -188,45 +220,45 @@ public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
|||
}).attachToRecyclerView(bind.playerQueueRecyclerView);
|
||||
}
|
||||
|
||||
private void initShuffleButton(MediaBrowser mediaBrowser) {
|
||||
bind.playerShuffleQueueFab.setOnClickListener(view -> {
|
||||
int startPosition = mediaBrowser.getCurrentMediaItemIndex() + 1;
|
||||
int endPosition = playerSongQueueAdapter.getItems().size() - 1;
|
||||
// private void initShuffleButton(MediaBrowser mediaBrowser) {
|
||||
// bind.playerShuffleQueueFab.setOnClickListener(view -> {
|
||||
// int startPosition = mediaBrowser.getCurrentMediaItemIndex() + 1;
|
||||
// int endPosition = playerSongQueueAdapter.getItems().size() - 1;
|
||||
|
||||
if (startPosition < endPosition) {
|
||||
ArrayList<Integer> pool = new ArrayList<>();
|
||||
// if (startPosition < endPosition) {
|
||||
// ArrayList<Integer> pool = new ArrayList<>();
|
||||
|
||||
for (int i = startPosition; i <= endPosition; i++) {
|
||||
pool.add(i);
|
||||
}
|
||||
// for (int i = startPosition; i <= endPosition; i++) {
|
||||
// pool.add(i);
|
||||
// }
|
||||
|
||||
while (pool.size() >= 2) {
|
||||
int fromPosition = (int) (Math.random() * (pool.size()));
|
||||
int positionA = pool.get(fromPosition);
|
||||
pool.remove(fromPosition);
|
||||
// while (pool.size() >= 2) {
|
||||
// int fromPosition = (int) (Math.random() * (pool.size()));
|
||||
// int positionA = pool.get(fromPosition);
|
||||
// pool.remove(fromPosition);
|
||||
|
||||
int toPosition = (int) (Math.random() * (pool.size()));
|
||||
int positionB = pool.get(toPosition);
|
||||
pool.remove(toPosition);
|
||||
// int toPosition = (int) (Math.random() * (pool.size()));
|
||||
// int positionB = pool.get(toPosition);
|
||||
// pool.remove(toPosition);
|
||||
|
||||
Collections.swap(playerSongQueueAdapter.getItems(), positionA, positionB);
|
||||
bind.playerQueueRecyclerView.getAdapter().notifyItemMoved(positionA, positionB);
|
||||
}
|
||||
// Collections.swap(playerSongQueueAdapter.getItems(), positionA, positionB);
|
||||
// bind.playerQueueRecyclerView.getAdapter().notifyItemMoved(positionA, positionB);
|
||||
// }
|
||||
|
||||
MediaManager.shuffle(mediaBrowserListenableFuture, playerSongQueueAdapter.getItems(), startPosition, endPosition);
|
||||
}
|
||||
});
|
||||
}
|
||||
// MediaManager.shuffle(mediaBrowserListenableFuture, playerSongQueueAdapter.getItems(), startPosition, endPosition);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
private void initCleanButton(MediaBrowser mediaBrowser) {
|
||||
bind.playerCleanQueueButton.setOnClickListener(view -> {
|
||||
int startPosition = mediaBrowser.getCurrentMediaItemIndex() + 1;
|
||||
int endPosition = playerSongQueueAdapter.getItems().size();
|
||||
// private void initCleanButton(MediaBrowser mediaBrowser) {
|
||||
// bind.playerCleanQueueButton.setOnClickListener(view -> {
|
||||
// int startPosition = mediaBrowser.getCurrentMediaItemIndex() + 1;
|
||||
// int endPosition = playerSongQueueAdapter.getItems().size();
|
||||
|
||||
MediaManager.removeRange(mediaBrowserListenableFuture, playerSongQueueAdapter.getItems(), startPosition, endPosition);
|
||||
bind.playerQueueRecyclerView.getAdapter().notifyItemRangeRemoved(startPosition, endPosition);
|
||||
});
|
||||
}
|
||||
// MediaManager.removeRange(mediaBrowserListenableFuture, playerSongQueueAdapter.getItems(), startPosition, endPosition);
|
||||
// bind.playerQueueRecyclerView.getAdapter().notifyItemRangeRemoved(startPosition, endPosition);
|
||||
// });
|
||||
// }
|
||||
|
||||
private void updateNowPlayingItem() {
|
||||
playerSongQueueAdapter.notifyDataSetChanged();
|
||||
|
|
@ -259,4 +291,90 @@ public class PlayerQueueFragment extends Fragment implements ClickCallback {
|
|||
playerSongQueueAdapter.setPlaybackState(id, playing != null && playing);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the visibility and animates all six secondary FABs.
|
||||
*/
|
||||
private void toggleFabMenu() {
|
||||
if (isMenuOpen) {
|
||||
// CLOSE MENU (Reverse order for visual effect)
|
||||
closeFab(fabSaveToPlaylist, 5);
|
||||
closeFab(fabDownloadAll, 4);
|
||||
closeFab(fabSaveQueue, 3);
|
||||
closeFab(fabLoadQueue, 2);
|
||||
closeFab(fabClearQueue, 1);
|
||||
closeFab(fabShuffleQueue, 0);
|
||||
|
||||
fabMenuToggle.animate().rotation(0f).setDuration(ANIMATION_DURATION).start();
|
||||
} else {
|
||||
// OPEN MENU (lowest index at bottom)
|
||||
openFab(fabShuffleQueue, 0);
|
||||
openFab(fabClearQueue, 1);
|
||||
openFab(fabLoadQueue, 2);
|
||||
openFab(fabSaveQueue, 3);
|
||||
openFab(fabDownloadAll, 4);
|
||||
openFab(fabSaveToPlaylist, 5);
|
||||
|
||||
fabMenuToggle.animate().rotation(45f).setDuration(ANIMATION_DURATION).start();
|
||||
}
|
||||
isMenuOpen = !isMenuOpen;
|
||||
}
|
||||
|
||||
private void openFab(View fab, int index) {
|
||||
final float displacement = getResources().getDisplayMetrics().density * (FAB_VERTICAL_SPACING_DP * (index + 1));
|
||||
|
||||
fab.setVisibility(View.VISIBLE);
|
||||
fab.setAlpha(0f);
|
||||
fab.setTranslationY(displacement); // Start at the hidden (closed) position
|
||||
|
||||
fab.animate()
|
||||
.translationY(0f)
|
||||
.alpha(1f)
|
||||
.setDuration(ANIMATION_DURATION)
|
||||
.start();
|
||||
}
|
||||
|
||||
private void closeFab(View fab, int index) {
|
||||
final float displacement = getResources().getDisplayMetrics().density * (FAB_VERTICAL_SPACING_DP * (index + 1));
|
||||
|
||||
fab.animate()
|
||||
.translationY(displacement)
|
||||
.alpha(0f)
|
||||
.setDuration(ANIMATION_DURATION)
|
||||
.withEndAction(() -> fab.setVisibility(View.GONE))
|
||||
.start();
|
||||
}
|
||||
|
||||
private void handleShuffleQueueClick() {
|
||||
Log.d(TAG, "Shuffle Queue Clicked!");
|
||||
toggleFabMenu();
|
||||
// TODO: Insert existing shuffle logic here
|
||||
}
|
||||
|
||||
private void handleClearQueueClick() {
|
||||
Log.d(TAG, "Clear Queue Clicked!");
|
||||
toggleFabMenu();
|
||||
// TODO: Insert existing clear queue logic here
|
||||
}
|
||||
|
||||
private void handleSaveToPlaylistClick() {
|
||||
Log.d(TAG, "Save to Playlist Clicked! (Placeholder)");
|
||||
toggleFabMenu();
|
||||
}
|
||||
|
||||
private void handleDownloadAllClick() {
|
||||
Log.d(TAG, "Download All Clicked! (Placeholder)");
|
||||
toggleFabMenu();
|
||||
}
|
||||
|
||||
private void handleSaveQueueClick() {
|
||||
Log.d(TAG, "Save Queue Clicked! (Placeholder)");
|
||||
toggleFabMenu();
|
||||
}
|
||||
|
||||
private void handleLoadQueueClick() {
|
||||
Log.d(TAG, "Load Queue Clicked! (Placeholder)");
|
||||
toggleFabMenu();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
|
@ -27,14 +29,82 @@
|
|||
|
||||
</com.cappielloantonio.tempo.helper.recyclerview.NestedScrollableHost>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/player_shuffle_queue_fab"
|
||||
<LinearLayout
|
||||
android:id="@+id/fab_menu_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="end"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
android:contentDescription="@string/content_description_shuffle_button"
|
||||
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior"
|
||||
app:srcCompat="@drawable/ic_shuffle" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
app:layout_behavior="com.google.android.material.behavior.HideBottomViewOnScrollBehavior">
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/fab_save_to_playlist"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="Save to Playlist (TODO)"
|
||||
tools:ignore="HardcodedText"
|
||||
app:icon="@android:drawable/ic_menu_edit" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/fab_download_all"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="Download All (TODO)"
|
||||
tools:ignore="HardcodedText"
|
||||
app:icon="@android:drawable/stat_sys_download_done" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/fab_save_queue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="Save Queue (TODO)"
|
||||
tools:ignore="HardcodedText"
|
||||
app:icon="@android:drawable/ic_menu_save" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/fab_load_queue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="Load Queue (TODO)"
|
||||
tools:ignore="HardcodedText"
|
||||
app:icon="@android:drawable/ic_menu_revert" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/fab_clear_queue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="@string/player_queue_clean_all_button"
|
||||
app:icon="@android:drawable/ic_menu_delete" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/fab_shuffle_queue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="gone"
|
||||
android:text="@string/content_description_shuffle_button"
|
||||
app:icon="@drawable/ic_shuffle" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_menu_toggle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="Toggle action menu (TODO: Fix Localization)"
|
||||
tools:ignore="HardcodedText"
|
||||
app:srcCompat="@drawable/ic_add" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
Loading…
Add table
Add a link
Reference in a new issue