diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/AlbumCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/AlbumCatalogueAdapter.java index 16169d1d..6dca9793 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/AlbumCatalogueAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/AlbumCatalogueAdapter.java @@ -5,6 +5,9 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.Filter; +import android.widget.Filterable; import android.widget.ImageView; import android.widget.TextView; @@ -14,19 +17,23 @@ import androidx.recyclerview.widget.RecyclerView; import com.cappielloantonio.play.R; import com.cappielloantonio.play.glide.CustomGlideRequest; import com.cappielloantonio.play.model.Album; +import com.cappielloantonio.play.ui.activities.MainActivity; import java.util.ArrayList; import java.util.List; import java.util.Objects; -public class AlbumCatalogueAdapter extends RecyclerView.Adapter { +public class AlbumCatalogueAdapter extends RecyclerView.Adapter implements Filterable { private static final String TAG = "AlbumCatalogueAdapter"; private List albums; + private List albumsFull; private LayoutInflater inflater; + private MainActivity activity; private Context context; - public AlbumCatalogueAdapter(Context context) { + public AlbumCatalogueAdapter(MainActivity activity, Context context) { + this.activity = activity; this.context = context; this.inflater = LayoutInflater.from(context); this.albums = new ArrayList<>(); @@ -87,6 +94,9 @@ public class AlbumCatalogueAdapter extends RecyclerView.Adapter albums) { this.albums = albums; + this.albumsFull = new ArrayList<>(albums); notifyDataSetChanged(); } + + @Override + public Filter getFilter() { + return filtering; + } + + private Filter filtering = new Filter() { + @Override + protected FilterResults performFiltering(CharSequence constraint) { + List filteredList = new ArrayList<>(); + + if (constraint == null || constraint.length() == 0) { + filteredList.addAll(albumsFull); + } else { + String filterPattern = constraint.toString().toLowerCase().trim(); + + for (Album item : albumsFull) { + 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) { + albums.clear(); + albums.addAll((List) results.values); + notifyDataSetChanged(); + } + }; } diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/ArtistCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/ArtistCatalogueAdapter.java index 5622b527..27092fad 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/ArtistCatalogueAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/ArtistCatalogueAdapter.java @@ -5,6 +5,9 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.Filter; +import android.widget.Filterable; import android.widget.ImageView; import android.widget.TextView; @@ -13,20 +16,25 @@ import androidx.recyclerview.widget.RecyclerView; import com.cappielloantonio.play.R; import com.cappielloantonio.play.glide.CustomGlideRequest; +import com.cappielloantonio.play.model.Album; import com.cappielloantonio.play.model.Artist; +import com.cappielloantonio.play.ui.activities.MainActivity; import java.util.ArrayList; import java.util.List; import java.util.Objects; -public class ArtistCatalogueAdapter extends RecyclerView.Adapter { +public class ArtistCatalogueAdapter extends RecyclerView.Adapter implements Filterable { private static final String TAG = "ArtistCatalogueAdapter"; private List artists; + private List artistFull; private LayoutInflater inflater; + private MainActivity activity; private Context context; - public ArtistCatalogueAdapter(Context context) { + public ArtistCatalogueAdapter(MainActivity activity, Context context) { + this.activity = activity; this.context = context; this.inflater = LayoutInflater.from(context); this.artists = new ArrayList<>(); @@ -83,6 +91,9 @@ public class ArtistCatalogueAdapter extends RecyclerView.Adapter artists) { this.artists = artists; + this.artistFull = new ArrayList<>(artists); notifyDataSetChanged(); } + + @Override + public Filter getFilter() { + return filtering; + } + + private Filter filtering = new Filter() { + @Override + protected FilterResults performFiltering(CharSequence constraint) { + List filteredList = new ArrayList<>(); + + if (constraint == null || constraint.length() == 0) { + filteredList.addAll(artistFull); + } else { + String filterPattern = constraint.toString().toLowerCase().trim(); + + for (Artist item : artistFull) { + if (item.getName().toLowerCase().contains(filterPattern)) { + filteredList.add(item); + } + } + } + + FilterResults results = new FilterResults(); + results.values = filteredList; + + return results; + } + + @Override + protected void publishResults(CharSequence constraint, FilterResults results) { + artists.clear(); + artists.addAll((List) results.values); + notifyDataSetChanged(); + } + }; } diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/GenreCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/GenreCatalogueAdapter.java index 395fe1dd..21796a3e 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/GenreCatalogueAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/GenreCatalogueAdapter.java @@ -4,25 +4,33 @@ import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.Filter; +import android.widget.Filterable; import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import com.cappielloantonio.play.R; +import com.cappielloantonio.play.model.Album; import com.cappielloantonio.play.model.Genre; +import com.cappielloantonio.play.ui.activities.MainActivity; import java.util.ArrayList; import java.util.List; -public class GenreCatalogueAdapter extends RecyclerView.Adapter { +public class GenreCatalogueAdapter extends RecyclerView.Adapter implements Filterable { private static final String TAG = "GenreCatalogueAdapter"; private List genres; + private List genresFull; private LayoutInflater mInflater; + private MainActivity activity; private Context context; private ItemClickListener itemClickListener; - public GenreCatalogueAdapter(Context context) { + public GenreCatalogueAdapter(MainActivity activity, Context context) { + this.activity = activity; this.context = context; this.mInflater = LayoutInflater.from(context); this.genres = new ArrayList<>(); @@ -60,7 +68,12 @@ public class GenreCatalogueAdapter extends RecyclerView.Adapter genres) { this.genres = genres; + this.genresFull = new ArrayList<>(genres); notifyDataSetChanged(); } @@ -80,4 +94,40 @@ public class GenreCatalogueAdapter extends RecyclerView.Adapter filteredList = new ArrayList<>(); + + if (constraint == null || constraint.length() == 0) { + filteredList.addAll(genresFull); + } else { + String filterPattern = constraint.toString().toLowerCase().trim(); + + for (Genre item : genresFull) { + if (item.getName().toLowerCase().contains(filterPattern)) { + filteredList.add(item); + } + } + } + + FilterResults results = new FilterResults(); + results.values = filteredList; + + return results; + } + + @Override + protected void publishResults(CharSequence constraint, FilterResults results) { + genres.clear(); + genres.addAll((List) results.values); + notifyDataSetChanged(); + } + }; } diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistCatalogueAdapter.java index 274c1611..cfb47202 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistCatalogueAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistCatalogueAdapter.java @@ -5,6 +5,9 @@ import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.Filter; +import android.widget.Filterable; import android.widget.ImageView; import android.widget.TextView; @@ -13,19 +16,24 @@ import androidx.recyclerview.widget.RecyclerView; import com.cappielloantonio.play.R; import com.cappielloantonio.play.glide.CustomGlideRequest; +import com.cappielloantonio.play.model.Album; import com.cappielloantonio.play.model.Genre; import com.cappielloantonio.play.model.Playlist; +import com.cappielloantonio.play.ui.activities.MainActivity; import java.util.ArrayList; import java.util.List; -public class PlaylistCatalogueAdapter extends RecyclerView.Adapter { +public class PlaylistCatalogueAdapter extends RecyclerView.Adapter implements Filterable { private List playlists; + private List playlistsFull; private LayoutInflater mInflater; + private MainActivity activity; private Context context; - public PlaylistCatalogueAdapter(Context context) { + public PlaylistCatalogueAdapter(MainActivity activity, Context context) { + this.activity = activity; this.context = context; this.mInflater = LayoutInflater.from(context); this.playlists = new ArrayList<>(); @@ -73,6 +81,8 @@ public class PlaylistCatalogueAdapter extends RecyclerView.Adapter playlists) { this.playlists = playlists; + this.playlistsFull = new ArrayList<>(playlists); notifyDataSetChanged(); } + + @Override + public Filter getFilter() { + return filtering; + } + + private Filter filtering = new Filter() { + @Override + protected FilterResults performFiltering(CharSequence constraint) { + List filteredList = new ArrayList<>(); + + if (constraint == null || constraint.length() == 0) { + filteredList.addAll(playlistsFull); + } else { + String filterPattern = constraint.toString().toLowerCase().trim(); + + for (Playlist item : playlistsFull) { + if (item.getName().toLowerCase().contains(filterPattern)) { + filteredList.add(item); + } + } + } + + FilterResults results = new FilterResults(); + results.values = filteredList; + + return results; + } + + @Override + protected void publishResults(CharSequence constraint, FilterResults results) { + playlists.clear(); + playlists.addAll((List) results.values); + notifyDataSetChanged(); + } + }; } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumCatalogueFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumCatalogueFragment.java index 176295c2..e837f618 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumCatalogueFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/AlbumCatalogueFragment.java @@ -1,21 +1,44 @@ package com.cappielloantonio.play.ui.fragment; +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.BlendMode; +import android.graphics.BlendModeColorFilter; +import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.LinearLayout; +import android.widget.SearchView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.cappielloantonio.play.App; +import com.cappielloantonio.play.R; import com.cappielloantonio.play.adapter.AlbumCatalogueAdapter; import com.cappielloantonio.play.databinding.FragmentAlbumCatalogueBinding; +import com.cappielloantonio.play.helper.MusicPlayerRemote; import com.cappielloantonio.play.helper.recyclerview.GridItemDecoration; +import com.cappielloantonio.play.repository.QueueRepository; import com.cappielloantonio.play.ui.activities.MainActivity; import com.cappielloantonio.play.viewmodel.AlbumCatalogueViewModel; +import java.util.Collections; + public class AlbumCatalogueFragment extends Fragment { private static final String TAG = "ArtistCatalogueFragment"; @@ -25,6 +48,12 @@ public class AlbumCatalogueFragment extends Fragment { private AlbumCatalogueAdapter albumAdapter; + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { activity = (MainActivity) getActivity(); @@ -33,6 +62,7 @@ public class AlbumCatalogueFragment extends Fragment { View view = bind.getRoot(); albumCatalogueViewModel = new ViewModelProvider(requireActivity()).get(AlbumCatalogueViewModel.class); + initAppBar(); initAlbumCatalogueView(); return view; @@ -50,17 +80,75 @@ public class AlbumCatalogueFragment extends Fragment { bind = null; } + private void initAppBar() { + activity.setSupportActionBar(bind.toolbar); + + if (activity.getSupportActionBar() != null) { + activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + activity.getSupportActionBar().setDisplayShowHomeEnabled(true); + } + + bind.toolbar.setNavigationOnClickListener(v -> { + hideKeyboard(v); + activity.navController.navigateUp(); + }); + + + bind.appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> { + if ((bind.albumInfoSector.getHeight() + verticalOffset) < (2 * ViewCompat.getMinimumHeight(bind.toolbar))) { + bind.toolbar.setTitle("Album Catalogue"); + } else { + bind.toolbar.setTitle(""); + } + }); + } + + @SuppressLint("ClickableViewAccessibility") private void initAlbumCatalogueView() { bind.albumCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2)); bind.albumCatalogueRecyclerView.addItemDecoration(new GridItemDecoration(2, 20, false)); bind.albumCatalogueRecyclerView.setHasFixedSize(true); - albumAdapter = new AlbumCatalogueAdapter(requireContext()); + albumAdapter = new AlbumCatalogueAdapter(activity, requireContext()); albumAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY); bind.albumCatalogueRecyclerView.setAdapter(albumAdapter); albumCatalogueViewModel.getAlbumList().observe(requireActivity(), albums -> { - bind.loadingProgressBar.setVisibility(View.GONE); albumAdapter.setItems(albums); }); + + bind.albumCatalogueRecyclerView.setOnTouchListener((v, event) -> { + hideKeyboard(v); + return false; + }); + } + + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + inflater.inflate(R.menu.album_catalogue_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) { + albumAdapter.getFilter().filter(newText); + return false; + } + }); + + searchView.setPadding(-32, 0, 0, 0); + } + + private void hideKeyboard(View view) { + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistCatalogueFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistCatalogueFragment.java index 66ec1fb9..3a60ca35 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistCatalogueFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/ArtistCatalogueFragment.java @@ -1,16 +1,28 @@ package com.cappielloantonio.play.ui.fragment; +import android.annotation.SuppressLint; +import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; +import android.view.Menu; +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; +import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.cappielloantonio.play.R; import com.cappielloantonio.play.adapter.ArtistCatalogueAdapter; import com.cappielloantonio.play.databinding.FragmentArtistCatalogueBinding; import com.cappielloantonio.play.helper.recyclerview.GridItemDecoration; @@ -26,6 +38,12 @@ public class ArtistCatalogueFragment extends Fragment { private ArtistCatalogueAdapter artistAdapter; + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { activity = (MainActivity) getActivity(); @@ -34,6 +52,7 @@ public class ArtistCatalogueFragment extends Fragment { View view = bind.getRoot(); artistCatalogueViewModel = new ViewModelProvider(requireActivity()).get(ArtistCatalogueViewModel.class); + initAppBar(); initArtistCatalogueView(); return view; @@ -51,17 +70,75 @@ public class ArtistCatalogueFragment extends Fragment { bind = null; } + private void initAppBar() { + activity.setSupportActionBar(bind.toolbar); + + if (activity.getSupportActionBar() != null) { + activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + activity.getSupportActionBar().setDisplayShowHomeEnabled(true); + } + + bind.toolbar.setNavigationOnClickListener(v -> { + hideKeyboard(v); + activity.navController.navigateUp(); + }); + + + bind.appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> { + if ((bind.artistInfoSector.getHeight() + verticalOffset) < (2 * ViewCompat.getMinimumHeight(bind.toolbar))) { + bind.toolbar.setTitle("Artist Catalogue"); + } else { + bind.toolbar.setTitle(""); + } + }); + } + + @SuppressLint("ClickableViewAccessibility") private void initArtistCatalogueView() { bind.artistCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2)); bind.artistCatalogueRecyclerView.addItemDecoration(new GridItemDecoration(2, 20, false)); bind.artistCatalogueRecyclerView.setHasFixedSize(true); - artistAdapter = new ArtistCatalogueAdapter(requireContext()); + artistAdapter = new ArtistCatalogueAdapter(activity, requireContext()); artistAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY); bind.artistCatalogueRecyclerView.setAdapter(artistAdapter); artistCatalogueViewModel.getArtistList().observe(requireActivity(), artistList -> { - bind.loadingProgressBar.setVisibility(View.GONE); artistAdapter.setItems(artistList); }); + + bind.artistCatalogueRecyclerView.setOnTouchListener((v, event) -> { + hideKeyboard(v); + return false; + }); + } + + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + inflater.inflate(R.menu.album_catalogue_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) { + artistAdapter.getFilter().filter(newText); + return false; + } + }); + + searchView.setPadding(-32, 0, 0, 0); + } + + private void hideKeyboard(View view) { + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/FilterFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/FilterFragment.java index 8e13f028..76208bcf 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/FilterFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/FilterFragment.java @@ -8,6 +8,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; @@ -36,6 +37,7 @@ public class FilterFragment extends Fragment { filterViewModel = new ViewModelProvider(requireActivity()).get(FilterViewModel.class); init(); + initAppBar(); setFilterChips(); return view; } @@ -63,6 +65,28 @@ public class FilterFragment extends Fragment { }); } + private void initAppBar() { + activity.setSupportActionBar(bind.toolbar); + + if (activity.getSupportActionBar() != null) { + activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + activity.getSupportActionBar().setDisplayShowHomeEnabled(true); + } + + bind.toolbar.setNavigationOnClickListener(v -> { + activity.navController.navigateUp(); + }); + + + bind.appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> { + if ((bind.genreFilterInfoSector.getHeight() + verticalOffset) < (2 * ViewCompat.getMinimumHeight(bind.toolbar))) { + bind.toolbar.setTitle("Filter"); + } else { + bind.toolbar.setTitle(""); + } + }); + } + private void setFilterChips() { filterViewModel.getGenreList().observe(requireActivity(), genres -> { bind.loadingProgressBar.setVisibility(View.GONE); diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/GenreCatalogueFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/GenreCatalogueFragment.java index 46a51ba4..bd303caa 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/GenreCatalogueFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/GenreCatalogueFragment.java @@ -1,13 +1,25 @@ package com.cappielloantonio.play.ui.fragment; +import android.annotation.SuppressLint; +import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; +import android.view.Menu; +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; +import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import com.cappielloantonio.play.R; import com.cappielloantonio.play.adapter.GenreCatalogueAdapter; @@ -26,6 +38,12 @@ public class GenreCatalogueFragment extends Fragment { private GenreCatalogueAdapter genreCatalogueAdapter; + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { activity = (MainActivity) getActivity(); @@ -35,6 +53,7 @@ public class GenreCatalogueFragment extends Fragment { genreCatalogueViewModel = new ViewModelProvider(requireActivity()).get(GenreCatalogueViewModel.class); init(); + initAppBar(); initArtistCatalogueView(); return view; @@ -56,24 +75,82 @@ public class GenreCatalogueFragment extends Fragment { bind.filterGenresTextViewClickable.setOnClickListener(v -> activity.navController.navigate(R.id.action_genreCatalogueFragment_to_filterFragment)); } + private void initAppBar() { + activity.setSupportActionBar(bind.toolbar); + + if (activity.getSupportActionBar() != null) { + activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + activity.getSupportActionBar().setDisplayShowHomeEnabled(true); + } + + bind.toolbar.setNavigationOnClickListener(v -> { + hideKeyboard(v); + activity.navController.navigateUp(); + }); + + + bind.appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> { + if ((bind.genreInfoSector.getHeight() + verticalOffset) < (2 * ViewCompat.getMinimumHeight(bind.toolbar))) { + bind.toolbar.setTitle("Genre Catalogue"); + } else { + bind.toolbar.setTitle(""); + } + }); + } + + @SuppressLint("ClickableViewAccessibility") private void initArtistCatalogueView() { bind.genreCatalogueRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), 2)); bind.genreCatalogueRecyclerView.addItemDecoration(new GridItemDecoration(2, 16, false)); bind.genreCatalogueRecyclerView.setHasFixedSize(true); - genreCatalogueAdapter = new GenreCatalogueAdapter(requireContext()); + genreCatalogueAdapter = new GenreCatalogueAdapter(activity, requireContext()); + genreCatalogueAdapter.setStateRestorationPolicy(RecyclerView.Adapter.StateRestorationPolicy.PREVENT_WHEN_EMPTY); + bind.genreCatalogueRecyclerView.setAdapter(genreCatalogueAdapter); genreCatalogueAdapter.setClickListener((view, position) -> { Bundle bundle = new Bundle(); bundle.putString(Song.BY_GENRE, Song.BY_GENRE); bundle.putParcelable("genre_object", genreCatalogueAdapter.getItem(position)); activity.navController.navigate(R.id.action_genreCatalogueFragment_to_songListPageFragment, bundle); }); - bind.genreCatalogueRecyclerView.setAdapter(genreCatalogueAdapter); genreCatalogueViewModel.getGenreList().observe(requireActivity(), genres -> { - bind.loadingProgressBar.setVisibility(View.GONE); - bind.genreCatalogueContainer.setVisibility(View.VISIBLE); genreCatalogueAdapter.setItems(genres); }); + + bind.genreCatalogueRecyclerView.setOnTouchListener((v, event) -> { + hideKeyboard(v); + return false; + }); + } + + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + inflater.inflate(R.menu.album_catalogue_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) { + genreCatalogueAdapter.getFilter().filter(newText); + return false; + } + }); + + searchView.setPadding(-32, 0, 0, 0); + } + + private void hideKeyboard(View view) { + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java index fcb8c052..b926da5c 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java @@ -1,10 +1,21 @@ package com.cappielloantonio.play.ui.fragment; +import android.annotation.SuppressLint; +import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; +import android.view.Menu; +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; +import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.GridLayoutManager; @@ -33,6 +44,12 @@ public class PlaylistCatalogueFragment extends Fragment { private PlaylistCatalogueAdapter playlistCatalogueAdapter; + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { activity = (MainActivity) getActivity(); @@ -41,6 +58,7 @@ public class PlaylistCatalogueFragment extends Fragment { View view = bind.getRoot(); playlistCatalogueViewModel = new ViewModelProvider(requireActivity()).get(PlaylistCatalogueViewModel.class); + initAppBar(); initArtistCatalogueView(); return view; @@ -58,14 +76,73 @@ public class PlaylistCatalogueFragment extends Fragment { bind = null; } + private void initAppBar() { + activity.setSupportActionBar(bind.toolbar); + + if (activity.getSupportActionBar() != null) { + activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + activity.getSupportActionBar().setDisplayShowHomeEnabled(true); + } + + bind.toolbar.setNavigationOnClickListener(v -> { + hideKeyboard(v); + activity.navController.navigateUp(); + }); + + + bind.appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> { + if ((bind.albumInfoSector.getHeight() + verticalOffset) < (2 * ViewCompat.getMinimumHeight(bind.toolbar))) { + bind.toolbar.setTitle("Playlist Catalogue"); + } else { + bind.toolbar.setTitle(""); + } + }); + } + + @SuppressLint("ClickableViewAccessibility") private void initArtistCatalogueView() { bind.playlistCatalogueRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); bind.playlistCatalogueRecyclerView.setHasFixedSize(true); - playlistCatalogueAdapter = new PlaylistCatalogueAdapter(requireContext()); + playlistCatalogueAdapter = new PlaylistCatalogueAdapter(activity, requireContext()); bind.playlistCatalogueRecyclerView.setAdapter(playlistCatalogueAdapter); playlistCatalogueViewModel.getPlaylistList().observe(requireActivity(), playlist -> { playlistCatalogueAdapter.setItems(playlist); }); + + bind.playlistCatalogueRecyclerView.setOnTouchListener((v, event) -> { + hideKeyboard(v); + return false; + }); + } + + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + inflater.inflate(R.menu.album_catalogue_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) { + playlistCatalogueAdapter.getFilter().filter(newText); + return false; + } + }); + + searchView.setPadding(-32, 0, 0, 0); + } + + private void hideKeyboard(View view) { + InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } } \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java index e944214f..aeae1ace 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SearchFragment.java @@ -103,7 +103,7 @@ public class SearchFragment extends Fragment { bind.searchResultGenreRecyclerView.addItemDecoration(new GridItemDecoration(2, 16, false)); bind.searchResultGenreRecyclerView.setHasFixedSize(true); - genreCatalogueAdapter = new GenreCatalogueAdapter(requireContext()); + genreCatalogueAdapter = new GenreCatalogueAdapter(activity, requireContext()); genreCatalogueAdapter.setClickListener((view, position) -> { Bundle bundle = new Bundle(); bundle.putString(Song.BY_GENRE, Song.BY_GENRE); diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SongListPageFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SongListPageFragment.java index 77e5ddbf..23c9e291 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/SongListPageFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/SongListPageFragment.java @@ -5,6 +5,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; @@ -32,6 +33,7 @@ public class SongListPageFragment extends Fragment { songListPageViewModel = new ViewModelProvider(requireActivity()).get(SongListPageViewModel.class); init(); + initAppBar(); initSongListView(); return view; @@ -94,6 +96,27 @@ public class SongListPageFragment extends Fragment { } } + private void initAppBar() { + activity.setSupportActionBar(bind.toolbar); + + if (activity.getSupportActionBar() != null) { + activity.getSupportActionBar().setDisplayHomeAsUpEnabled(true); + activity.getSupportActionBar().setDisplayShowHomeEnabled(true); + } + + bind.toolbar.setNavigationOnClickListener(v -> { + activity.navController.navigateUp(); + }); + + bind.appBarLayout.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> { + if ((bind.albumInfoSector.getHeight() + verticalOffset) < (2 * ViewCompat.getMinimumHeight(bind.toolbar))) { + bind.toolbar.setTitle("Songs"); + } else { + bind.toolbar.setTitle(""); + } + }); + } + private void initSongListView() { bind.songListRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); bind.songListRecyclerView.setHasFixedSize(true); diff --git a/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumCatalogueViewModel.java b/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumCatalogueViewModel.java index 862d9db0..2ed61dac 100644 --- a/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumCatalogueViewModel.java +++ b/app/src/main/java/com/cappielloantonio/play/viewmodel/AlbumCatalogueViewModel.java @@ -15,6 +15,8 @@ public class AlbumCatalogueViewModel extends AndroidViewModel { private AlbumRepository albumRepository; public LiveData> albumList; + private String query = ""; + public AlbumCatalogueViewModel(@NonNull Application application) { super(application); @@ -25,4 +27,12 @@ public class AlbumCatalogueViewModel extends AndroidViewModel { albumList = albumRepository.getListLiveAlbums(); return albumList; } + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } } diff --git a/app/src/main/res/drawable/ic_done.xml b/app/src/main/res/drawable/ic_done.xml new file mode 100644 index 00000000..122a7ac6 --- /dev/null +++ b/app/src/main/res/drawable/ic_done.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_filter_list.xml b/app/src/main/res/drawable/ic_filter_list.xml new file mode 100644 index 00000000..6ff78015 --- /dev/null +++ b/app/src/main/res/drawable/ic_filter_list.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/fragment_album_catalogue.xml b/app/src/main/res/layout/fragment_album_catalogue.xml index 73f28d38..8835f55c 100644 --- a/app/src/main/res/layout/fragment_album_catalogue.xml +++ b/app/src/main/res/layout/fragment_album_catalogue.xml @@ -1,42 +1,60 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> - - - + android:layout_height="?attr/actionBarSize" + app:layout_collapseMode="pin" + app:navigationIcon="@drawable/ic_arrow_back" + android:theme="@style/SearchViewStyle" /> - - + android:layout_height="match_parent" + android:paddingTop="8dp"> + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_album_page.xml b/app/src/main/res/layout/fragment_album_page.xml index dc27100e..c8c29b7b 100644 --- a/app/src/main/res/layout/fragment_album_page.xml +++ b/app/src/main/res/layout/fragment_album_page.xml @@ -165,7 +165,7 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> - - - + android:layout_height="?attr/actionBarSize" + app:layout_collapseMode="pin" + app:navigationIcon="@drawable/ic_arrow_back" + app:titleTextColor="@color/titleTextColor" + app:queryBackground="@android:color/transparent" + android:theme="@style/SearchViewStyle" /> - - + android:layout_height="match_parent" + android:paddingTop="8dp"> + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_filter.xml b/app/src/main/res/layout/fragment_filter.xml index ccf60c7e..f0576cf4 100644 --- a/app/src/main/res/layout/fragment_filter.xml +++ b/app/src/main/res/layout/fragment_filter.xml @@ -1,75 +1,91 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> - + - + android:paddingTop="8dp"> - + app:elevation="0dp"> - + android:layout_height="172dp" + android:clipChildren="false" + app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> - - - - + style="@style/HeadlineTextView" + android:text="Filter Genres" + android:paddingTop="16dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingBottom="24dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintBottom_toBottomOf="parent"/> + + + + + + + + - - - + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:paddingBottom="@dimen/global_padding_bottom"/> + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_genre_catalogue.xml b/app/src/main/res/layout/fragment_genre_catalogue.xml index 57b53ca0..1c51ed0a 100644 --- a/app/src/main/res/layout/fragment_genre_catalogue.xml +++ b/app/src/main/res/layout/fragment_genre_catalogue.xml @@ -1,66 +1,73 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> - - - - + android:layout_height="?attr/actionBarSize" + app:layout_collapseMode="pin" + app:navigationIcon="@drawable/ic_arrow_back" + android:theme="@style/SearchViewStyle" /> - - - - - - - - + android:layout_height="match_parent" + android:paddingTop="8dp"> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_playlist_catalogue.xml b/app/src/main/res/layout/fragment_playlist_catalogue.xml index 2ee599fc..4abc0d1a 100644 --- a/app/src/main/res/layout/fragment_playlist_catalogue.xml +++ b/app/src/main/res/layout/fragment_playlist_catalogue.xml @@ -1,32 +1,60 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> - - + android:layout_height="?attr/actionBarSize" + app:layout_collapseMode="pin" + app:navigationIcon="@drawable/ic_arrow_back" + android:theme="@style/SearchViewStyle" /> - - + android:layout_height="match_parent" + android:paddingTop="8dp"> + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_song_list_page.xml b/app/src/main/res/layout/fragment_song_list_page.xml index 8e87ad9c..1901bd08 100644 --- a/app/src/main/res/layout/fragment_song_list_page.xml +++ b/app/src/main/res/layout/fragment_song_list_page.xml @@ -1,30 +1,61 @@ - + android:layout_height="?attr/actionBarSize" + app:layout_collapseMode="pin" + app:navigationIcon="@drawable/ic_arrow_back" + android:theme="@style/SearchViewStyle" /> - + android:paddingTop="8dp"> + + + + + + + + + + + + diff --git a/app/src/main/res/menu/album_catalogue_menu.xml b/app/src/main/res/menu/album_catalogue_menu.xml new file mode 100644 index 00000000..8e16b210 --- /dev/null +++ b/app/src/main/res/menu/album_catalogue_menu.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 081cbe3d..e85682dd 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -29,6 +29,17 @@ @color/dividerColor + +