diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/FavoritesScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/FavoritesScene.java index ab747c57c..f075eac6d 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/FavoritesScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/FavoritesScene.java @@ -34,7 +34,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.Toolbar; -import androidx.core.content.ContextCompat; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsAnimationCompat; import androidx.drawerlayout.widget.DrawerLayout; @@ -69,12 +68,10 @@ import com.hippo.ehviewer.ui.annotation.DrawerLifeCircle; import com.hippo.ehviewer.ui.annotation.ViewLifeCircle; import com.hippo.ehviewer.ui.annotation.WholeLifeCircle; import com.hippo.ehviewer.widget.GalleryInfoContentHelper; -import com.hippo.ehviewer.widget.SearchBar; import com.hippo.scene.Announcer; import com.hippo.scene.SceneFragment; import com.hippo.widget.ContentLayout; import com.hippo.widget.FabLayout; -import com.hippo.widget.SearchBarMover; import com.hippo.yorozuya.AssertUtils; import com.hippo.yorozuya.ObjectUtils; import com.hippo.yorozuya.SimpleHandler; @@ -91,8 +88,8 @@ import rikka.core.res.ResourcesKt; // TODO Get favorite, modify favorite, add favorite, what a mess! @SuppressLint("RtlHardcoded") -public class FavoritesScene extends BaseScene implements - FastScroller.OnDragHandlerListener, SearchBarMover.Helper, SearchBar.Helper, +public class FavoritesScene extends SearchBarScene implements + FastScroller.OnDragHandlerListener, FabLayout.OnClickFabListener, FabLayout.OnExpandListener, EasyRecyclerView.CustomChoiceListener { @@ -113,9 +110,6 @@ public class FavoritesScene extends BaseScene implements private EasyRecyclerView mRecyclerView; @Nullable @ViewLifeCircle - private SearchBar mSearchBar; - @Nullable - @ViewLifeCircle private FabLayout mFabLayout; @Nullable @ViewLifeCircle @@ -125,9 +119,6 @@ public class FavoritesScene extends BaseScene implements private FavoritesHelper mHelper; @Nullable @ViewLifeCircle - private SearchBarMover mSearchBarMover; - @Nullable - @ViewLifeCircle private DrawerArrowDrawable mLeftDrawable; private AddDeleteDrawable mActionFabDrawable; @Nullable @@ -246,16 +237,19 @@ public class FavoritesScene extends BaseScene implements @Nullable @Override - public View onCreateView(@NonNull LayoutInflater inflater, + public View onCreateViewWithToolbar(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.scene_favorites, container, false); mContentLayout = view.findViewById(R.id.content_layout); MainActivity activity = getMainActivity(); AssertUtils.assertNotNull(activity); + setOnApplySearch((query) -> { + onApplySearch(query); + return null; + }); mDrawerLayout = (DrawerLayout) ViewUtils.$$(activity, R.id.draw_view); mRecyclerView = mContentLayout.getRecyclerView(); FastScroller fastScroller = mContentLayout.getFastScroller(); - mSearchBar = (SearchBar) ViewUtils.$$(view, R.id.search_bar); mFabLayout = (FabLayout) ViewUtils.$$(view, R.id.fab_layout); ViewCompat.setWindowInsetsAnimationCallback(view, new WindowInsetsAnimationHelper( WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_STOP, @@ -283,13 +277,10 @@ public class FavoritesScene extends BaseScene implements fastScroller.getPaddingRight(), fastScroller.getPaddingBottom()); mLeftDrawable = new DrawerArrowDrawable(context, ResourcesKt.resolveColor(getTheme(), android.R.attr.colorControlNormal)); - mSearchBar.setLeftDrawable(mLeftDrawable); - mSearchBar.setRightDrawable(ContextCompat.getDrawable(context, R.drawable.v_magnify_x24)); - mSearchBar.setHelper(this); - mSearchBar.setAllowEmptySearch(false); + setNavigationDrawable(mLeftDrawable); + setAllowEmptySearch(false); updateSearchBar(); updateJumpFab(); - mSearchBarMover = new SearchBarMover(this, mSearchBar, mRecyclerView); int colorID = ResourcesKt.resolveColor(getTheme(), com.google.android.material.R.attr.colorOnSurface); mActionFabDrawable = new AddDeleteDrawable(context, colorID); @@ -320,7 +311,7 @@ public class FavoritesScene extends BaseScene implements // They changed, call it private void updateSearchBar() { Context context = getContext(); - if (null == context || null == mUrlBuilder || null == mSearchBar || null == mFavCatArray) { + if (null == context || null == mUrlBuilder || null == mFavCatArray) { return; } @@ -337,17 +328,17 @@ public class FavoritesScene extends BaseScene implements String keyword = mUrlBuilder.getKeyword(); if (TextUtils.isEmpty(keyword)) { if (!ObjectUtils.equal(favCatName, mOldFavCat)) { - mSearchBar.setTitle(getString(R.string.favorites_title, favCatName)); + setSearchBarHint(getString(R.string.favorites_title, favCatName)); } } else { if (!ObjectUtils.equal(favCatName, mOldFavCat) || !ObjectUtils.equal(keyword, mOldKeyword)) { - mSearchBar.setTitle(getString(R.string.favorites_title_2, favCatName, keyword)); + setSearchBarHint(getString(R.string.favorites_title_2, favCatName, keyword)); } } // Update hint if (!ObjectUtils.equal(favCatName, mOldFavCat)) { - mSearchBar.setEditTextHint(getString(R.string.favorites_search_bar_hint, favCatName)); + setEditTextHint(getString(R.string.favorites_search_bar_hint, favCatName)); } mOldFavCat = favCatName; @@ -384,10 +375,6 @@ public class FavoritesScene extends BaseScene implements } mAdapter = null; - - mSearchBar = null; - - mSearchBarMover = null; mLeftDrawable = null; mOldFavCat = null; @@ -445,6 +432,8 @@ public class FavoritesScene extends BaseScene implements mFabLayout.toggle(); } else if (mSearchMode) { exitSearchMode(true); + } else if (isSearchViewShown()) { + hideSearchView(); } else { finish(); } @@ -463,9 +452,7 @@ public class FavoritesScene extends BaseScene implements setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, Gravity.RIGHT); } - if (mSearchBarMover != null) { - mSearchBarMover.returnSearchBarPosition(); - } + showSearchBar(); } public boolean onItemClick(View view, int position) { @@ -531,70 +518,6 @@ public class FavoritesScene extends BaseScene implements return true; } - @Override - public boolean isValidView(RecyclerView recyclerView) { - return recyclerView == mRecyclerView; - } - - @Override - public RecyclerView getValidRecyclerView() { - return mRecyclerView; - } - - @Override - public boolean forceShowSearchBar() { - return false; - } - - @Override - public void onClickTitle() { - // Skip if in search mode - if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) { - return; - } - - if (!mSearchMode) { - enterSearchMode(true); - } - } - - @Override - public void onClickLeftIcon() { - // Skip if in search mode - if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) { - return; - } - - if (mSearchMode) { - exitSearchMode(true); - } else { - toggleDrawer(Gravity.LEFT); - } - } - - @Override - public void onClickRightIcon() { - // Skip if in search mode - if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) { - return; - } - - if (!mSearchMode) { - enterSearchMode(true); - } else if (mSearchBar != null) { - if (mSearchBar.getEditText().length() == 0) { - exitSearchMode(true); - } else { - mSearchBar.applySearch(); - } - } - } - - @Override - public void onSearchEditTextClick() { - } - - @Override public void onApplySearch(String query) { // Skip if in search mode if (mRecyclerView != null && mRecyclerView.isInCustomChoice()) { @@ -617,11 +540,6 @@ public class FavoritesScene extends BaseScene implements mHelper.refresh(); } - @Override - public void onSearchEditTextBackPressed() { - onBackPressed(); - } - @Override public void onExpand(boolean expanded) { if (expanded) { @@ -810,28 +728,25 @@ public class FavoritesScene extends BaseScene implements } private void enterSearchMode(boolean animation) { - if (mSearchMode || mSearchBar == null || mSearchBarMover == null || mLeftDrawable == null) { + if (mSearchMode || mLeftDrawable == null) { return; } mSearchMode = true; - mSearchBar.setState(SearchBar.STATE_SEARCH_LIST, animation); - mSearchBarMover.returnSearchBarPosition(animation); + showSearchBar(); mLeftDrawable.setArrow(ANIMATE_TIME); } private void exitSearchMode(boolean animation) { - if (!mSearchMode || mSearchBar == null || mSearchBarMover == null || mLeftDrawable == null) { + if (!mSearchMode || mLeftDrawable == null) { return; } mSearchMode = false; - mSearchBar.setState(SearchBar.STATE_NORMAL, animation); - mSearchBarMover.returnSearchBarPosition(); + showSearchBar(); mLeftDrawable.setMenu(ANIMATE_TIME); } private void onGetFavoritesSuccess(FavoritesParser.Result result, int taskId) { - if (mHelper != null && mSearchBarMover != null && - mHelper.isCurrentTask(taskId)) { + if (mHelper != null && mHelper.isCurrentTask(taskId)) { if (mFavCatArray != null) { System.arraycopy(result.catArray, 0, mFavCatArray, 0, 10); @@ -878,8 +793,7 @@ public class FavoritesScene extends BaseScene implements } private void onGetFavoritesFailure(Exception e, int taskId) { - if (mHelper != null && mSearchBarMover != null && - mHelper.isCurrentTask(taskId)) { + if (mHelper != null && mHelper.isCurrentTask(taskId)) { mHelper.onGetException(taskId, e); } } @@ -1315,9 +1229,7 @@ public class FavoritesScene extends BaseScene implements @Override public void onShowView(View hiddenView, View shownView) { - if (null != mSearchBarMover) { - mSearchBarMover.showSearchBar(); - } + showSearchBar(); } @Override @@ -1326,11 +1238,9 @@ public class FavoritesScene extends BaseScene implements } @Override - protected void onScrollToPosition(int postion) { - if (0 == postion) { - if (null != mSearchBarMover) { - mSearchBarMover.showSearchBar(); - } + protected void onScrollToPosition(int position) { + if (0 == position) { + showSearchBar(); } } diff --git a/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java b/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java deleted file mode 100644 index 64561d937..000000000 --- a/app/src/main/java/com/hippo/ehviewer/widget/SearchBar.java +++ /dev/null @@ -1,681 +0,0 @@ -/* - * Copyright 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.ehviewer.widget; - -import android.animation.Animator; -import android.animation.ObjectAnimator; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Bundle; -import android.os.Parcelable; -import android.text.Editable; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.AttributeSet; -import android.view.HapticFeedbackConstants; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputMethodManager; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.core.util.Pair; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.google.android.material.card.MaterialCardView; -import com.hippo.app.BaseDialogBuilder; -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.MathUtils; -import com.hippo.yorozuya.SimpleAnimatorListener; -import com.hippo.yorozuya.ViewUtils; - -import java.util.ArrayList; -import java.util.List; - -public class SearchBar extends MaterialCardView implements View.OnClickListener, - TextView.OnEditorActionListener, TextWatcher, - SearchEditText.SearchEditTextListener { - - public static final int STATE_NORMAL = 0; - public static final int STATE_SEARCH = 1; - public static final int STATE_SEARCH_LIST = 2; - private static final String STATE_KEY_SUPER = "super"; - private static final String STATE_KEY_STATE = "state"; - private static final long ANIMATE_TIME = 300L; - private final Rect mRect = new Rect(); - private int mState = STATE_NORMAL; - private int mWidth; - private int mHeight; - private int mBaseHeight; - private float mProgress; - - private ImageView mMenuButton; - private TextView mTitleTextView; - private ImageView mActionButton; - private SearchEditText mEditText; - private EasyRecyclerView mListView; - private View mListContainer; - private View mListHeader; - - private ViewTransition mViewTransition; - - private SearchDatabase mSearchDatabase; - private List mSuggestionList; - private SuggestionAdapter mSuggestionAdapter; - - private Helper mHelper; - private OnStateChangeListener mOnStateChangeListener; - private SuggestionProvider mSuggestionProvider; - - private boolean mAllowEmptySearch = true; - - private boolean mInAnimation; - - public SearchBar(Context context) { - super(context); - init(context); - } - - public SearchBar(Context context, AttributeSet attrs) { - super(context, attrs); - init(context); - } - - public SearchBar(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - init(context); - } - - private void init(Context context) { - mSearchDatabase = SearchDatabase.getInstance(getContext()); - - LayoutInflater inflater = LayoutInflater.from(context); - inflater.inflate(R.layout.widget_search_bar, this); - mMenuButton = (ImageView) ViewUtils.$$(this, R.id.search_menu); - mTitleTextView = (TextView) ViewUtils.$$(this, R.id.search_title); - 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 = (EasyRecyclerView) ViewUtils.$$(mListContainer, R.id.search_bar_list); - mListHeader = ViewUtils.$$(mListContainer, R.id.list_header); - - mViewTransition = new ViewTransition(mTitleTextView, mEditText); - - mTitleTextView.setOnClickListener(this); - mMenuButton.setOnClickListener(this); - mActionButton.setOnClickListener(this); - mEditText.setSearchEditTextListener(this); - mEditText.setOnEditorActionListener(this); - mEditText.addTextChangedListener(this); - - // Get base height - ViewUtils.measureView(this, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - mBaseHeight = getMeasuredHeight(); - - mSuggestionList = new ArrayList<>(); - mSuggestionAdapter = new SuggestionAdapter(LayoutInflater.from(getContext())); - mListView.setAdapter(mSuggestionAdapter); - LinearLayoutManager layoutManager = new LinearLayoutManager(context); - mListView.setLayoutManager(layoutManager); - } - - private void addListHeader() { - mListHeader.setVisibility(VISIBLE); - } - - private void removeListHeader() { - mListHeader.setVisibility(GONE); - } - - private void updateSuggestions() { - updateSuggestions(true); - } - - private void updateSuggestions(boolean scrollToTop) { - List suggestions = new ArrayList<>(); - - String text = mEditText.getText().toString(); - - if (mSuggestionProvider != null) { - List providerSuggestions = mSuggestionProvider.providerSuggestions(text); - if (providerSuggestions != null && !providerSuggestions.isEmpty()) { - suggestions.addAll(providerSuggestions); - } - } - - String[] keywords = mSearchDatabase.getSuggestions(text, 128); - for (String keyword : keywords) { - suggestions.add(new KeywordSuggestion(keyword)); - } - - EhTagDatabase ehTagDatabase = EhTagDatabase.getInstance(getContext()); - if (!TextUtils.isEmpty(text) && ehTagDatabase != null && !text.endsWith(" ")) { - String[] s = text.split(" "); - if (s.length > 0) { - String keyword = s[s.length - 1]; - ArrayList> searchHints = ehTagDatabase.suggest(keyword); - - for (Pair searchHint : searchHints) { - suggestions.add(new TagSuggestion(searchHint.first, searchHint.second)); - } - - } - } - - mSuggestionList = suggestions; - if (mSuggestionList.size() == 0) { - removeListHeader(); - } else { - addListHeader(); - } - mSuggestionAdapter.notifyDataSetChanged(); - - if (scrollToTop) { - mListView.scrollToPosition(0); - } - } - - public void setAllowEmptySearch(boolean allowEmptySearch) { - mAllowEmptySearch = allowEmptySearch; - } - - public void setEditTextHint(CharSequence hint) { - mEditText.setHint(hint); - } - - public void setHelper(Helper helper) { - mHelper = helper; - } - - public void setOnStateChangeListener(OnStateChangeListener listener) { - mOnStateChangeListener = listener; - } - - public void setSuggestionProvider(SuggestionProvider suggestionProvider) { - mSuggestionProvider = suggestionProvider; - } - - public String getText() { - return mEditText.getText().toString(); - } - - public void setText(String text) { - mEditText.setText(text); - } - - public void cursorToEnd() { - mEditText.setSelection(mEditText.getText().length()); - } - - public void setTitle(String title) { - mTitleTextView.setText(title); - } - - public void setSearch(String search) { - mTitleTextView.setText(search); - mEditText.setText(search); - } - - public void setLeftDrawable(Drawable drawable) { - mMenuButton.setImageDrawable(drawable); - } - - public void setRightDrawable(Drawable drawable) { - mActionButton.setImageDrawable(drawable); - } - - public void applySearch() { - String query = mEditText.getText().toString().trim(); - - if (!mAllowEmptySearch && TextUtils.isEmpty(query)) { - return; - } - - // Put it into db - mSearchDatabase.addQuery(query); - // Callback - mHelper.onApplySearch(query); - } - - @Override - public void onClick(View v) { - if (v == mTitleTextView) { - mHelper.onClickTitle(); - } else if (v == mMenuButton) { - v.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); - mHelper.onClickLeftIcon(); - } else if (v == mActionButton) { - v.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK); - mHelper.onClickRightIcon(); - } - } - - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (v == mEditText) { - if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_NULL) { - applySearch(); - return true; - } - } - return false; - } - - public int getState() { - return mState; - } - - public void setState(int state) { - setState(state, true); - } - - public void setState(int state, boolean animation) { - if (mState != state) { - int oldState = mState; - mState = state; - - switch (oldState) { - default: - case STATE_NORMAL: - mViewTransition.showView(1, animation); - mEditText.requestFocus(); - - if (state == STATE_SEARCH_LIST) { - showImeAndSuggestionsList(animation); - } - if (mOnStateChangeListener != null) { - mOnStateChangeListener.onStateChange(this, state, oldState, animation); - } - break; - case STATE_SEARCH: - if (state == STATE_NORMAL) { - mViewTransition.showView(0, animation); - } else if (state == STATE_SEARCH_LIST) { - showImeAndSuggestionsList(animation); - } - if (mOnStateChangeListener != null) { - mOnStateChangeListener.onStateChange(this, state, oldState, animation); - } - break; - case STATE_SEARCH_LIST: - hideImeAndSuggestionsList(animation); - if (state == STATE_NORMAL) { - mViewTransition.showView(0, animation); - } - if (mOnStateChangeListener != null) { - mOnStateChangeListener.onStateChange(this, state, oldState, animation); - } - break; - } - } - } - - public void showImeAndSuggestionsList(boolean animation) { - // Show ime - InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(mEditText, 0); - // update suggestion for show suggestions list - updateSuggestions(); - // Show suggestions list - if (animation) { - ObjectAnimator oa = ObjectAnimator.ofFloat(this, "progress", 1f); - oa.setDuration(ANIMATE_TIME); - oa.setInterpolator(AnimationUtils.FAST_SLOW_INTERPOLATOR); - oa.addListener(new SimpleAnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - mListContainer.setVisibility(View.VISIBLE); - mInAnimation = true; - } - - @Override - public void onAnimationEnd(Animator animation) { - mInAnimation = false; - } - }); - oa.setAutoCancel(true); - oa.start(); - } else { - mListContainer.setVisibility(View.VISIBLE); - setProgress(1f); - } - } - - private void hideImeAndSuggestionsList(boolean animation) { - // Hide ime - InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(this.getWindowToken(), 0); - // Hide suggestions list - if (animation) { - ObjectAnimator oa = ObjectAnimator.ofFloat(this, "progress", 0f); - oa.setDuration(ANIMATE_TIME); - oa.setInterpolator(AnimationUtils.SLOW_FAST_INTERPOLATOR); - oa.addListener(new SimpleAnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - mInAnimation = true; - } - - @Override - public void onAnimationEnd(Animator animation) { - mListContainer.setVisibility(View.GONE); - mInAnimation = false; - } - }); - oa.setAutoCancel(true); - oa.start(); - } else { - setProgress(0f); - mListContainer.setVisibility(View.GONE); - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (mListContainer.getVisibility() == View.VISIBLE && (!mInAnimation || mHeight == 0)) { - mWidth = right - left; - mHeight = bottom - top; - } - } - - public float getProgress() { - return mProgress; - } - - @Keep - public void setProgress(float progress) { - mProgress = progress; - invalidate(); - } - - public SearchEditText getEditText() { - return mEditText; - } - - @Override - public void draw(@NonNull Canvas canvas) { - if (mInAnimation && mHeight != 0) { - final int state = canvas.save(); - int bottom = MathUtils.lerp(mBaseHeight, mHeight, mProgress); - mRect.set(0, 0, mWidth, bottom); - setClipBounds(mRect); - canvas.clipRect(mRect); - super.draw(canvas); - canvas.restoreToCount(state); - } else { - setClipBounds(null); - super.draw(canvas); - } - } - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - // Empty - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - // Empty - } - - @Override - public void afterTextChanged(Editable s) { - updateSuggestions(); - } - - @Override - public void onClick() { - mHelper.onSearchEditTextClick(); - } - - @Override - public void onBackPressed() { - mHelper.onSearchEditTextBackPressed(); - } - - @Override - public void onReceiveContent(Uri uri) { - mHelper.onReceiveContent(uri); - } - - @Override - public Parcelable onSaveInstanceState() { - final Bundle state = new Bundle(); - state.putParcelable(STATE_KEY_SUPER, super.onSaveInstanceState()); - state.putInt(STATE_KEY_STATE, mState); - return state; - } - - @Override - public void onRestoreInstanceState(Parcelable state) { - if (state instanceof final Bundle savedState) { - super.onRestoreInstanceState(savedState.getParcelable(STATE_KEY_SUPER)); - setState(savedState.getInt(STATE_KEY_STATE), false); - } - } - - private String wrapTagKeyword(String keyword) { - keyword = keyword.trim(); - - int index1 = keyword.indexOf(':'); - if (index1 == -1 || index1 >= keyword.length() - 1) { - // Can't find :, or : is the last char - return keyword; - } - if (keyword.charAt(index1 + 1) == '"') { - // The char after : is ", the word must be quoted - return keyword; - } - int index2 = keyword.indexOf(' '); - if (index2 <= index1) { - // Can't find space, or space is before : - return keyword; - } - - return keyword.substring(0, index1 + 1) + "\"" + keyword.substring(index1 + 1) + "$\""; - } - - public interface Helper { - void onClickTitle(); - - void onClickLeftIcon(); - - void onClickRightIcon(); - - void onSearchEditTextClick(); - - void onApplySearch(String query); - - void onSearchEditTextBackPressed(); - - default void onReceiveContent(Uri uri) { - - } - - } - - public interface OnStateChangeListener { - - void onStateChange(SearchBar searchBar, int newState, int oldState, boolean animation); - } - - public interface SuggestionProvider { - - List providerSuggestions(String text); - } - - public abstract static class Suggestion { - - public abstract CharSequence getText(TextView textView); - - public abstract void onClick(); - - public boolean onLongClick() { - return false; - } - - } - - 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; - - private SuggestionAdapter(LayoutInflater inflater) { - mInflater = inflater; - } - - @NonNull - @Override - public SuggestionHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new SuggestionHolder(mInflater.inflate(R.layout.item_simple_list_2, parent, false)); - } - - @Override - 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); - } - - holder.itemView.setOnClickListener(v -> { - if (position < mSuggestionList.size()) { - mSuggestionList.get(position).onClick(); - } - }); - holder.itemView.setOnLongClickListener(v -> { - if (position < mSuggestionList.size()) { - return mSuggestionList.get(position).onLongClick(); - } else { - return false; - } - }); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public int getItemCount() { - return mSuggestionList.size(); - } - - } - - public class TagSuggestion extends SearchBar.Suggestion { - public String mHint; - public String mKeyword; - - private TagSuggestion(String hint, String keyword) { - mHint = hint; - mKeyword = keyword; - } - - @Override - public CharSequence getText(TextView textView) { - if (textView.getId() == android.R.id.text1) { - return mKeyword; - } else { - return mHint; - } - } - - @Override - public void onClick() { - 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()); - } - } - } - - public class KeywordSuggestion extends Suggestion { - - private final String mKeyword; - - private KeywordSuggestion(String keyword) { - mKeyword = keyword; - } - - @Override - 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.length()); - } - - @Override - public boolean onLongClick() { - new BaseDialogBuilder(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/ehviewer/widget/SearchEditText.java b/app/src/main/java/com/hippo/ehviewer/widget/SearchEditText.java deleted file mode 100644 index 123d2c6af..000000000 --- a/app/src/main/java/com/hippo/ehviewer/widget/SearchEditText.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2015 Hippo Seven - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.ehviewer.widget; - -import android.content.ClipData; -import android.content.Context; -import android.net.Uri; -import android.os.Build; -import android.util.AttributeSet; -import android.view.ContentInfo; -import android.view.KeyEvent; -import android.view.MotionEvent; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; -import androidx.appcompat.widget.AppCompatEditText; - -import com.hippo.util.ExceptionUtils; - -public class SearchEditText extends AppCompatEditText { - - private SearchEditTextListener mListener; - - public SearchEditText(Context context) { - super(context); - } - - public SearchEditText(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public SearchEditText(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - public void setSearchEditTextListener(SearchEditTextListener listener) { - mListener = listener; - } - - @Override - public boolean onKeyPreIme(int keyCode, @NonNull KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { - // special case for the back key, we do not even try to send it - // to the drop down list but instead, consume it immediately - if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { - KeyEvent.DispatcherState state = getKeyDispatcherState(); - if (state != null) { - state.startTracking(event, this); - } - return true; - } else if (event.getAction() == KeyEvent.ACTION_UP) { - KeyEvent.DispatcherState state = getKeyDispatcherState(); - if (state != null) { - state.handleUpEvent(event); - } - if (event.isTracking() && !event.isCanceled()) { - // TODO stopSelectionActionMode - if (mListener != null) { - mListener.onBackPressed(); - return true; - } - } - } - } - return super.onKeyPreIme(keyCode, event); - } - - @Override - public boolean onTouchEvent(@NonNull MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_UP && mListener != null) { - mListener.onClick(); - } - try { - return super.onTouchEvent(event); - } catch (Throwable t) { - // Some devices crash here. - // I don't why. - ExceptionUtils.throwIfFatal(t); - return false; - } - } - - @RequiresApi(api = Build.VERSION_CODES.S) - @Nullable - @Override - public ContentInfo onReceiveContent(@NonNull ContentInfo payload) { - ClipData clipData = payload.getClip(); - if (clipData.getItemCount() == 1) { - if (mListener != null) { - mListener.onReceiveContent(clipData.getItemAt(0).getUri()); - } - } - return super.onReceiveContent(payload); - } - - public interface SearchEditTextListener { - void onClick(); - - void onBackPressed(); - - void onReceiveContent(Uri uri); - } -} diff --git a/app/src/main/res/layout/scene_favorites.xml b/app/src/main/res/layout/scene_favorites.xml index 08410741b..a761fa178 100644 --- a/app/src/main/res/layout/scene_favorites.xml +++ b/app/src/main/res/layout/scene_favorites.xml @@ -18,7 +18,9 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/main_layout" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:paddingTop="16dp" + app:layout_behavior="@string/searchbar_scrolling_view_behavior"> - - - - - - - - - - - - - - - - - - - - - - - - - - - -