feat: add search functionality for songs within playlists

This commit is contained in:
CappielloAntonio 2024-11-20 22:20:37 +01:00
parent 4ec1519063
commit 0f471a7b9f
4 changed files with 86 additions and 5 deletions

View file

@ -4,6 +4,8 @@ import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import androidx.annotation.NonNull;
import androidx.appcompat.content.res.AppCompatResources;
@ -29,19 +31,54 @@ import java.util.Objects;
import java.util.Optional;
@UnstableApi
public class SongHorizontalAdapter extends RecyclerView.Adapter<SongHorizontalAdapter.ViewHolder> {
public class SongHorizontalAdapter extends RecyclerView.Adapter<SongHorizontalAdapter.ViewHolder> implements Filterable {
private final ClickCallback click;
private final boolean showCoverArt;
private final boolean showAlbum;
private final AlbumID3 album;
private List<Child> songsFull;
private List<Child> songs;
private String currentFilter;
private final Filter filtering = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
List<Child> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(songsFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
currentFilter = filterPattern;
for (Child item : songsFull) {
if (item.getTitle().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
songs = (List<Child>) results.values;
notifyDataSetChanged();
}
};
public SongHorizontalAdapter(ClickCallback click, boolean showCoverArt, boolean showAlbum, AlbumID3 album) {
this.click = click;
this.showCoverArt = showCoverArt;
this.showAlbum = showAlbum;
this.songs = Collections.emptyList();
this.songsFull = Collections.emptyList();
this.currentFilter = "";
this.album = album;
}
@ -135,7 +172,8 @@ public class SongHorizontalAdapter extends RecyclerView.Adapter<SongHorizontalAd
}
public void setItems(List<Child> songs) {
this.songs = songs != null ? songs : Collections.emptyList();
this.songsFull = songs != null ? songs : Collections.emptyList();
filtering.filter(currentFilter);
notifyDataSetChanged();
}
@ -149,6 +187,11 @@ public class SongHorizontalAdapter extends RecyclerView.Adapter<SongHorizontalAd
return position;
}
@Override
public Filter getFilter() {
return filtering;
}
public Child getItem(int id) {
return songs.get(id);
}

View file

@ -1,6 +1,7 @@
package com.cappielloantonio.tempo.ui.fragment;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
@ -8,6 +9,9 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.SearchView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -58,8 +62,28 @@ public class PlaylistPageFragment extends Fragment implements ClickCallback {
@Override
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.playlist_page_menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
searchView.clearFocus();
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
songHorizontalAdapter.getFilter().filter(newText);
return false;
}
});
searchView.setPadding(-32, 0, 0, 0);
initMenuOption(menu);
}
@ -152,11 +176,19 @@ public class PlaylistPageFragment extends Fragment implements ClickCallback {
bind.playlistSongCountLabel.setText(getString(R.string.playlist_song_count, playlistPageViewModel.getPlaylist().getSongCount()));
bind.playlistDurationLabel.setText(getString(R.string.playlist_duration, MusicUtil.getReadableDurationString(playlistPageViewModel.getPlaylist().getDuration(), false)));
bind.animToolbar.setNavigationOnClickListener(v -> activity.navController.navigateUp());
bind.animToolbar.setNavigationOnClickListener(v -> {
hideKeyboard(v);
activity.navController.navigateUp();
});
Objects.requireNonNull(bind.animToolbar.getOverflowIcon()).setTint(requireContext().getResources().getColor(R.color.titleTextColor, null));
}
private void hideKeyboard(View view) {
InputMethodManager imm = (InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
private void initMusicButton() {
playlistPageViewModel.getPlaylistSongLiveList().observe(getViewLifecycleOwner(), songs -> {
if (bind != null) {

View file

@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_search"
android:icon="@drawable/ic_search"
android:title="@string/menu_search_button"
app:actionViewClass="android.widget.SearchView"
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_download_playlist"
android:icon="@drawable/ic_file_download"

View file

@ -8,5 +8,4 @@
android:title="@string/menu_search_button"
app:actionViewClass="android.widget.SearchView"
app:showAsAction="ifRoom" />
</menu>