mirror of
https://github.com/antebudimir/tempus.git
synced 2026-01-01 09:53:33 +00:00
feat: replace old searchbar implementation with official material3
This commit is contained in:
parent
d7c5be834e
commit
3b80725673
5 changed files with 192 additions and 105 deletions
|
|
@ -2,9 +2,14 @@ package com.cappielloantonio.tempo.ui.fragment;
|
|||
|
||||
import android.content.ComponentName;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
|
@ -28,17 +33,15 @@ import com.cappielloantonio.tempo.ui.adapter.AlbumAdapter;
|
|||
import com.cappielloantonio.tempo.ui.adapter.ArtistAdapter;
|
||||
import com.cappielloantonio.tempo.ui.adapter.SongHorizontalAdapter;
|
||||
import com.cappielloantonio.tempo.util.Constants;
|
||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||
import com.cappielloantonio.tempo.viewmodel.SearchViewModel;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.paulrybitskyi.persistentsearchview.adapters.model.SuggestionItem;
|
||||
import com.paulrybitskyi.persistentsearchview.listeners.OnSuggestionChangeListener;
|
||||
import com.paulrybitskyi.persistentsearchview.utils.SuggestionCreationUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@UnstableApi
|
||||
public class SearchFragment extends Fragment implements ClickCallback {
|
||||
private static final String TAG = "SearchFragment";
|
||||
|
||||
private FragmentSearchBinding bind;
|
||||
private MainActivity activity;
|
||||
private SearchViewModel searchViewModel;
|
||||
|
|
@ -60,6 +63,7 @@ public class SearchFragment extends Fragment implements ClickCallback {
|
|||
|
||||
initSearchResultView();
|
||||
initSearchView();
|
||||
inputFocus();
|
||||
|
||||
return view;
|
||||
}
|
||||
|
|
@ -70,12 +74,6 @@ public class SearchFragment extends Fragment implements ClickCallback {
|
|||
initializeMediaBrowser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
inputFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
releaseMediaBrowser();
|
||||
|
|
@ -118,64 +116,101 @@ public class SearchFragment extends Fragment implements ClickCallback {
|
|||
}
|
||||
|
||||
private void initSearchView() {
|
||||
if (isQueryValid(searchViewModel.getQuery())) {
|
||||
search(searchViewModel.getQuery());
|
||||
}
|
||||
setRecentSuggestions();
|
||||
|
||||
bind.persistentSearchView.setInputQuery(searchViewModel.getQuery());
|
||||
setSuggestions();
|
||||
bind.searchView
|
||||
.getEditText()
|
||||
.setOnEditorActionListener((textView, actionId, keyEvent) -> {
|
||||
|
||||
bind.persistentSearchView.setOnSearchQueryChangeListener((searchView, oldQuery, newQuery) -> {
|
||||
if (!newQuery.trim().equals("") && newQuery.trim().length() > 1) {
|
||||
searchViewModel.getSearchSuggestion(newQuery).observe(getViewLifecycleOwner(), suggestions -> searchView.setSuggestions(SuggestionCreationUtil.asRegularSearchSuggestions(MusicUtil.getReadableStrings(suggestions)), false));
|
||||
} else {
|
||||
setSuggestions();
|
||||
}
|
||||
});
|
||||
String query = bind.searchView.getText().toString();
|
||||
|
||||
bind.persistentSearchView.setOnSuggestionChangeListener(new OnSuggestionChangeListener() {
|
||||
@Override
|
||||
public void onSuggestionPicked(SuggestionItem suggestion) {
|
||||
search(suggestion.getItemModel().getText());
|
||||
}
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
if (isQueryValid(query)) {
|
||||
search(bind.searchView.getText().toString());
|
||||
return true;
|
||||
} else {
|
||||
Toast.makeText(requireContext(), getString(R.string.search_info_minimum_characters), Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuggestionRemoved(SuggestionItem suggestion) {
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
bind.persistentSearchView.setOnSearchConfirmedListener((searchView, query) -> {
|
||||
if (isQueryValid(query)) {
|
||||
searchView.collapse();
|
||||
search(query);
|
||||
} else {
|
||||
Toast.makeText(requireContext(), getString(R.string.search_info_minimum_characters), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
bind.searchView
|
||||
.getEditText()
|
||||
.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
|
||||
|
||||
bind.persistentSearchView.setOnSuggestionChangeListener(new OnSuggestionChangeListener() {
|
||||
@Override
|
||||
public void onSuggestionPicked(SuggestionItem suggestion) {
|
||||
search(suggestion.getItemModel().getText());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuggestionRemoved(SuggestionItem suggestion) {
|
||||
searchViewModel.deleteRecentSearch(suggestion.getItemModel().getText());
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
|
||||
if (count > 1) {
|
||||
setSearchSuggestions(charSequence.toString());
|
||||
} else {
|
||||
setRecentSuggestions();
|
||||
}
|
||||
}
|
||||
|
||||
bind.persistentSearchView.setOnClearInputBtnClickListener(v -> searchViewModel.setQuery(""));
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setSuggestions() {
|
||||
bind.persistentSearchView.setSuggestions(SuggestionCreationUtil.asRecentSearchSuggestions(searchViewModel.getRecentSearchSuggestion()), false);
|
||||
public void setRecentSuggestions() {
|
||||
bind.searchViewSuggestionContainer.removeAllViews();
|
||||
|
||||
for (String suggestion : searchViewModel.getRecentSearchSuggestion()) {
|
||||
View view = LayoutInflater.from(bind.searchViewSuggestionContainer.getContext()).inflate(R.layout.item_search_suggestion, bind.searchViewSuggestionContainer, false);
|
||||
|
||||
ImageView leadingImageView = view.findViewById(R.id.search_suggestion_icon);
|
||||
TextView titleView = view.findViewById(R.id.search_suggestion_title);
|
||||
ImageView tailingImageView = view.findViewById(R.id.search_suggestion_delete_icon);
|
||||
|
||||
leadingImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_history, null));
|
||||
titleView.setText(suggestion);
|
||||
|
||||
view.setOnClickListener(v -> search(suggestion));
|
||||
|
||||
tailingImageView.setOnClickListener(v -> {
|
||||
searchViewModel.deleteRecentSearch(suggestion);
|
||||
setRecentSuggestions();
|
||||
});
|
||||
|
||||
bind.searchViewSuggestionContainer.addView(view);
|
||||
}
|
||||
}
|
||||
|
||||
public void setSearchSuggestions(String query) {
|
||||
searchViewModel.getSearchSuggestion(query).observe(getViewLifecycleOwner(), suggestions -> {
|
||||
bind.searchViewSuggestionContainer.removeAllViews();
|
||||
|
||||
for (String suggestion : suggestions) {
|
||||
View view = LayoutInflater.from(bind.searchViewSuggestionContainer.getContext()).inflate(R.layout.item_search_suggestion, bind.searchViewSuggestionContainer, false);
|
||||
|
||||
ImageView leadingImageView = view.findViewById(R.id.search_suggestion_icon);
|
||||
TextView titleView = view.findViewById(R.id.search_suggestion_title);
|
||||
ImageView tailingImageView = view.findViewById(R.id.search_suggestion_delete_icon);
|
||||
|
||||
leadingImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_search, null));
|
||||
titleView.setText(suggestion);
|
||||
tailingImageView.setVisibility(View.GONE);
|
||||
|
||||
view.setOnClickListener(v -> search(suggestion));
|
||||
|
||||
bind.searchViewSuggestionContainer.addView(view);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void search(String query) {
|
||||
searchViewModel.setQuery(query);
|
||||
|
||||
bind.persistentSearchView.setInputQuery(query);
|
||||
bind.searchBar.setText(query);
|
||||
bind.searchView.hide();
|
||||
performSearch(query);
|
||||
}
|
||||
|
||||
|
|
@ -216,7 +251,7 @@ public class SearchFragment extends Fragment implements ClickCallback {
|
|||
}
|
||||
|
||||
private void inputFocus() {
|
||||
bind.persistentSearchView.expand();
|
||||
bind.searchView.show();
|
||||
}
|
||||
|
||||
private void initializeMediaBrowser() {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z" />
|
||||
</vector>
|
||||
android:fillColor="@color/titleTextColor"
|
||||
android:pathData="M256,760L200,704L424,480L200,256L256,200L480,424L704,200L760,256L536,480L760,704L704,760L480,536L256,760Z"/>
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_history.xml
Normal file
9
app/src/main/res/drawable/ic_history.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:fillColor="@color/titleTextColor"
|
||||
android:pathData="M480,840Q342,840 239.5,748.5Q137,657 122,520L204,520Q218,624 296.5,692Q375,760 480,760Q597,760 678.5,678.5Q760,597 760,480Q760,363 678.5,281.5Q597,200 480,200Q411,200 351,232Q291,264 250,320L360,320L360,400L120,400L120,160L200,160L200,254Q251,190 324.5,155Q398,120 480,120Q555,120 620.5,148.5Q686,177 734.5,225.5Q783,274 811.5,339.5Q840,405 840,480Q840,555 811.5,620.5Q783,686 734.5,734.5Q686,783 620.5,811.5Q555,840 480,840ZM592,648L440,496L440,280L520,280L520,464L648,592L592,648Z"/>
|
||||
</vector>
|
||||
|
|
@ -1,54 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout 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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.paulrybitskyi.persistentsearchview.PersistentSearchView
|
||||
android:id="@+id/persistentSearchView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
app:areSuggestionsDisabled="false"
|
||||
app:cardBackgroundColor="?attr/colorSurface"
|
||||
app:cardCornerRadius="0dp"
|
||||
app:cardElevation="0dp"
|
||||
app:clearInputButtonDrawable="@drawable/ic_close"
|
||||
app:dividerColor="@color/dividerColor"
|
||||
app:isClearInputButtonEnabled="true"
|
||||
app:isDismissableOnTouchOutside="true"
|
||||
app:isProgressBarEnabled="true"
|
||||
app:isVoiceInputButtonEnabled="false"
|
||||
app:leftButtonDrawable="@drawable/ic_search"
|
||||
app:progressBarColor="?attr/colorOnSurface"
|
||||
app:queryInputBarIconColor="@color/searchPlaceholderColor"
|
||||
app:queryInputCursorColor="?attr/colorOnSurface"
|
||||
app:queryInputHint="@string/search_hint"
|
||||
app:queryInputHintColor="@color/searchPlaceholderColor"
|
||||
app:queryInputTextColor="@color/searchPlaceholderColor"
|
||||
app:shouldDimBehind="false"
|
||||
app:suggestionRecentSearchIconColor="@color/searchColor"
|
||||
app:suggestionSearchSuggestionIconColor="@color/searchColor"
|
||||
app:suggestionSelectedTextColor="?attr/colorPrimary"
|
||||
app:suggestionTextColor="@color/searchColor"
|
||||
app:suggestionIconColor="@color/searchColor" />
|
||||
|
||||
<View
|
||||
android:id="@+id/search_bar_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.75dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_below="@+id/persistentSearchView"
|
||||
android:background="?attr/colorSurfaceVariant" />
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/search_result_nested_scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/search_bar_divider">
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/searchbar_scrolling_view_behavior">
|
||||
|
||||
<!-- Search result -->
|
||||
<LinearLayout
|
||||
|
|
@ -56,6 +16,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="64dp"
|
||||
android:paddingBottom="@dimen/global_padding_bottom">
|
||||
|
||||
<!-- Artist -->
|
||||
|
|
@ -150,4 +111,39 @@
|
|||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</RelativeLayout>
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.google.android.material.search.SearchBar
|
||||
android:id="@+id/search_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/search_hint">
|
||||
|
||||
</com.google.android.material.search.SearchBar>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<com.google.android.material.search.SearchView
|
||||
android:id="@+id/search_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:hint="@string/search_hint"
|
||||
app:layout_anchor="@id/search_bar">
|
||||
|
||||
<!-- Content goes here (ScrollView, RecyclerView, etc.). -->
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbars="none"
|
||||
android:paddingBottom="@dimen/global_padding_bottom">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/search_view_suggestion_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"/>
|
||||
</ScrollView>
|
||||
</com.google.android.material.search.SearchView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
48
app/src/main/res/layout/item_search_suggestion.xml
Normal file
48
app/src/main/res/layout/item_search_suggestion.xml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_suggestion_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_history"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/search_suggestion_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:text="@string/label_placeholder"
|
||||
android:textAppearance="?attr/textAppearanceBody2"
|
||||
app:layout_constraintBottom_toBottomOf="@id/search_suggestion_icon"
|
||||
app:layout_constraintEnd_toStartOf="@id/search_suggestion_delete_icon"
|
||||
app:layout_constraintStart_toEndOf="@id/search_suggestion_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/search_suggestion_icon" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_suggestion_delete_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_close"
|
||||
app:layout_constraintBottom_toBottomOf="@id/search_suggestion_icon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/search_suggestion_title"
|
||||
app:layout_constraintTop_toTopOf="@id/search_suggestion_icon"
|
||||
tools:ignore="ContentDescription" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
Loading…
Add table
Add a link
Reference in a new issue