Convert FavouriteScene to New SearchBar, Kill hippo's searchbar
This commit is contained in:
1 parent
0effc0d181
commit
a20ca4ea2e
5 files changed
+29
-1021
No files matched your search
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Suggestion> 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<Suggestion> suggestions = new ArrayList<>();
|
||||
|
||||
String text = mEditText.getText().toString();
|
||||
|
||||
if (mSuggestionProvider != null) {
|
||||
List<Suggestion> 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<Pair<String, String>> searchHints = ehTagDatabase.suggest(keyword);
|
||||
|
||||
for (Pair<String, String> 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<Suggestion> 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<SuggestionHolder> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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">
|
||||
|
||||
<com.hippo.widget.ContentLayout
|
||||
android:id="@+id/content_layout"
|
||||
@@ -26,15 +28,6 @@
|
||||
android:layout_height="match_parent"
|
||||
app:fitsSystemWindowsInsets="top|bottom" />
|
||||
|
||||
<com.hippo.ehviewer.widget.SearchBar
|
||||
android:id="@+id/search_bar"
|
||||
style="@style/Widget.Material3.CardView.Filled"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="@dimen/gallery_search_bar_margin_h"
|
||||
android:layout_marginVertical="@dimen/gallery_search_bar_margin_v"
|
||||
app:layout_fitsSystemWindowsInsets="top|bottom" />
|
||||
|
||||
<com.hippo.widget.FabLayout
|
||||
android:id="@+id/fab_layout"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ 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
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/search_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingHorizontal="48dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_little_large" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_menu"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="left|center_vertical"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="12dp" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_action"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="12dp" />
|
||||
|
||||
<com.hippo.ehviewer.widget.SearchEditText
|
||||
android:id="@+id/search_edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="48dp"
|
||||
android:layout_marginRight="48dp"
|
||||
android:background="@null"
|
||||
android:imeOptions="actionSearch"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/text_little_small"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/list_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<View
|
||||
android:id="@+id/list_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/dividerColor" />
|
||||
|
||||
<com.hippo.easyrecyclerview.EasyRecyclerView
|
||||
android:id="@+id/search_bar_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</merge>
|
||||
Reference in new issue
Block a user