Update
This commit is contained in:
1 parent
4ef644837f
commit
a5bcad9296
15 files changed
+429
-45
No files matched your search
@@ -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
|
||||
|
||||
@@ -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/");
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<GalleryInfo> 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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<E, VH extends RecyclerView.ViewHolder>
|
||||
extends EasyRecyclerView.Adapter<VH>
|
||||
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<E> 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<E> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user