From 85c9d83ae56773f2c35d4bfddf77ecc91007f680 Mon Sep 17 00:00:00 2001 From: NekoInverter <42698724+NekoInverter@users.noreply.github.com> Date: Wed, 11 Nov 2020 20:14:13 +0800 Subject: [PATCH] Use recyclerview for search suggestion --- .../ehviewer/ui/scene/GalleryListScene.java | 25 ++-- .../com/hippo/ehviewer/widget/SearchBar.java | 137 ++++++++++-------- .../java/com/hippo/scene/StageActivity.java | 4 +- .../res/anim/scene_open_exit_horizontal.xml | 28 ---- .../main/res/layout/item_simple_list_2.xml | 3 +- app/src/main/res/layout/scene_favorites.xml | 5 +- .../main/res/layout/scene_gallery_list.xml | 5 +- app/src/main/res/layout/widget_search_bar.xml | 30 ++-- app/src/main/res/values-night-v29/colors.xml | 3 + app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 11 files changed, 120 insertions(+), 122 deletions(-) delete mode 100644 app/src/main/res/anim/scene_open_exit_horizontal.xml create mode 100644 app/src/main/res/values-night-v29/colors.xml diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java index 4f077cd38..6c618cbae 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java @@ -1721,16 +1721,20 @@ public final class GalleryListScene extends BaseScene private abstract class UrlSuggestion extends SearchBar.Suggestion { @Override - public CharSequence getText(float textSize) { - Drawable bookImage = DrawableManager.getVectorDrawable(getContext2(), R.drawable.v_book_open_x24); - SpannableStringBuilder ssb = new SpannableStringBuilder(" "); - ssb.append(getResources2().getString(R.string.gallery_list_search_bar_open_gallery)); - int imageSize = (int) (textSize * 1.25); - if (bookImage != null) { - bookImage.setBounds(0, 0, imageSize, imageSize); - ssb.setSpan(new ImageSpan(bookImage), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + public CharSequence getText(TextView textView) { + if (textView.getId() == android.R.id.text1) { + Drawable bookImage = DrawableManager.getVectorDrawable(textView.getContext(), R.drawable.v_book_open_x24); + SpannableStringBuilder ssb = new SpannableStringBuilder(" "); + ssb.append(getString(R.string.gallery_list_search_bar_open_gallery)); + int imageSize = (int) (textView.getTextSize() * 1.25); + if (bookImage != null) { + bookImage.setBounds(0, 0, imageSize, imageSize); + ssb.setSpan(new ImageSpan(bookImage), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return ssb; + } else { + return null; } - return ssb; } @Override @@ -1746,9 +1750,6 @@ public final class GalleryListScene extends BaseScene public abstract Announcer createAnnouncer(); - @Override - public void onLongClick() { - } } private class GalleryDetailUrlSuggestion extends UrlSuggestion { diff --git a/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java b/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java index b1b8d12bc..3420fc1e2 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java @@ -34,21 +34,23 @@ import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; -import android.widget.BaseAdapter; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; import androidx.annotation.Keep; import androidx.annotation.NonNull; import androidx.core.util.Pair; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.card.MaterialCardView; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.hippo.easyrecyclerview.EasyRecyclerView; import com.hippo.ehviewer.R; import com.hippo.ehviewer.client.EhTagDatabase; import com.hippo.view.ViewTransition; import com.hippo.yorozuya.AnimationUtils; -import com.hippo.yorozuya.LayoutUtils; import com.hippo.yorozuya.MathUtils; import com.hippo.yorozuya.SimpleAnimatorListener; import com.hippo.yorozuya.ViewUtils; @@ -77,7 +79,7 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, private TextView mTitleTextView; private ImageView mActionButton; private SearchEditText mEditText; - private ListView mListView; + private EasyRecyclerView mListView; private View mListContainer; private View mListHeader; @@ -120,7 +122,7 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, mActionButton = (ImageView) ViewUtils.$$(this, R.id.search_action); mEditText = (SearchEditText) ViewUtils.$$(this, R.id.search_edit_text); mListContainer = ViewUtils.$$(this, R.id.list_container); - mListView = (ListView) ViewUtils.$$(mListContainer, R.id.search_bar_list); + mListView = (EasyRecyclerView) ViewUtils.$$(mListContainer, R.id.search_bar_list); mListHeader = ViewUtils.$$(mListContainer, R.id.list_header); mViewTransition = new ViewTransition(mTitleTextView, mEditText); @@ -139,11 +141,16 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, mSuggestionList = new ArrayList<>(); mSuggestionAdapter = new SuggestionAdapter(LayoutInflater.from(getContext())); mListView.setAdapter(mSuggestionAdapter); - mListView.setOnItemClickListener((parent, view, position, id) -> mSuggestionList.get(position).onClick()); - mListView.setOnItemLongClickListener((parent, view, position, id) -> { - mSuggestionList.get(position).onLongClick(); + LinearLayoutManager layoutManager = new LinearLayoutManager(context); + DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(context, + layoutManager.getOrientation()); + mListView.addItemDecoration(dividerItemDecoration); + mListView.setLayoutManager(layoutManager); + mListView.setOnItemClickListener((parent, view, position, id) -> { + mSuggestionList.get(position).onClick(); return true; }); + mListView.setOnItemLongClickListener((parent, view, position, id) -> mSuggestionList.get(position).onLongClick()); } private void addListHeader() { @@ -173,7 +180,7 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, EhTagDatabase ehTagDatabase = EhTagDatabase.getInstance(getContext()); if (!TextUtils.isEmpty(text) && ehTagDatabase != null && !text.endsWith(" ")) { String[] s = text.split(" "); - if (s != null && s.length > 0) { + if (s.length > 0) { String keyword = s[s.length - 1]; ArrayList> searchHints = ehTagDatabase.suggest(keyword); @@ -197,7 +204,7 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, mSuggestionAdapter.notifyDataSetChanged(); if (scrollToTop) { - mListView.setSelection(0); + mListView.scrollToPosition(0); } } @@ -501,14 +508,28 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, public abstract static class Suggestion { - public abstract CharSequence getText(float textSize); + public abstract CharSequence getText(TextView textView); public abstract void onClick(); - public abstract void onLongClick(); + public boolean onLongClick() { + return false; + } + } - private class SuggestionAdapter extends BaseAdapter { + private static class SuggestionHolder extends RecyclerView.ViewHolder { + TextView text1; + TextView text2; + + public SuggestionHolder(@NonNull View itemView) { + super(itemView); + text1 = itemView.findViewById(android.R.id.text1); + text2 = itemView.findViewById(android.R.id.text2); + } + } + + private class SuggestionAdapter extends RecyclerView.Adapter { private final LayoutInflater mInflater; @@ -516,14 +537,25 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, mInflater = inflater; } + @NonNull @Override - public int getCount() { - return mSuggestionList.size(); + public SuggestionHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new SuggestionHolder(mInflater.inflate(R.layout.item_simple_list_2, parent, false)); } @Override - public Object getItem(int position) { - return mSuggestionList.get(position); + public void onBindViewHolder(@NonNull SuggestionHolder holder, int position) { + Suggestion suggestion = mSuggestionList.get(position); + CharSequence text1 = suggestion.getText(holder.text1); + CharSequence text2 = suggestion.getText(holder.text2); + holder.text1.setText(text1); + if (text2 == null) { + holder.text2.setVisibility(View.GONE); + holder.text2.setText(""); + } else { + holder.text2.setVisibility(View.VISIBLE); + holder.text2.setText(text2); + } } @Override @@ -532,29 +564,10 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, } @Override - public View getView(int position, View convertView, ViewGroup parent) { - View view; - if (convertView == null) { - view = mInflater.inflate(R.layout.item_simple_list_2, parent, false); - } else { - view = convertView; - } - - TextView textView1 = view.findViewById(android.R.id.text1); - CharSequence text1 = mSuggestionList.get(position).getText(textView1.getTextSize()); - TextView textView2 = view.findViewById(android.R.id.text2); - CharSequence text2 = mSuggestionList.get(position).getText(textView2.getTextSize()); - textView1.setText(text1); - if (text1.equals(text2)) { - textView2.setVisibility(View.GONE); - textView2.setText(""); - } else { - textView2.setVisibility(View.VISIBLE); - textView2.setText(text2); - } - - return view; + public int getItemCount() { + return mSuggestionList.size(); } + } public class TagSuggestion extends SearchBar.Suggestion { @@ -567,8 +580,8 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, } @Override - public CharSequence getText(float textSize) { - if (LayoutUtils.pix2sp(getContext(), textSize) > 15) { + public CharSequence getText(TextView textView) { + if (textView.getId() == android.R.id.text1) { return mKeyword; } else { return mHint; @@ -577,17 +590,16 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, @Override public void onClick() { - String text = mEditText.getText().toString(); - String temp = wrapTagKeyword(mKeyword) + " "; - if (text.contains(" ")) { - temp = text.substring(0, text.lastIndexOf(" ")) + " " + temp; + Editable editable = mEditText.getText(); + if (editable != null) { + String text = editable.toString(); + String temp = wrapTagKeyword(mKeyword) + " "; + if (text.contains(" ")) { + temp = text.substring(0, text.lastIndexOf(" ")) + " " + temp; + } + mEditText.setText(temp); + mEditText.setSelection(editable.length()); } - mEditText.setText(temp); - mEditText.setSelection(mEditText.getText().length()); - } - - @Override - public void onLongClick() { } } @@ -600,20 +612,31 @@ public class SearchBar extends MaterialCardView implements View.OnClickListener, } @Override - public CharSequence getText(float textSize) { - return mKeyword; + public CharSequence getText(TextView textView) { + if (textView.getId() == android.R.id.text1) { + return mKeyword; + } else { + return null; + } } @Override public void onClick() { mEditText.setText(mKeyword); - mEditText.setSelection(mEditText.getText().length()); + mEditText.setSelection(mEditText.length()); } @Override - public void onLongClick() { - mSearchDatabase.deleteQuery(mKeyword); - updateSuggestions(false); + public boolean onLongClick() { + new MaterialAlertDialogBuilder(getContext()) + .setMessage(getContext().getString(R.string.delete_search_history, mKeyword)) + .setNegativeButton(android.R.string.cancel, null) + .setPositiveButton(R.string.delete, (dialog, which) -> { + mSearchDatabase.deleteQuery(mKeyword); + updateSuggestions(false); + }) + .show(); + return true; } } diff --git a/app/src/main/java/com/hippo/scene/StageActivity.java b/app/src/main/java/com/hippo/scene/StageActivity.java index 10cc9e5dc..4ef67a631 100644 --- a/app/src/main/java/com/hippo/scene/StageActivity.java +++ b/app/src/main/java/com/hippo/scene/StageActivity.java @@ -269,7 +269,7 @@ public abstract class StageActivity extends EhActivity { // Use default animation if (horizontal) { - transaction.setCustomAnimations(R.anim.scene_open_enter_horizontal, R.anim.scene_open_exit_horizontal); + transaction.setCustomAnimations(R.anim.scene_open_enter_horizontal, R.anim.scene_open_exit); } else { transaction.setCustomAnimations(R.anim.scene_open_enter, R.anim.scene_open_exit); } @@ -361,7 +361,7 @@ public abstract class StageActivity extends EhActivity { newScene.setExitTransition(null); // Set default animation if (horizontal) { - transaction.setCustomAnimations(R.anim.scene_open_enter_horizontal, R.anim.scene_open_exit_horizontal); + transaction.setCustomAnimations(R.anim.scene_open_enter_horizontal, R.anim.scene_open_exit); } else { transaction.setCustomAnimations(R.anim.scene_open_enter, R.anim.scene_open_exit); } diff --git a/app/src/main/res/anim/scene_open_exit_horizontal.xml b/app/src/main/res/anim/scene_open_exit_horizontal.xml deleted file mode 100644 index c637be392..000000000 --- a/app/src/main/res/anim/scene_open_exit_horizontal.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - diff --git a/app/src/main/res/layout/item_simple_list_2.xml b/app/src/main/res/layout/item_simple_list_2.xml index b90a28559..2ae071619 100644 --- a/app/src/main/res/layout/item_simple_list_2.xml +++ b/app/src/main/res/layout/item_simple_list_2.xml @@ -21,7 +21,8 @@ android:paddingLeft="?attr/listPreferredItemPaddingLeft" android:paddingTop="8dp" android:paddingRight="?attr/listPreferredItemPaddingRight" - android:paddingBottom="8dp"> + android:paddingBottom="8dp" + android:background="?selectableItemBackground"> + android:layout_marginHorizontal="@dimen/gallery_search_bar_margin_h" + android:layout_marginVertical="@dimen/gallery_search_bar_margin_v" /> + android:layout_marginHorizontal="@dimen/gallery_search_bar_margin_h" + android:layout_marginVertical="@dimen/gallery_search_bar_margin_v" /> + + - - - + android:layout_height="wrap_content" /> diff --git a/app/src/main/res/values-night-v29/colors.xml b/app/src/main/res/values-night-v29/colors.xml new file mode 100644 index 000000000..1c01a12e7 --- /dev/null +++ b/app/src/main/res/values-night-v29/colors.xml @@ -0,0 +1,3 @@ + + @android:color/transparent + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 5ee4336b7..a302827fa 100755 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -733,4 +733,5 @@ 投票成功 从剪贴板导入 未在剪贴板中发现 Cookeis。 + 从搜索记录中删除“%s”? diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9eaa70c49..bbdd10800 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -797,4 +797,5 @@ Vote successfully From clipboard No cookies found in clipboard. + Delete \"%s\" from search history?