diff --git a/app/src/main/java/com/hippo/ehviewer/EhApplication.java b/app/src/main/java/com/hippo/ehviewer/EhApplication.java index c35a6b2b7..003b38dc8 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhApplication.java +++ b/app/src/main/java/com/hippo/ehviewer/EhApplication.java @@ -19,6 +19,7 @@ import android.content.Context; import com.facebook.drawee.backends.pipeline.Fresco; import com.hippo.content.VectorContext; +import com.hippo.ehviewer.util.Config; import com.hippo.scene.SceneApplication; import com.hippo.util.Log; @@ -29,6 +30,7 @@ public class EhApplication extends SceneApplication { super.onCreate(); Fresco.initialize(this); + Config.initialize(this); } @Override diff --git a/app/src/main/java/com/hippo/ehviewer/data/ListUrlBuilder.java b/app/src/main/java/com/hippo/ehviewer/data/ListUrlBuilder.java index 32fb033d7..b5b914ff6 100644 --- a/app/src/main/java/com/hippo/ehviewer/data/ListUrlBuilder.java +++ b/app/src/main/java/com/hippo/ehviewer/data/ListUrlBuilder.java @@ -48,6 +48,18 @@ public class ListUrlBuilder { private int mAdvanceSearch = -1; private int mMinRating = -1; + /** + * Make this ListUrlBuilder point to homepage + */ + public void reset() { + mMode = MODE_NORMAL; + mPageIndex = 0; + mCategory = EhUtils.NONE; + mKeyword = null; + mAdvanceSearch = -1; + mMinRating = -1; + } + public int getMode() { return mMode; } @@ -109,7 +121,7 @@ public class ListUrlBuilder { mMinRating = glub.mMinRating; } - public String build(int source) throws UnsupportedSearch { + public String build(int source) throws UnsupportedSearchException { switch (mMode) { default: case MODE_NORMAL: @@ -168,7 +180,7 @@ public class ListUrlBuilder { } case MODE_TAG: { if (source == EhClient.SOURCE_LOFI) { - throw new UnsupportedSearch("Lofi do not support tag search"); + throw new UnsupportedSearchException("Lofi do not support tag search"); } StringBuilder sb = new StringBuilder(EhClient.getUrlHeader(source)); sb.append("tag/"); diff --git a/app/src/main/java/com/hippo/ehviewer/data/UnsupportedSearch.java b/app/src/main/java/com/hippo/ehviewer/data/UnsupportedSearchException.java similarity index 83% rename from app/src/main/java/com/hippo/ehviewer/data/UnsupportedSearch.java rename to app/src/main/java/com/hippo/ehviewer/data/UnsupportedSearchException.java index c260cf71d..13fc897a7 100644 --- a/app/src/main/java/com/hippo/ehviewer/data/UnsupportedSearch.java +++ b/app/src/main/java/com/hippo/ehviewer/data/UnsupportedSearchException.java @@ -15,9 +15,9 @@ package com.hippo.ehviewer.data; -public class UnsupportedSearch extends Exception { +public class UnsupportedSearchException extends Exception { - public UnsupportedSearch(String detailMessage) { + public UnsupportedSearchException(String detailMessage) { super(detailMessage); } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java index 661283eb1..f33968249 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/ContentActivity.java @@ -26,6 +26,7 @@ import android.view.Gravity; import com.hippo.content.VectorContext; import com.hippo.ehviewer.R; import com.hippo.ehviewer.ui.scene.GalleryListScene; +import com.hippo.ehviewer.util.Config; import com.hippo.ehviewer.widget.StatusBarLayout; import com.hippo.scene.StageActivity; import com.hippo.scene.StageLayout; @@ -41,7 +42,7 @@ public class ContentActivity extends StageActivity @Override protected boolean isShowStats() { - return true; + return Config.getShowApplicationStats(); } @Override diff --git a/app/src/main/java/com/hippo/ehviewer/ui/StartActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/StartActivity.java index 89a57eacd..0c843d2b9 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/StartActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/StartActivity.java @@ -22,6 +22,7 @@ import android.widget.TextView; import com.hippo.app.StatsActivity; import com.hippo.ehviewer.R; +import com.hippo.ehviewer.util.Config; import com.hippo.util.ViewUtils; import com.larvalabs.svgandroid.SVG; import com.larvalabs.svgandroid.SVGBuilder; @@ -33,7 +34,7 @@ public class StartActivity extends StatsActivity { @Override protected boolean isShowStats() { - return true; + return Config.getShowApplicationStats(); } @Override diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java index a20a47f10..44d7d2ae5 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java @@ -19,6 +19,7 @@ import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; +import android.content.Context; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.net.Uri; @@ -28,12 +29,17 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; import android.util.SparseArray; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; import android.widget.TextView; +import android.widget.Toast; import com.facebook.drawee.view.SimpleDraweeView; import com.hippo.animation.SimpleAnimatorListener; @@ -43,6 +49,8 @@ import com.hippo.ehviewer.R; import com.hippo.ehviewer.client.EhClient; import com.hippo.ehviewer.client.ListParser; import com.hippo.ehviewer.data.GalleryInfo; +import com.hippo.ehviewer.data.ListUrlBuilder; +import com.hippo.ehviewer.data.UnsupportedSearchException; import com.hippo.ehviewer.ui.ContentActivity; import com.hippo.ehviewer.util.EhUtils; import com.hippo.ehviewer.widget.ContentLayout; @@ -52,7 +60,9 @@ import com.hippo.ehviewer.widget.SearchBar; import com.hippo.ehviewer.widget.SearchDatabase; import com.hippo.ehviewer.widget.SearchLayout; import com.hippo.scene.Scene; +import com.hippo.scene.SimpleDialog; import com.hippo.util.AnimationUtils; +import com.hippo.util.AppHandler; import com.hippo.util.AssertUtils; import com.hippo.util.Log; import com.hippo.util.MathUtils; @@ -62,6 +72,7 @@ import com.hippo.widget.FloatingActionButton; import java.util.List; +// TODO remeber the data in ContentHelper after screen dirction change // TODO Must refresh when change source // TODO disable click action when animating public class GalleryListScene extends Scene implements SearchBar.Helper, @@ -106,6 +117,68 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, private int mState = STATE_NORMAL; private int mFabState = FAB_STATE_NORMAL; + private ListUrlBuilder mListUrlBuilder = new ListUrlBuilder(); + + private SimpleDialog.OnCreateCustomViewListener mGoToCreateCustomViewListener = + new SimpleDialog.OnCreateCustomViewListener() { + @Override + public void onCreateCustomView(final SimpleDialog dialog, View view) { + int currentPage = mGalleryListHelper.getCurrentPage(); + int pageSize = mGalleryListHelper.getPageSize(); + TextView pageInfo = (TextView) view.findViewById(R.id.go_to_page_info); + pageInfo.setText(String.format(mResources.getString(R.string.go_to_page_info), + currentPage + 1, pageSize == Integer.MAX_VALUE ? + mResources.getString(R.string.unknown).toLowerCase() : Integer.toString(pageSize))); + + EditText goToPage = (EditText) view.findViewById(R.id.go_to_page); + goToPage.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEARCH || actionId == EditorInfo.IME_NULL) { + dialog.pressPositiveButton(); + return true; + } + return false; + } + }); + } + }; + + private SimpleDialog.OnButtonClickListener mGoToButtonClickListener = + new SimpleDialog.OnButtonClickListener() { + @Override + public boolean onClick(SimpleDialog dialog, int which) { + if (which == SimpleDialog.POSITIVE) { + int targetPage; + EditText goToPage = (EditText) dialog.findViewById(R.id.go_to_page); + try { + String text = goToPage.getText().toString(); + if (TextUtils.isEmpty(text)) { + Toast.makeText(mActivity, R.string.go_to_error_null, + Toast.LENGTH_SHORT).show(); + return false; + } + targetPage = Integer.parseInt(text); + int pageSize = mGalleryListHelper.getPageSize(); + if (targetPage <= 0 || (targetPage > pageSize)) { + Toast.makeText(mActivity, R.string.go_to_error_invaild, + Toast.LENGTH_SHORT).show(); + return false; + } else { + mGalleryListHelper.goTo(targetPage - 1); + return true; + } + } catch (NumberFormatException e) { + Toast.makeText(mActivity, R.string.go_to_error_not_number, + Toast.LENGTH_SHORT).show(); + return false; + } + } else { + return true; + } + } + }; + @SuppressWarnings("deprecation") @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -141,7 +214,8 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, ViewUtils.removeOnGlobalLayoutListener(mSearchBar.getViewTreeObserver(), this); mSearchBarOriginalTop = mSearchBar.getTop(); mSearchBarOriginalBottom = mSearchBar.getBottom(); - int fitPaddingTop = mSearchBar.getHeight() + mResources.getDimensionPixelOffset(R.dimen.search_bar_padding_vertical); + int fitPaddingTop = mSearchBar.getHeight() + + mResources.getDimensionPixelOffset(R.dimen.search_bar_padding_vertical); mContentLayout.setFitPaddingTop(fitPaddingTop); mSearchLayout.setFitPaddingTop(fitPaddingTop); } @@ -149,7 +223,12 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, mSearchLayout.setHelper(this); // Content Layout - mGalleryListHelper = new GalleryListHelper(); + if (mGalleryListHelper != null) { + mGalleryListHelper = mGalleryListHelper.newInstance(mActivity); + } else { + mGalleryListHelper = new GalleryListHelper(mActivity); + } + mContentLayout.setHelper(mGalleryListHelper); // Fab Layout @@ -277,6 +356,16 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, mAddDeleteDrawable.setShape(mFabLayout.isExpanded(), ANIMATE_TIME); } + public void showGoToDialog() { + int[] center = new int[2]; + ViewUtils.getCenterInAncestor(mGoToFab, center, R.id.stage); + new SimpleDialog.Builder(mActivity).setTitle(R.string._goto) + .setCustomView(R.layout.dialog_go_to, mGoToCreateCustomViewListener) + .setOnButtonClickListener(mGoToButtonClickListener) + .setPositiveButton(android.R.string.ok) + .setStartPoint(center[0], center[1]).show(); + } + @Override public void onClick(View v) { if (v == mCornerFab) { @@ -290,7 +379,9 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, mGalleryListHelper.refreshWithSameSearch(); } else if (v == mGoToFab) { toggleFabLayout(); - // TODO do go to + if (mGalleryListHelper.canGoTo()) { + showGoToDialog(); + } } } @@ -424,16 +515,19 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, } if (offset != 0) { + final boolean needRequestLayout = mSearchBar.getBottom() <= 0 && offset > 0; final ValueAnimator va = ValueAnimator.ofInt(0, offset); va.setDuration(ANIMATE_TIME); va.addListener(new SimpleAnimatorListener() { @Override - public void onAnimationEnd(Animator animation) { + public void onAnimationEnd(Animator animation, boolean canceled) { + super.onAnimationEnd(animation, canceled); mSearchBarMoveAnimator = null; } }); va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { int lastValue; + boolean hasRequestLayout; @Override public void onAnimationUpdate(ValueAnimator animation) { int value = (Integer) animation.getAnimatedValue(); @@ -441,6 +535,11 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, lastValue = value; mSearchBar.offsetTopAndBottom(offsetStep); ((OffsetLayout.LayoutParams) mSearchBar.getLayoutParams()).offsetY += offsetStep; + + if (!hasRequestLayout && needRequestLayout && mSearchBar.getBottom() > 0) { + hasRequestLayout = true; + mSearchBar.requestLayout(); + } } }); if (mSearchBarMoveAnimator != null) { @@ -482,9 +581,9 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, ((OffsetLayout.LayoutParams) mSearchBar.getLayoutParams()).offsetY += offsetYStep; int newBottom = mSearchBar.getBottom(); - // TODO Sometimes if it is out of screen than go into again, it do not show, + // Sometimes if it is out of screen than go into again, it do not show, // so I need to requestLayout - if (oldBottom == 0 && newBottom > 0) { + if (oldBottom <= 0 && newBottom > 0) { mSearchBar.requestLayout(); } } @@ -522,8 +621,28 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, private LayoutInflater mInflater; - public GalleryListHelper() { - super(); + private Runnable mSearchBarPositionTask = new Runnable() { + @Override + public void run() { + returnSearchBarPosition(); + } + }; + + public GalleryListHelper(Context context) { + super(context); + init(); + } + + private GalleryListHelper(Context context, List data) { + super(context, data); + init(); + } + + public GalleryListHelper newInstance(Context context) { + return new GalleryListHelper(context, getData()); + } + + private void init() { mInflater = mActivity.getLayoutInflater(); } @@ -534,10 +653,23 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, //return new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL); } + @Override + protected void onScrollToPosition() { + AppHandler.getInstance().post(mSearchBarPositionTask); + } + @Override protected void getPageData(int taskId, int type, int page) { - GalleryListListener listener = new GalleryListListener(taskId, type, page, EhClient.SOURCE_LOFI); - EhClient.getInstance().getGalleryList(EhClient.SOURCE_LOFI, "http://lofi.e-hentai.org/", listener); + try { + mListUrlBuilder.setPageIndex(page); + String url = mListUrlBuilder.build(EhClient.SOURCE_LOFI); + GalleryListListener listener = new GalleryListListener(taskId, type, + page, EhClient.SOURCE_LOFI); + EhClient.getInstance().getGalleryList(EhClient.SOURCE_LOFI, + url, listener); + } catch (UnsupportedSearchException e) { + onGetPageData(taskId, e); + } } @Override diff --git a/app/src/main/java/com/hippo/ehviewer/util/Config.java b/app/src/main/java/com/hippo/ehviewer/util/Config.java new file mode 100644 index 000000000..2916fd60b --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/util/Config.java @@ -0,0 +1,87 @@ +/* + * 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.util; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +import com.hippo.ehviewer.BuildConfig; + +public final class Config { + + private static SharedPreferences sConfigPre; + + private Config() { + } + + public static void initialize(Context context) { + sConfigPre = PreferenceManager.getDefaultSharedPreferences(context); + } + + public static boolean getBoolean(String key, boolean defValue) { + return sConfigPre.getBoolean(key, defValue); + } + + public static void putBoolean(String key, boolean value) { + sConfigPre.edit().putBoolean(key, value).apply(); + } + + public static int getInt(String key, int defValue) { + return sConfigPre.getInt(key, defValue); + } + + public static void putInt(String key, int value) { + sConfigPre.edit().putInt(key, value).apply(); + } + + public static long getLong(String key, long defValue) { + return sConfigPre.getLong(key, defValue); + } + + public static void putLong(String key, long value) { + sConfigPre.edit().putLong(key, value).apply(); + } + + public static float getFloat(String key, float defValue) { + return sConfigPre.getFloat(key, defValue); + } + + public static void putFloat(String key, float value) { + sConfigPre.edit().putFloat(key, value).apply(); + } + + public static String getString(String key, String defValue) { + return sConfigPre.getString(key, defValue); + } + + public static void putString(String key, String value) { + sConfigPre.edit().putString(key, value).apply(); + } + + /****** Advance ******/ + + private static final String KEY_SHOW_APPLICATION_STATS = "show_application_stats"; + private static final boolean DEFAULT_SHOW_APPLICATION_STATS = BuildConfig.DEBUG; + + public static boolean getShowApplicationStats() { + return getBoolean(KEY_SHOW_APPLICATION_STATS, DEFAULT_SHOW_APPLICATION_STATS); + } + + public static void putShowApplicationStats(boolean value) { + putBoolean(KEY_SHOW_APPLICATION_STATS, value); + } +} diff --git a/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java b/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java index 4858584a1..643d75033 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java @@ -16,6 +16,8 @@ package com.hippo.ehviewer.widget; import android.content.Context; +import android.os.Bundle; +import android.os.Parcelable; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.LayoutInflater; @@ -27,6 +29,7 @@ import android.widget.TextView; import com.hippo.effect.ViewTransition; import com.hippo.ehviewer.R; +import com.hippo.util.AssertUtils; import com.hippo.util.IntIdGenerator; import com.hippo.util.LayoutManagerUtils; import com.hippo.util.UiUtils; @@ -47,6 +50,8 @@ public class ContentLayout extends FrameLayout { private TextView mTextView; private Snackbar mSnackbar; + private ContentHelper mContentHelper; + private int mRecyclerViewOriginTop; private int mRecyclerViewOriginBottom; private int mSnackbarOriginBottom; @@ -83,12 +88,6 @@ public class ContentLayout extends FrameLayout { // Snackbar mSnackbarOriginBottom = mSnackbar.getPaddingBottom(); - mSnackbar.setAction(context.getString(R.string.retry), new View.OnClickListener() { - @Override - public void onClick(View v) { - // TODO - } - }); } public EasyRecyclerView getRecyclerView() { @@ -96,6 +95,7 @@ public class ContentLayout extends FrameLayout { } public void setHelper(ContentHelper helper) { + mContentHelper = helper; helper.init(this); } @@ -115,10 +115,25 @@ public class ContentLayout extends FrameLayout { mSnackbar.setPadding(mSnackbar.getPaddingLeft(), mSnackbar.getPaddingTop(), mSnackbar.getPaddingRight(), mSnackbarOriginBottom + fitPaddingBottom); } + @Override + public Parcelable onSaveInstanceState() { + return mContentHelper.onSaveInstanceState(super.onSaveInstanceState()); + } + + @Override + public void onRestoreInstanceState(Parcelable state) { + super.onRestoreInstanceState(mContentHelper.onRestoreInstanceState(state)); + } + public abstract static class ContentHelper extends EasyRecyclerView.Adapter implements RefreshLayout.OnHeaderRefreshListener, - RefreshLayout.OnFooterRefreshListener { + RefreshLayout.OnFooterRefreshListener, View.OnClickListener { + + private static final String STATE_KEY_SUPER = "super"; + private static final String STATE_KEY_SHOWN_VIEW = "shown_view"; + private static final String STATE_KEY_RECYCLER_VIEW = "recycler_view"; + private static final String STATE_KEY_TIP_MESSAGE = "tip_message"; public static final int TYPE_REFRESH = 0; public static final int TYPE_PRE_PAGE = 1; @@ -127,6 +142,8 @@ public class ContentLayout extends FrameLayout { public static final int TYPE_NEXT_PAGE_KEEP_POS = 4; public static final int TYPE_SOMEWHERE = 5; + private Context mContext; + private ProgressBar mProgressBar; private ViewGroup mTipView; private RefreshLayout mRefreshLayout; @@ -168,6 +185,7 @@ public class ContentLayout extends FrameLayout { private int mCurrentPage; private int mPageVolume; + // TODO save mCurrentTaskId mCurrentTaskType mCurrentTaskPage private int mCurrentTaskId; private int mCurrentTaskType; private int mCurrentTaskPage; @@ -204,11 +222,17 @@ public class ContentLayout extends FrameLayout { } }; - public ContentHelper() { + public ContentHelper(Context context) { + mContext = context; mData = new ArrayList<>(); mIdGenerator = IntIdGenerator.create(); } + protected ContentHelper(Context context, List data) { + this(context); + mData.addAll(data); + } + private void init(ContentLayout contentLayout) { mProgressBar = contentLayout.mProgressBar; mTipView = contentLayout.mTipView; @@ -227,10 +251,19 @@ public class ContentLayout extends FrameLayout { mRecyclerView.addOnScrollListener(mOnScrollListener); mRefreshLayout.setOnHeaderRefreshListener(this); mRefreshLayout.setOnFooterRefreshListener(this); + + mTipView.setOnClickListener(this); + mSnackbar.setAction(mContext.getString(R.string.retry), this); + } + + protected List getData() { + return mData; } protected abstract RecyclerView.LayoutManager generateLayoutManager(); + protected abstract void onScrollToPosition(); + public void showContent() { mViewTransition.showView(0); } @@ -272,6 +305,10 @@ public class ContentLayout extends FrameLayout { return mPageSize; } + public int getCurrentPage() { + return mCurrentPage; + } + public void resetPageSize() { mPageSize = Integer.MAX_VALUE; } @@ -295,6 +332,7 @@ public class ContentLayout extends FrameLayout { mRecyclerView.stopScroll(); LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, 0, 0); + onScrollToPosition(); break; case TYPE_PRE_PAGE: case TYPE_PRE_PAGE_KEEP_POS: @@ -313,6 +351,7 @@ public class ContentLayout extends FrameLayout { mRecyclerView.stopScroll(); LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, 0, 0); + onScrollToPosition(); } break; case TYPE_NEXT_PAGE: @@ -329,6 +368,7 @@ public class ContentLayout extends FrameLayout { mRecyclerView.stopScroll(); LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, mFirstIndex, 0); + onScrollToPosition(); } break; case TYPE_SOMEWHERE: @@ -344,6 +384,7 @@ public class ContentLayout extends FrameLayout { mRecyclerView.stopScroll(); LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, 0, 0); + onScrollToPosition(); break; } } @@ -385,6 +426,13 @@ public class ContentLayout extends FrameLayout { } } + @Override + public void onClick(View v) { + if (v == mTipView) { + refreshWithSameSearch(); + } + } + private void doRefresh() { mCurrentTaskId = mIdGenerator.nextId(); mCurrentTaskType = TYPE_REFRESH; @@ -421,20 +469,12 @@ public class ContentLayout extends FrameLayout { } } - /** - * Only work when data is loaded - */ - public void goToTopAndRefresh() { - if (mViewTransition.getShownViewIndex() == 0 && - !mRefreshLayout.isRefreshing()) { - // Go to top - mRecyclerView.stopScroll(); - mLayoutManager.smoothScrollToPosition(mRecyclerView, null, 0); - // Show header refresh - mRefreshLayout.setHeaderRefreshing(true); - // Do refresh - doRefresh(); - } + public void cancelCurrentTask() { + mCurrentTaskId = mIdGenerator.nextId(); + } + + public boolean canGoTo() { + return mViewTransition.getShownViewIndex() == 0; } /** @@ -444,23 +484,35 @@ public class ContentLayout extends FrameLayout { if (page < 0 || page >= mPageSize) { throw new IndexOutOfBoundsException("Page size is " + mPageSize + ", page is " + page); } else if (page >= mFirstPage && page < mLastPage) { + cancelCurrentTask(); + mCurrentPage = page; mFirstIndex = mPageVolume * (page - mFirstPage); mLastIndex = mFirstIndex + mPageVolume; int position = mFirstIndex; mRecyclerView.stopScroll(); LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, position, 0); + onScrollToPosition(); } else if (page == mFirstPage - 1) { + mRefreshLayout.setFooterRefreshing(false); + mRefreshLayout.setHeaderRefreshing(true); + mCurrentTaskId = mIdGenerator.nextId(); mCurrentTaskType = TYPE_PRE_PAGE; mCurrentTaskPage = page; getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage); } else if (page == mLastPage) { + mRefreshLayout.setFooterRefreshing(false); + mRefreshLayout.setHeaderRefreshing(true); + mCurrentTaskId = mIdGenerator.nextId(); mCurrentTaskType = TYPE_NEXT_PAGE; mCurrentTaskPage = page; getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage); } else { + mRefreshLayout.setFooterRefreshing(false); + mRefreshLayout.setHeaderRefreshing(true); + mCurrentTaskId = mIdGenerator.nextId(); mCurrentTaskType = TYPE_SOMEWHERE; mCurrentTaskPage = page; @@ -478,11 +530,30 @@ public class ContentLayout extends FrameLayout { mLastIndex = mPageVolume; mRecyclerView.stopScroll(); LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, 0, 0); + onScrollToPosition(); } @Override public int getItemCount() { return mData.size(); } + + protected Parcelable onSaveInstanceState(Parcelable superParcelable) { + final Bundle state = new Bundle(); + state.putParcelable(STATE_KEY_SUPER, superParcelable); + state.putInt(STATE_KEY_SHOWN_VIEW, mViewTransition.getShownViewIndex()); + state.putParcelable(STATE_KEY_RECYCLER_VIEW, mRecyclerView.onSaveInstanceState()); + state.putString(STATE_KEY_TIP_MESSAGE, mTextView.getText().toString()); + return state; + } + + protected Parcelable onRestoreInstanceState(Parcelable state) { + AssertUtils.assertInstanceof("state must be Bundle", state, Bundle.class); + final Bundle savedState = (Bundle) state; + mViewTransition.showView(savedState.getInt(STATE_KEY_SHOWN_VIEW), false); + mRecyclerView.onRestoreInstanceState(savedState.getParcelable(STATE_KEY_RECYCLER_VIEW)); + mTextView.setText(savedState.getString(STATE_KEY_TIP_MESSAGE)); + return savedState.getParcelable(STATE_KEY_SUPER); + } } } diff --git a/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java b/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java index 7e2245b9f..bdc9bface 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/SearchLayout.java @@ -266,12 +266,11 @@ public class SearchLayout extends MonoRecyclerView implements CompoundButton.OnC } else if (v == mAction2) { toggleSearchMode(); } else if (v == mSearchTagHelp) { - int[] location = new int [2]; - ViewUtils.getLocationInAncestor(mSearchTagHelp, location, R.id.stage); + int[] center = new int [2]; + ViewUtils.getCenterInAncestor(mSearchTagHelp, center, R.id.stage); new SimpleDialog.Builder(getContext()).setTitle(R.string.search_specify_tag) .setMessage(R.string.search_tag_help) - .setStartPoint(location[0] + mSearchTagHelp.getWidth() / 2, - location[1] + mSearchTagHelp.getHeight() / 2).show(); + .setStartPoint(center[0], center[1]).show(); } } diff --git a/app/src/main/res/layout/dialog_go_to.xml b/app/src/main/res/layout/dialog_go_to.xml new file mode 100644 index 000000000..e81a5e720 --- /dev/null +++ b/app/src/main/res/layout/dialog_go_to.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_gallery_list_detail.xml b/app/src/main/res/layout/item_gallery_list_detail.xml index da7dcad30..3ebe76094 100644 --- a/app/src/main/res/layout/item_gallery_list_detail.xml +++ b/app/src/main/res/layout/item_gallery_list_detail.xml @@ -28,7 +28,8 @@ + android:layout_height="@dimen/list_thumb_height" + auto:actualImageScaleType="fitCenter"/> + + diff --git a/app/src/main/res/layout/widget_content_layout.xml b/app/src/main/res/layout/widget_content_layout.xml index acc7ffd70..5ed02ad76 100644 --- a/app/src/main/res/layout/widget_content_layout.xml +++ b/app/src/main/res/layout/widget_content_layout.xml @@ -53,7 +53,6 @@ android:layout_height="match_parent"> 4 星 5 星 + + 第 %1$d 页,共 %2$s 页 + 跳至 + 请输入目标页面 + 请输入数字 + 当前页面无效 关键字 搜索 + 重试 + 跳页 + 未知 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 17f6d31a3..94883f073 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,7 +31,6 @@ COSPLAY ASIAN PORN MISC - UNKNOWN Search %s @@ -74,9 +73,17 @@ 4 stars 5 stars + + Page %1$d, %2$s pages in total + Go to + Please enter target page + Please enter a number + The page is invaild Keyword Search Retry + Go to + Unknown