Add search history
This commit is contained in:
1 parent
beec5d8776
commit
be8ab2fcb2
5 files changed
+216
-43
No files matched your search
@@ -24,6 +24,7 @@ import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.ui.ContentActivity;
|
||||
import com.hippo.ehviewer.widget.ContentLayout;
|
||||
import com.hippo.ehviewer.widget.SearchBar;
|
||||
import com.hippo.ehviewer.widget.SearchDatabase;
|
||||
import com.hippo.scene.Scene;
|
||||
import com.hippo.scene.TransitionCurtain;
|
||||
import com.hippo.util.Log;
|
||||
@@ -37,6 +38,7 @@ class GalleryListScene extends Scene implements SearchBar.Helper{
|
||||
|
||||
private ContentActivity mActivity;
|
||||
private Resources mResources;
|
||||
private SearchDatabase mSearchDatabase;
|
||||
|
||||
private SearchBar mSearchBar;
|
||||
private ContentLayout mContentLayout;
|
||||
@@ -48,6 +50,7 @@ class GalleryListScene extends Scene implements SearchBar.Helper{
|
||||
|
||||
mActivity = (ContentActivity) getStageActivity();
|
||||
mResources = mActivity.getResources();
|
||||
mSearchDatabase = SearchDatabase.getInstance(getStageActivity());
|
||||
|
||||
mSearchBar = (SearchBar) findViewById(R.id.search_bar);
|
||||
mContentLayout = (ContentLayout) findViewById(R.id.content_layout);
|
||||
@@ -73,6 +76,7 @@ class GalleryListScene extends Scene implements SearchBar.Helper{
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onGetFitPaddingBottom(int b) {
|
||||
// TODO
|
||||
}
|
||||
@@ -90,5 +94,7 @@ class GalleryListScene extends Scene implements SearchBar.Helper{
|
||||
@Override
|
||||
public void onApplySearch(String query) {
|
||||
Log.d("onApplySearch " + query);
|
||||
mSearchDatabase.addQuery(query);
|
||||
mSearchBar.setInNormalMode();
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,12 @@ import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.CardView;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -49,7 +50,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SearchBar extends CardView implements View.OnClickListener,
|
||||
TextView.OnEditorActionListener {
|
||||
TextView.OnEditorActionListener, TextWatcher {
|
||||
|
||||
private static final long ANIMATION_TIME = 300;
|
||||
|
||||
@@ -60,7 +61,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
private float mProgress;
|
||||
|
||||
private SimpleImageView mMenuButton;
|
||||
private TextView mLogoTextView;
|
||||
private TextView mTitleTextView;
|
||||
private SimpleImageView mActionButton;
|
||||
private SearchEditText mEditText;
|
||||
private ListView mList;
|
||||
@@ -68,6 +69,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
private DrawerArrowDrawable mDrawerArrowDrawable;
|
||||
private AddDeleteDrawable mAddDeleteDrawable;
|
||||
|
||||
private SearchDatabase mSearchDatabase;
|
||||
private List<String> mSuggestionList;
|
||||
private ArrayAdapter mSuggestionAdapter;
|
||||
|
||||
@@ -93,15 +95,17 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
mSearchDatabase = SearchDatabase.getInstance(getContext());
|
||||
|
||||
setRadius(UiUtils.dp2pix(context, 2));
|
||||
setCardElevation(UiUtils.dp2pix(context, 2));
|
||||
setCardBackgroundColor(Color.WHITE);
|
||||
setOnClickListener(this);
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.widget_search_bar, this);
|
||||
mMenuButton = (SimpleImageView) findViewById(R.id.menu);
|
||||
mLogoTextView = (TextView) findViewById(R.id.logo);
|
||||
mActionButton = (SimpleImageView) findViewById(R.id.action);
|
||||
mMenuButton = (SimpleImageView) findViewById(R.id.search_menu);
|
||||
mTitleTextView = (TextView) findViewById(R.id.search_title);
|
||||
mActionButton = (SimpleImageView) findViewById(R.id.search_action);
|
||||
mEditText = (SearchEditText) findViewById(R.id.search_edit_text);
|
||||
mList = (ListView) findViewById(R.id.search_bar_list);
|
||||
|
||||
@@ -110,22 +114,28 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
|
||||
mMenuButton.setDrawable(mDrawerArrowDrawable);
|
||||
mMenuButton.setOnClickListener(this);
|
||||
mLogoTextView.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/Slabo.ttf"));
|
||||
mActionButton.setDrawable(mAddDeleteDrawable);
|
||||
mActionButton.setOnClickListener(this);
|
||||
mEditText.setSearchBar(this);
|
||||
mEditText.setOnEditorActionListener(this);
|
||||
mEditText.addTextChangedListener(this);
|
||||
|
||||
mSuggestionList = new ArrayList<>();
|
||||
mSuggestionList.add("aaaaaaaaaaaaaaaaaaaaa");
|
||||
mSuggestionList.add("dfsgfewrewfes");
|
||||
mSuggestionList.add("dehyklrthrhbdsrf");
|
||||
mSuggestionList.add("粉色热污染份额为别人的");
|
||||
mSuggestionAdapter = new ArrayAdapter<>(getContext(),
|
||||
android.R.layout.simple_list_item_1, mSuggestionList);
|
||||
mList.setAdapter(mSuggestionAdapter);
|
||||
}
|
||||
|
||||
private void updateSuggestions() {
|
||||
String prefix = mEditText.getText().toString();
|
||||
String[] suggestions = mSearchDatabase.getSuggestions(prefix);
|
||||
mSuggestionList.clear();
|
||||
for (String suggestion : suggestions) {
|
||||
mSuggestionList.add(suggestion);
|
||||
}
|
||||
mSuggestionAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void setHelper(Helper helper) {
|
||||
mHelper = helper;
|
||||
}
|
||||
@@ -142,7 +152,6 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
}
|
||||
} else if (v == mActionButton) {
|
||||
if (mInEditMode) {
|
||||
// TODO when set prefix
|
||||
mEditText.setText("");
|
||||
} else {
|
||||
mHelper.onClickAction();
|
||||
@@ -168,12 +177,14 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
if (!mInEditMode) {
|
||||
mInEditMode = true;
|
||||
setClickable(false);
|
||||
ViewUtils.setVisibility(mLogoTextView, View.GONE);
|
||||
ViewUtils.setVisibility(mTitleTextView, View.GONE);
|
||||
ViewUtils.setVisibility(mEditText, View.VISIBLE);
|
||||
mEditText.requestFocus();
|
||||
// show ime
|
||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
|
||||
// update suggestion
|
||||
updateSuggestions();
|
||||
// start animator
|
||||
ObjectAnimator oa1 = ObjectAnimator.ofFloat(mDrawerArrowDrawable, "progress", 0f, 1f);
|
||||
oa1.setDuration(ANIMATION_TIME);
|
||||
@@ -208,7 +219,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
if (mInEditMode) {
|
||||
mInEditMode = false;
|
||||
setOnClickListener(this);
|
||||
ViewUtils.setVisibility(mLogoTextView, View.VISIBLE);
|
||||
ViewUtils.setVisibility(mTitleTextView, View.VISIBLE);
|
||||
ViewUtils.setVisibility(mEditText, View.GONE);
|
||||
// hide ime
|
||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
@@ -243,6 +254,10 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
}
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
mTitleTextView.setText(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
@@ -282,6 +297,21 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
}
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
public interface Helper {
|
||||
void onClickMenu();
|
||||
void onClickAction();
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.hippo.util.Log;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class SearchDatabase {
|
||||
|
||||
private static final String TAG = SearchDatabase.class.getSimpleName();
|
||||
|
||||
public static final String COLUMN_QUERY = "query";
|
||||
public static final String COLUMN_DATE = "date";
|
||||
|
||||
private static final String DATABASE_NAME = "search_database.db";
|
||||
private static final String TABLE_SUGGESTIONS = "suggestions";
|
||||
|
||||
private static final int MAX_HISTORY = 100;
|
||||
|
||||
private SQLiteDatabase mDatabase;
|
||||
|
||||
private static SearchDatabase sInstance;
|
||||
|
||||
public static SearchDatabase getInstance(Context context) {
|
||||
if (sInstance == null) {
|
||||
sInstance = new SearchDatabase(context.getApplicationContext());
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private SearchDatabase(Context context) {
|
||||
DatabaseHelper databaseHelper = new DatabaseHelper(context);
|
||||
mDatabase = databaseHelper.getWritableDatabase();
|
||||
}
|
||||
|
||||
public String[] getSuggestions(String prefix) {
|
||||
List<String> queryList = new LinkedList<>();
|
||||
|
||||
// TODO add limit
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("SELECT * FROM ").append(TABLE_SUGGESTIONS);
|
||||
if (!TextUtils.isEmpty(prefix)) {
|
||||
sb.append(" WHERE ").append(COLUMN_QUERY).append(" LIKE '")
|
||||
.append(prefix).append("%'");
|
||||
}
|
||||
sb.append(" ORDER BY ").append(COLUMN_DATE).append(" DESC")
|
||||
.append(" LIMIT 5");
|
||||
Cursor cursor = mDatabase.rawQuery(sb.toString(), null);
|
||||
int queryIndex = cursor.getColumnIndex(COLUMN_QUERY);
|
||||
if (cursor.moveToFirst()) {
|
||||
while (!cursor.isAfterLast()) {
|
||||
String suggestion = cursor.getString(queryIndex);
|
||||
if (!prefix.equals(suggestion)) {
|
||||
queryList.add(suggestion);
|
||||
}
|
||||
cursor.moveToNext();
|
||||
}
|
||||
}
|
||||
cursor.close();
|
||||
return queryList.toArray(new String[queryList.size()]);
|
||||
}
|
||||
|
||||
public void addQuery(final String query) {
|
||||
if (!TextUtils.isEmpty(query)) {
|
||||
// Delete old first
|
||||
deleteQuery(query);
|
||||
// Add it to database
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(COLUMN_QUERY, query);
|
||||
values.put(COLUMN_DATE, System.currentTimeMillis());
|
||||
mDatabase.insert(TABLE_SUGGESTIONS, null, values);
|
||||
// Remove history if more than max
|
||||
truncateHistory(MAX_HISTORY);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteQuery(final String query) {
|
||||
mDatabase.delete(TABLE_SUGGESTIONS, COLUMN_DATE + "=?", new String[]{query});
|
||||
}
|
||||
|
||||
public void clearQuery() {
|
||||
truncateHistory(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the length of the history table, to prevent it from growing too large.
|
||||
*
|
||||
* @param maxEntries Max entries to leave in the table. 0 means remove all entries.
|
||||
*/
|
||||
protected void truncateHistory(int maxEntries) {
|
||||
if (maxEntries < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
try {
|
||||
// null means "delete all". otherwise "delete but leave n newest"
|
||||
String selection = null;
|
||||
if (maxEntries > 0) {
|
||||
selection = "_id IN " +
|
||||
"(SELECT _id FROM " + TABLE_SUGGESTIONS +
|
||||
" ORDER BY " + COLUMN_DATE + " DESC" +
|
||||
" LIMIT -1 OFFSET " + String.valueOf(maxEntries) + ")";
|
||||
}
|
||||
mDatabase.delete(TABLE_SUGGESTIONS, selection, null);
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "truncateHistory", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builds the database. This version has extra support for using the version field
|
||||
* as a mode flags field, and configures the database columns depending on the mode bits
|
||||
* (features) requested by the extending class.
|
||||
*/
|
||||
private static class DatabaseHelper extends SQLiteOpenHelper {
|
||||
|
||||
public DatabaseHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE " + TABLE_SUGGESTIONS + " (" +
|
||||
"_id INTEGER PRIMARY KEY" +
|
||||
"," + COLUMN_QUERY + " TEXT" +
|
||||
"," + COLUMN_DATE + " LONG" +
|
||||
");");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
db.execSQL("DROP TABLE IF EXISTS " + TABLE_SUGGESTIONS);
|
||||
onCreate(db);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +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
|
||||
* 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.util;
|
||||
|
||||
public class TextUtils {
|
||||
|
||||
public static final String STRING_EMPTY = "";
|
||||
public static final String STRING_NULL = "null";
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user