Improve GalleryListScene

This commit is contained in:
seven332 committed 2016-01-26 19:54:26 +08:00
1 parent d1650c4ec5
commit 24a64c23dc
17 files changed
+326 -46

No files matched your search

@@ -127,4 +127,16 @@ public class EhUtils {
return gi.title;
}
}
public static String getSpecifyUploaderKeyword(String query) {
return "uploader:\"" + query + "\"";
}
public static String getKeywordFromSpecifyUploader(String query) {
if (query.startsWith("uploader:\"") && query.endsWith("\"") && query.length() > 11) {
return query.substring(10, query.length() - 1);
} else {
return query;
}
}
}
@@ -242,6 +242,7 @@ public class ListUrlBuilder implements Cloneable, Parcelable {
public ListUrlBuilder() {}
@SuppressWarnings("WrongConstant")
protected ListUrlBuilder(Parcel in) {
mMode = in.readInt();
mPageIndex = in.readInt();
@@ -75,7 +75,11 @@ public final class MainActivity extends StageActivity
}
public void setNavCheckedItem(@IdRes int resId) {
mNavView.setCheckedItem(resId);
if (resId == 0) {
mNavView.setCheckedItem(R.id.nav_stub);
} else {
mNavView.setCheckedItem(resId);
}
}
private void onInit() {
@@ -108,7 +112,9 @@ public final class MainActivity extends StageActivity
int id = item.getItemId();
if (id == R.id.nav_homepage) {
Bundle args = new Bundle();
args.putString(GalleryListScene.KEY_ACTION, GalleryListScene.ACTION_HOMEPAGE);
startScene(GalleryListScene.class, args);
} else if (id == R.id.nav_whats_hot) {
} else if (id == R.id.nav_favourite) {
@@ -121,6 +127,10 @@ public final class MainActivity extends StageActivity
}
if (id != R.id.nav_stub) {
mDrawerLayout.closeDrawers();
}
return true;
}
}
@@ -22,18 +22,23 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ImageSpan;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
import com.hippo.anani.SimpleAnimatorListener;
import com.hippo.drawable.AddDeleteDrawable;
@@ -62,14 +67,24 @@ import com.hippo.widget.LoadImageView;
import com.hippo.widget.OffsetLayout;
import com.hippo.yorozuya.MathUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
public final class GalleryListScene extends BaseScene
implements EasyRecyclerView.OnItemClickListener, SearchBar.Helper,
SearchBar.OnStateChangeListener, FastScroller.OnDragHandlerListener,
SearchLayout.Helper {
SearchLayout.Helper, View.OnClickListener {
@IntDef({STATE_NORMAL, STATE_SIMPLE_SEARCH, STATE_SEARCH, STATE_SEARCH_SHOW_LIST})
@Retention(RetentionPolicy.SOURCE)
private @interface State {}
private static final int BACK_PRESSED_INTERVAL = 2000;
public final static String KEY_ACTION = "action";
public final static String ACTION_HOMEPAGE = "action_homepage";
public final static String ACTION_WHATS_HOT = "action_whats_hot";
public final static String ACTION_SEARCH = "action_search";
public final static String KEY_LIST_URL_BUILDER = "list_url_builder";
@@ -87,6 +102,7 @@ public final class GalleryListScene extends BaseScene
private EasyRecyclerView mRecyclerView;
private SearchLayout mSearchLayout;
private SearchBar mSearchBar;
private FloatingActionButton mFab;
private ViewTransition mViewTransition;
@@ -99,16 +115,47 @@ public final class GalleryListScene extends BaseScene
private SearchBarMoveHelper mSearchBarMoveHelper;
private ListUrlBuilder mUrlBuilder;
@State
private int mState = STATE_NORMAL;
// Double click back exit
private long mPressBackTime = 0;
private Animator.AnimatorListener mFabAnimatorListener = null;
@Override
public int getLaunchMode() {
return LAUNCH_MODE_SINGLE_TOP;
}
@Override
public int getSoftInputMode() {
return WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN |
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
}
private void handleArgs(Bundle args) {
if (args == null) {
return;
}
String action = args.getString(KEY_ACTION);
if (ACTION_HOMEPAGE.equals(action)) {
mUrlBuilder.reset();
} else if (ACTION_WHATS_HOT.equals(action)) {
mUrlBuilder.setMode(ListUrlBuilder.MODE_WHATS_HOT);
} else if (ACTION_SEARCH.equals(action)) {
mUrlBuilder.reset();
// TODO
}
}
@Override
public void onNewArguments(@NonNull Bundle args) {
// TODO
handleArgs(args);
onUpdateUrlBuilder();
mHelper.refresh();
setState(STATE_NORMAL);
}
@Override
@@ -124,17 +171,7 @@ public final class GalleryListScene extends BaseScene
public void onInit() {
mUrlBuilder = new ListUrlBuilder();
Bundle args = getArguments();
if (args != null) {
String action = args.getString(KEY_ACTION);
if (ACTION_HOMEPAGE.equals(action)) {
setNavCheckedItem(R.id.nav_homepage);
} else if (ACTION_WHATS_HOT.equals(action)) {
setNavCheckedItem(R.id.nav_whats_hot);
mUrlBuilder.setMode(ListUrlBuilder.MODE_WHATS_HOT);
}
}
handleArgs(getArguments());
}
private void setSearchBarHint(Context context, SearchBar searchBar) {
@@ -150,18 +187,40 @@ public final class GalleryListScene extends BaseScene
searchBar.setEditTextHint(ssb);
}
private void updateSearchBar() {
// Update search bar title, drawer checked item
private void onUpdateUrlBuilder() {
ListUrlBuilder builder = mUrlBuilder;
SearchBar sb = mSearchBar;
Resources resources = getResources();
switch (builder.getMode()) {
case ListUrlBuilder.MODE_NORMAL:
if (EhUtils.NONE ==builder.getCategory()) {
sb.setTitle(resources.getString(R.string.app_name));
}
break;
// TODO
String keyword = builder.getKeyword();
int category = builder.getCategory();
String title;
if (ListUrlBuilder.MODE_NORMAL == builder.getMode() &&
EhUtils.NONE == category &&
TextUtils.isEmpty(keyword)) {
title = resources.getString(R.string.app_name);
} else if (ListUrlBuilder.MODE_WHATS_HOT == builder.getMode()) {
title = resources.getString(R.string.whats_hot);
} else if (!TextUtils.isEmpty(keyword)) {
title = keyword;
} else if (MathUtils.hammingWeight(category) == 1) {
title = EhUtils.getCategory(category);
} else {
title = resources.getString(R.string.search);
}
mSearchBar.setTitle(title);
int checkedItemId;
if (ListUrlBuilder.MODE_NORMAL == builder.getMode() &&
EhUtils.NONE == category &&
TextUtils.isEmpty(keyword)) {
checkedItemId = R.id.nav_homepage;
} else if (ListUrlBuilder.MODE_WHATS_HOT == builder.getMode()) {
checkedItemId = R.id.nav_whats_hot;
} else {
checkedItemId = 0;
}
setNavCheckedItem(checkedItemId);
}
@Nullable
@@ -177,6 +236,7 @@ public final class GalleryListScene extends BaseScene
mRecyclerView = mContentLayout.getRecyclerView();
mSearchLayout = (SearchLayout) mSearchBarLayout.findViewById(R.id.search_layout);
mSearchBar = (SearchBar) mSearchBarLayout.findViewById(R.id.search_bar);
mFab = (FloatingActionButton) mSearchBarLayout.findViewById(R.id.fab);
mViewTransition = new ViewTransition(mContentLayout, mSearchLayout);
@@ -206,15 +266,19 @@ public final class GalleryListScene extends BaseScene
mSearchBar.setHelper(this);
mSearchBar.setOnStateChangeListener(this);
setSearchBarHint(getContext(), mSearchBar);
updateSearchBar();
mSearchLayout.setHelper(this);
Drawable searchDrawable = VectorDrawable.create(getContext(), R.drawable.ic_magnify_dark);
mFab.setImageDrawable(searchDrawable);
mFab.setOnClickListener(this);
mSearchBarMoveHelper = new SearchBarMoveHelper();
mRecyclerView.addOnScrollListener(mSearchBarMoveHelper);
mSearchLayout.addOnScrollListener(mSearchBarMoveHelper);
// Refresh
onUpdateUrlBuilder();
mHelper.firstRefresh();
return view;
@@ -232,16 +296,78 @@ public final class GalleryListScene extends BaseScene
mUrlBuilder = savedInstanceState.getParcelable(KEY_LIST_URL_BUILDER);
}
@Override
public void onClick(View v) {
if (mFab == v) {
if (mState != STATE_NORMAL) {
mSearchBar.applySearch();
}
}
}
private boolean checkDoubleClickExit() {
if (getStackIndex() != 0) {
return false;
}
long time = System.currentTimeMillis();
if (time - mPressBackTime > BACK_PRESSED_INTERVAL) {
// It is the last scene
mPressBackTime = time;
Toast.makeText(getContext(), R.string.press_twice_exit, Toast.LENGTH_SHORT).show();
return true;
} else {
return false;
}
}
@Override
public boolean onBackPressed() {
switch (mState) {
default:
case STATE_NORMAL:
return checkDoubleClickExit();
case STATE_SIMPLE_SEARCH:
setState(STATE_NORMAL);
return true;
case STATE_SEARCH:
setState(STATE_NORMAL);
return true;
case STATE_SEARCH_SHOW_LIST:
setState(STATE_SEARCH);
return true;
}
}
@Override
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
return false;
}
private void setState(int state) {
private void showFab() {
mFab.setVisibility(View.VISIBLE);
mFab.setScaleX(0.0f);
mFab.setScaleY(0.0f);
mFab.animate().scaleX(1.0f).scaleY(1.0f).setListener(null).setDuration(ANIMATE_TIME).start();
}
private void hideFab() {
if (mFabAnimatorListener == null) {
mFabAnimatorListener = new SimpleAnimatorListener() {
@Override
public void onAnimationEnd(Animator animation) {
mFab.setVisibility(View.GONE);
}
};
}
mFab.animate().scaleX(0.0f).scaleY(0.0f).setListener(mFabAnimatorListener).setDuration(ANIMATE_TIME).start();
}
private void setState(@State int state) {
setState(state, true);
}
private void setState(int state, boolean animation) {
private void setState(@State int state, boolean animation) {
if (mState != state) {
int oldState = mState;
mState = state;
@@ -252,18 +378,21 @@ public final class GalleryListScene extends BaseScene
case STATE_SIMPLE_SEARCH:
mSearchBar.setState(SearchBar.STATE_SEARCH_LIST, animation);
mSearchBarMoveHelper.returnSearchBarPosition();
showFab();
break;
case STATE_SEARCH:
mViewTransition.showView(1, animation);
mSearchLayout.scrollSearchContainerToTop();
mSearchBar.setState(SearchBar.STATE_SEARCH, animation);
mSearchBarMoveHelper.returnSearchBarPosition();
showFab();
break;
case STATE_SEARCH_SHOW_LIST:
mViewTransition.showView(1, animation);
mSearchLayout.scrollSearchContainerToTop();
mSearchBar.setState(SearchBar.STATE_SEARCH_LIST, animation);
mSearchBarMoveHelper.returnSearchBarPosition();
showFab();
break;
}
break;
@@ -272,6 +401,7 @@ public final class GalleryListScene extends BaseScene
case STATE_NORMAL:
mSearchBar.setState(SearchBar.STATE_NORMAL, animation);
mSearchBarMoveHelper.returnSearchBarPosition();
hideFab();
break;
case STATE_SEARCH:
mViewTransition.showView(1, animation);
@@ -293,6 +423,7 @@ public final class GalleryListScene extends BaseScene
mViewTransition.showView(0, animation);
mSearchBar.setState(SearchBar.STATE_NORMAL, animation);
mSearchBarMoveHelper.returnSearchBarPosition();
hideFab();
break;
case STATE_SIMPLE_SEARCH:
mViewTransition.showView(0, animation);
@@ -311,6 +442,7 @@ public final class GalleryListScene extends BaseScene
mViewTransition.showView(0, animation);
mSearchBar.setState(SearchBar.STATE_NORMAL, animation);
mSearchBarMoveHelper.returnSearchBarPosition();
hideFab();
break;
case STATE_SIMPLE_SEARCH:
mViewTransition.showView(0, animation);
@@ -362,12 +494,19 @@ public final class GalleryListScene extends BaseScene
@Override
public void onApplySearch(String query) {
if (mState == STATE_SEARCH || mState == STATE_SEARCH_SHOW_LIST) {
mSearchLayout.formatListUrlBuilder(mUrlBuilder, query);
} else {
mUrlBuilder.reset();
}
onUpdateUrlBuilder();
mHelper.refresh();
setState(STATE_NORMAL);
}
@Override
public void onSearchEditTextBackPressed() {
setState(STATE_NORMAL);
onBackPressed();
}
@Override
@@ -678,11 +817,13 @@ public final class GalleryListScene extends BaseScene
public void onSuccess(GalleryListParser.Result result) {
mHelper.setPages(mTaskId, result.pages);
mHelper.onGetPageData(mTaskId, result.galleryInfos);
mSearchBarMoveHelper.returnSearchBarPosition();
}
@Override
public void onFailure(Exception e) {
mHelper.onGetExpection(mTaskId, e);
mSearchBarMoveHelper.returnSearchBarPosition();
}
@Override
@@ -27,6 +27,7 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
@@ -61,6 +62,12 @@ public final class LoginScene extends BaseScene implements EditText.OnEditorActi
private EhCookieStore mCookieStore;
private EhRequest mSignInRequest;
@Override
public int getSoftInputMode() {
return WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE |
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -207,6 +207,14 @@ public class SearchBar extends CardView implements View.OnClickListener,
mEditText.setLayoutParams(lp);
}
public void applySearch() {
String query = mEditText.getText().toString().trim();
// Put it into db
mSearchDatabase.addQuery(query);
// Callback
mHelper.onApplySearch(query);
}
@Override
public void onClick(View v) {
if (v == mTitleTextView) {
@@ -222,8 +230,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (v == mEditText) {
if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_NULL) {
String query = mEditText.getText().toString();
mHelper.onApplySearch(query);
applySearch();
return true;
}
}
@@ -16,7 +16,6 @@
package com.hippo.ehviewer.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
@@ -41,6 +40,9 @@ import android.widget.TextView;
import com.hippo.easyrecyclerview.EasyRecyclerView;
import com.hippo.easyrecyclerview.MarginItemDecoration;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.client.EhUrl;
import com.hippo.ehviewer.client.EhUtils;
import com.hippo.ehviewer.client.data.ListUrlBuilder;
import com.hippo.rippleold.RippleSalon;
import com.hippo.widget.SimpleImageView;
import com.hippo.yorozuya.ViewUtils;
@@ -95,8 +97,6 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
private AdvanceSearchTable mTableAdvanceSearch;
private View mActionView;
private TextView mAction1;
private TextView mAction2;
private LinearLayoutManager mLayoutManager;
private SearchAdapter mAdapter;
@@ -113,7 +113,6 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
init(context);
}
@SuppressLint("InflateParams")
private void init(Context context) {
Resources resources = context.getResources();
mInflater = LayoutInflater.from(context);
@@ -149,13 +148,11 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
mEnableAdvanceSwitch.setSwitchPadding(resources.getDimensionPixelSize(R.dimen.switch_padding));
// Create advance view
mAdvanceView = mInflater.inflate(R.layout.search_advance, null);
mAdvanceView = mInflater.inflate(R.layout.search_advance, frameLayout, false);
mTableAdvanceSearch = (AdvanceSearchTable) mAdvanceView.findViewById(R.id.search_advance_search_table);
// Create action view
mActionView = mInflater.inflate(R.layout.search_action, null);
mAction1 = (TextView) mActionView.findViewById(R.id.search_action_1);
mAction2 = (TextView) mActionView.findViewById(R.id.search_action_2);
mActionView = new View(context);// TODO mInflater.inflate(R.layout.search_action, frameLayout, false);
}
public void setHelper(Helper helper) {
@@ -221,6 +218,33 @@ public class SearchLayout extends EasyRecyclerView implements CompoundButton.OnC
}
}
// TODO image search
public void formatListUrlBuilder(ListUrlBuilder urlBuilder, String query) {
urlBuilder.reset();
int nsMode = mNormalSearchMode.getCheckedRadioButtonId();
switch (nsMode) {
default:
case R.id.search_normal_search:
case R.id.search_specify_uploader:
if (nsMode == R.id.search_specify_uploader) {
urlBuilder.setKeyword(EhUtils.getSpecifyUploaderKeyword(query));
} else {
urlBuilder.setKeyword(query);
}
urlBuilder.setCategory(mCategoryTable.getCategory());
if (mEnableAdvance) {
urlBuilder.setAdvanceSearch(mTableAdvanceSearch.getAdvanceSearch());
urlBuilder.setMinRating(mTableAdvanceSearch.getMinRating());
}
break;
case R.id.search_specify_tag:
urlBuilder.setMode(ListUrlBuilder.MODE_TAG);
urlBuilder.setKeyword(query);
break;
}
}
public void setSearchMode(@SearchMode int searchMode, boolean animation) {
if (mSearchMode != searchMode) {
int oldItemCount = mAdapter.getItemCount();
@@ -39,6 +39,11 @@ public class SceneFragment extends Fragment {
return LAUNCH_MODE_STANDARD;
}
public int getSoftInputMode() {
return 0; // WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED |
// WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED
}
public void onNewArguments(@NonNull Bundle args) {}
public <T extends SceneFragment> void startScene(Class<T> clazz) {
@@ -66,6 +71,18 @@ public class SceneFragment extends Fragment {
}
}
/**
* @return negative for error
*/
public int getStackIndex() {
FragmentActivity activity = getActivity();
if (activity instanceof StageActivity) {
return ((StageActivity) activity).getStackIndex(this);
} else {
return -1;
}
}
/**
* @return true for handle this back pressed action
*/
@@ -100,13 +100,23 @@ public abstract class StageActivity extends AppCompatActivity {
}
transaction.add(getContainerViewId(), scene, newTag);
transaction.commit();
// Update SoftInputMode
getWindow().setSoftInputMode(scene.getSoftInputMode());
}
int getStackIndex(SceneFragment scene) {
return getStackIndex(scene.getTag());
}
int getStackIndex(String tag) {
return Collections.binarySearch(mSceneTagList, tag);
}
public void finishScene(SceneFragment scene) {
finishScene(scene.getTag());
}
private void finishScene(String tag) {
FragmentManager fragmentManager = getSupportFragmentManager();