Update ContentLayout
This commit is contained in:
1 parent
8da847ebc8
commit
755354a8fe
14 files changed
+451
-54
No files matched your search
@@ -23,6 +23,7 @@ import com.hippo.ehviewer.network.EhHttpHelper;
|
||||
import com.hippo.network.ResponseCodeException;
|
||||
import com.hippo.util.PriorityThreadFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
@@ -107,7 +108,7 @@ public final class EhClient {
|
||||
}
|
||||
|
||||
public abstract static class OnGetGalleryListListener implements EhClientListener {
|
||||
public abstract void onSuccess(GalleryInfo[] glArray, int pageNum);
|
||||
public abstract void onSuccess(List<GalleryInfo> glArray, int pageNum);
|
||||
}
|
||||
|
||||
private void doBgJob(BgJobHelper bjh) {
|
||||
@@ -182,7 +183,7 @@ public final class EhClient {
|
||||
|
||||
ListParser parser = new ListParser();
|
||||
parser.parse(body, source);
|
||||
return new Object[]{parser.giArray, parser.pageNum};
|
||||
return new Object[]{parser.giList, parser.pageNum};
|
||||
}
|
||||
|
||||
private final class GetGalleryListHelper extends SimpleBgJobHelper {
|
||||
@@ -191,7 +192,7 @@ public final class EhClient {
|
||||
private String mUrl;
|
||||
private OnGetGalleryListListener mListener;
|
||||
|
||||
private GalleryInfo[] mGlArray;
|
||||
private List<GalleryInfo> mGlList;
|
||||
private int mPageNum;
|
||||
|
||||
public GetGalleryListHelper(int source, String url, OnGetGalleryListListener listener) {
|
||||
@@ -204,13 +205,13 @@ public final class EhClient {
|
||||
@Override
|
||||
public void doBgJob() throws Exception {
|
||||
Object[] objs = doGetGalleryList(mSource, mUrl);
|
||||
mGlArray = (GalleryInfo[]) objs[0];
|
||||
mGlList = (List<GalleryInfo>) objs[0];
|
||||
mPageNum = (int) objs[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSuccessCallback() {
|
||||
mListener.onSuccess(mGlArray, mPageNum);
|
||||
mListener.onSuccess(mGlList, mPageNum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public class ListParser {
|
||||
*/
|
||||
public int pageNum;
|
||||
|
||||
public GalleryInfo[] giArray;
|
||||
public List<GalleryInfo> giList;
|
||||
|
||||
private void parse(String body) throws EhException {
|
||||
Pattern p;
|
||||
@@ -61,7 +61,7 @@ public class ListParser {
|
||||
}
|
||||
|
||||
// Get gallery
|
||||
List<GalleryInfo> giList = new ArrayList<>(DEFAULT_LIST_SIZE);
|
||||
giList = new ArrayList<>(DEFAULT_LIST_SIZE);
|
||||
|
||||
p = Pattern.compile("<td class=\"itdc\">(?:<a.+?>)?<img.+?alt=\"(.+?)\".+?/>(?:</a>)?</td>" // category
|
||||
+ "<td.+?>(.+?)</td>" // posted
|
||||
@@ -113,8 +113,6 @@ public class ListParser {
|
||||
if (giList.size() == 0) {
|
||||
throw new EhException(PARSE_MESSAGE);
|
||||
}
|
||||
|
||||
giArray = giList.toArray(new GalleryInfo[giList.size()]);
|
||||
}
|
||||
|
||||
private void parseLofi(String body) throws Exception {
|
||||
@@ -122,7 +120,7 @@ public class ListParser {
|
||||
Matcher m;
|
||||
|
||||
// Get gallery
|
||||
List<LofiGalleryInfo> lgiList = new ArrayList<>(DEFAULT_LIST_SIZE);
|
||||
giList = new ArrayList<>(DEFAULT_LIST_SIZE);
|
||||
p = Pattern.compile("<td class=\"ii\"><a href=\"(.+?)\">" // detail url
|
||||
+ "<img src=\"(.+?)\".+?/>" // thumb url
|
||||
+ ".+?<a class=\"b\" href=\".+?\">(.+?)</a>" // title
|
||||
@@ -160,10 +158,10 @@ public class ListParser {
|
||||
lgi.rating = getStartNum(rating);
|
||||
lgi.generateSLang();
|
||||
|
||||
lgiList.add(lgi);
|
||||
giList.add(lgi);
|
||||
}
|
||||
|
||||
if (lgiList.size() == 0) {
|
||||
if (giList.size() == 0) {
|
||||
if (body.contains("No hits found</div>")) {
|
||||
pageNum = 0;
|
||||
} else if (body.contains("No more hits found</div>")) {
|
||||
@@ -226,7 +224,7 @@ public class ListParser {
|
||||
|
||||
private void getPostedAndUploader(String raw, String[] pau) throws AssertException {
|
||||
int index = raw.indexOf(PAU_SPACER);
|
||||
AssertUtils.assertEqualsEx("Can not parse posted and uploader", index, -1);
|
||||
AssertUtils.assertNotEqualsEx("Can not parse posted and uploader", index, -1);
|
||||
pau[0] = raw.substring(0, index);
|
||||
pau[1] = raw.substring(index + PAU_SPACER.length());
|
||||
}
|
||||
|
||||
@@ -26,17 +26,20 @@ import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.StaggeredGridLayoutManager;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.animation.SimpleAnimatorListener;
|
||||
import com.hippo.drawable.AddDeleteDrawable;
|
||||
import com.hippo.effect.ViewTransition;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.client.EhClient;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.ui.ContentActivity;
|
||||
import com.hippo.util.InterpolatorUtils;
|
||||
import com.hippo.ehviewer.widget.ContentLayout;
|
||||
import com.hippo.ehviewer.widget.OffsetLayout;
|
||||
import com.hippo.ehviewer.widget.SearchBar;
|
||||
@@ -44,12 +47,15 @@ import com.hippo.ehviewer.widget.SearchDatabase;
|
||||
import com.hippo.ehviewer.widget.SearchLayout;
|
||||
import com.hippo.scene.Scene;
|
||||
import com.hippo.util.AssertUtils;
|
||||
import com.hippo.util.InterpolatorUtils;
|
||||
import com.hippo.util.Log;
|
||||
import com.hippo.util.MathUtils;
|
||||
import com.hippo.util.ViewUtils;
|
||||
import com.hippo.widget.FabLayout;
|
||||
import com.hippo.widget.FloatingActionButton;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// TODO disable click action when animating
|
||||
public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
View.OnClickListener, FabLayout.OnCancelListener,
|
||||
@@ -80,6 +86,8 @@ public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
|
||||
private ViewTransition mViewTransition;
|
||||
|
||||
private GalleryListHelper mGalleryListHelper;
|
||||
|
||||
private int mSearchBarOriginalTop;
|
||||
private int mSearchBarOriginalBottom;
|
||||
private ValueAnimator mSearchBarMoveAnimator;
|
||||
@@ -131,6 +139,11 @@ public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
});
|
||||
mSearchLayout.setHelper(this);
|
||||
|
||||
// Content Layout
|
||||
mGalleryListHelper = new GalleryListHelper();
|
||||
mContentLayout.setHelper(mGalleryListHelper);
|
||||
mContentLayout.showContent();
|
||||
|
||||
// Fab Layout
|
||||
mFabLayout.setOnCancelListener(this);
|
||||
|
||||
@@ -147,7 +160,7 @@ public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
mCornerFab.setDrawable(mAddDeleteDrawable);
|
||||
|
||||
// TEST
|
||||
mContentLayout.showText("四姑拉斯基");
|
||||
mGalleryListHelper.refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,6 +191,8 @@ public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
|
||||
@Override
|
||||
protected void onGetFitPaddingBottom(int b) {
|
||||
// Content Layout
|
||||
mContentLayout.setFitPaddingBottom(b);
|
||||
// Search Layout
|
||||
mSearchLayout.setFitPaddingBottom(b);
|
||||
// Corner Fab
|
||||
@@ -470,4 +485,45 @@ public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
(mState == STATE_SEARCH && view == mSearchLayout);
|
||||
}
|
||||
}
|
||||
|
||||
private class GalleryHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public GalleryHolder(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
private class GalleryListHelper extends ContentLayout.ContentHelper<GalleryInfo, GalleryHolder> {
|
||||
|
||||
@Override
|
||||
protected StaggeredGridLayoutManager generateLayoutManager() {
|
||||
return new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void getPageData(final int taskId, int page) {
|
||||
EhClient.getInstance().getGalleryList(EhClient.SOURCE_LOFI, "http://lofi.e-hentai.org/", new EhClient.OnGetGalleryListListener() {
|
||||
@Override
|
||||
public void onSuccess(List<GalleryInfo> glArray, int pageNum) {
|
||||
setPageSize(pageNum);
|
||||
onGetPageData(taskId, glArray);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
Log.d("onFailure", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public GalleryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
return new GalleryHolder(new TextView(mActivity));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(GalleryHolder holder, int position) {
|
||||
((TextView) holder.itemView).setText(getDataAt(position).title);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,9 @@ import android.widget.TextView;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.util.IntIdGenerator;
|
||||
import com.hippo.util.Log;
|
||||
import com.hippo.util.ViewUtils;
|
||||
import com.hippo.widget.Snackbar;
|
||||
import com.hippo.widget.recyclerview.EasyRecyclerView;
|
||||
import com.hippo.widget.refreshlayout.RefreshLayout;
|
||||
|
||||
@@ -43,11 +45,14 @@ public class ContentLayout extends FrameLayout {
|
||||
private EasyRecyclerView mRecyclerView;
|
||||
private View mImageView;
|
||||
private TextView mTextView;
|
||||
private Snackbar mSnackbar;
|
||||
|
||||
private StaggeredGridLayoutManager mLayoutManager;
|
||||
|
||||
private ContentHelper mHelper;
|
||||
|
||||
private int mSnackbarOriginBottom;
|
||||
|
||||
public ContentLayout(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
@@ -69,12 +74,19 @@ public class ContentLayout extends FrameLayout {
|
||||
mProgressBar = (ProgressBar) getChildAt(0);
|
||||
mItView = (ViewGroup) getChildAt(1);
|
||||
mRefreshLayout = (RefreshLayout) getChildAt(2);
|
||||
mSnackbar = (Snackbar) getChildAt(3);
|
||||
mRecyclerView = (EasyRecyclerView) mRefreshLayout.getChildAt(1);
|
||||
mImageView = mItView.getChildAt(0);
|
||||
mTextView = (TextView) mItView.getChildAt(1);
|
||||
|
||||
mLayoutManager = new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL); // TODO
|
||||
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||
// Snackbar
|
||||
mSnackbarOriginBottom = mSnackbar.getPaddingBottom();
|
||||
mSnackbar.setAction(context.getString(R.string.retry), new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public EasyRecyclerView getRecyclerView() {
|
||||
@@ -83,12 +95,20 @@ public class ContentLayout extends FrameLayout {
|
||||
|
||||
public void setHelper(ContentHelper helper) {
|
||||
mHelper = helper;
|
||||
helper.init(mRecyclerView, mLayoutManager);
|
||||
mLayoutManager = helper.generateLayoutManager();
|
||||
mRecyclerView.setLayoutManager(mLayoutManager);
|
||||
mRecyclerView.setAdapter(helper);
|
||||
helper.init(mRefreshLayout, mRecyclerView, mLayoutManager);
|
||||
mRefreshLayout.setOnHeaderRefreshListener(helper);
|
||||
mRefreshLayout.setOnFooterRefreshListener(helper);
|
||||
mRecyclerView.addOnScrollListener(helper.getOnScrollListener());
|
||||
}
|
||||
|
||||
public void setFitPaddingBottom(int fitPaddingBottom) {
|
||||
// Snackbar
|
||||
mSnackbar.setPadding(mSnackbar.getPaddingLeft(), mSnackbar.getPaddingTop(), mSnackbar.getPaddingRight(), mSnackbarOriginBottom + fitPaddingBottom);
|
||||
}
|
||||
|
||||
public void showProgressBar() {
|
||||
ViewUtils.setVisibility(mProgressBar, View.VISIBLE);
|
||||
ViewUtils.setVisibility(mItView, View.GONE);
|
||||
@@ -103,11 +123,25 @@ public class ContentLayout extends FrameLayout {
|
||||
mTextView.setText(text);
|
||||
}
|
||||
|
||||
private abstract static class ContentHelper<E, VH extends RecyclerView.ViewHolder>
|
||||
public void showContent() {
|
||||
ViewUtils.setVisibility(mProgressBar, View.GONE);
|
||||
ViewUtils.setVisibility(mItView, View.GONE);
|
||||
ViewUtils.setVisibility(mRefreshLayout, View.VISIBLE);
|
||||
}
|
||||
|
||||
public abstract static class ContentHelper<E, VH extends RecyclerView.ViewHolder>
|
||||
extends EasyRecyclerView.Adapter<VH>
|
||||
implements RefreshLayout.OnHeaderRefreshListener,
|
||||
RefreshLayout.OnFooterRefreshListener {
|
||||
|
||||
private static final int TYPE_REFRESH = 0;
|
||||
private static final int TYPE_PRE_PAGE = 1;
|
||||
private static final int TYPE_PRE_PAGE_KEEP_POS = 2;
|
||||
private static final int TYPE_NEXT_PAGE = 3;
|
||||
private static final int TYPE_NEXT_PAGE_KEEP_POS = 4;
|
||||
private static final int TYPE_SOMEWHERE = 5;
|
||||
|
||||
private RefreshLayout mRefreshLayout;
|
||||
private RecyclerView mRecyclerView;
|
||||
private StaggeredGridLayoutManager mLayoutManager;
|
||||
|
||||
@@ -121,96 +155,232 @@ public class ContentLayout extends FrameLayout {
|
||||
/**
|
||||
* Store data
|
||||
*/
|
||||
private List<E> mList;
|
||||
private List<E> mData;
|
||||
|
||||
private IntIdGenerator mIdGenerator;
|
||||
|
||||
/**
|
||||
* First index index of current page
|
||||
*/
|
||||
private int mFirstIndex;
|
||||
/**
|
||||
* Last index index of current page
|
||||
*/
|
||||
private int mLastIndex;
|
||||
/**
|
||||
* Current page index
|
||||
*/
|
||||
private int mCurrentPage;
|
||||
/**
|
||||
* First shown page index
|
||||
*/
|
||||
private int mFirstPage;
|
||||
/**
|
||||
* Last shown page index
|
||||
* Last shown page index + 1
|
||||
*/
|
||||
private int mLastPage;
|
||||
/**
|
||||
* The number of page in sum
|
||||
* First index index of current page
|
||||
*/
|
||||
private int mPageNum;
|
||||
private int mFirstIndex;
|
||||
/**
|
||||
* Last index index of current page + 1
|
||||
*/
|
||||
private int mLastIndex;
|
||||
/**
|
||||
* The size of page
|
||||
*/
|
||||
private int mPageSize;
|
||||
private int mCurrentPage;
|
||||
private int mPageVolume;
|
||||
|
||||
private int mCurrentTaskId;
|
||||
private int mCurrentTaskType;
|
||||
private int mCurrentTaskPage;
|
||||
|
||||
private ContentHelper() {
|
||||
mList = new ArrayList<>();
|
||||
public ContentHelper() {
|
||||
mData = new ArrayList<>();
|
||||
mIdGenerator = IntIdGenerator.create();
|
||||
}
|
||||
|
||||
private void init(RecyclerView recyclerView,
|
||||
private void init(RefreshLayout refreshLayout, RecyclerView recyclerView,
|
||||
StaggeredGridLayoutManager layoutManager) {
|
||||
mRefreshLayout = refreshLayout;
|
||||
mRecyclerView = recyclerView;
|
||||
mLayoutManager = layoutManager;
|
||||
}
|
||||
|
||||
RecyclerView.OnScrollListener getOnScrollListener() {
|
||||
private RecyclerView.OnScrollListener getOnScrollListener() {
|
||||
return mOnScrollListener;
|
||||
}
|
||||
|
||||
protected abstract StaggeredGridLayoutManager generateLayoutManager();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param location
|
||||
* @return
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if {@code location < 0 || location >= size()}
|
||||
*/
|
||||
public E getDataAt(int location) {
|
||||
return mList.get(location);
|
||||
return mData.get(location);
|
||||
}
|
||||
|
||||
public abstract E[] getPageData(int page);
|
||||
/**
|
||||
* Call {@link #onGetPageData(int, List)} when get data
|
||||
*
|
||||
* @param taskId task id
|
||||
* @param page the page to get
|
||||
*/
|
||||
protected abstract void getPageData(int taskId, int page);
|
||||
|
||||
public void onGetPageData(int mTaskId, int page, E[] data) {
|
||||
public void setPageSize(int pageSize) {
|
||||
mPageSize = pageSize;
|
||||
}
|
||||
|
||||
public void onGetPageData(int taskId, List<E> data) {
|
||||
int pageVolume = data.size();
|
||||
mPageVolume = pageVolume;
|
||||
if (mCurrentTaskId == taskId) {
|
||||
switch (mCurrentTaskType) {
|
||||
case TYPE_REFRESH:
|
||||
mFirstPage = 0;
|
||||
mLastPage = 1;
|
||||
mCurrentPage = 0;
|
||||
mFirstIndex = 0;
|
||||
mLastIndex = pageVolume;
|
||||
|
||||
mData.clear();
|
||||
mData.addAll(data);
|
||||
notifyDataSetChanged();
|
||||
|
||||
mRecyclerView.stopScroll();
|
||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
break;
|
||||
case TYPE_PRE_PAGE:
|
||||
case TYPE_PRE_PAGE_KEEP_POS:
|
||||
mData.addAll(0, data);
|
||||
notifyItemRangeInserted(0, pageVolume);
|
||||
|
||||
mFirstPage--;
|
||||
if (mCurrentTaskType == TYPE_PRE_PAGE_KEEP_POS) {
|
||||
mFirstIndex += pageVolume;
|
||||
mLastIndex += pageVolume;
|
||||
// TODO
|
||||
} else {
|
||||
mCurrentPage = mFirstPage;
|
||||
mFirstIndex = 0;
|
||||
mLastIndex = pageVolume;
|
||||
|
||||
mRecyclerView.stopScroll();
|
||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
}
|
||||
break;
|
||||
case TYPE_NEXT_PAGE:
|
||||
case TYPE_NEXT_PAGE_KEEP_POS:
|
||||
int oldDataSize = mData.size();
|
||||
mData.addAll(data);
|
||||
notifyItemRangeInserted(oldDataSize, pageVolume);
|
||||
|
||||
mLastPage++;
|
||||
if (mCurrentTaskType != TYPE_NEXT_PAGE_KEEP_POS) {
|
||||
mCurrentPage = mLastPage - 1;
|
||||
mFirstIndex = mData.size() - pageVolume;
|
||||
mLastIndex = mData.size();
|
||||
|
||||
mRecyclerView.stopScroll();
|
||||
mLayoutManager.scrollToPositionWithOffset(mFirstIndex, 0);
|
||||
}
|
||||
break;
|
||||
case TYPE_SOMEWHERE:
|
||||
mData.clear();
|
||||
mData.addAll(data);
|
||||
notifyDataSetChanged();
|
||||
|
||||
mFirstPage = mCurrentTaskPage;
|
||||
mLastPage = mCurrentTaskPage + 1;
|
||||
mCurrentPage = mCurrentTaskPage;
|
||||
mFirstIndex = 0;
|
||||
mLastIndex = pageVolume;
|
||||
|
||||
mRecyclerView.stopScroll();
|
||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mRefreshLayout.setHeaderRefreshing(false);
|
||||
mRefreshLayout.setFooterRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onFooterRefresh() {
|
||||
return false;
|
||||
if (mLastPage >= mPageSize) {
|
||||
return false;
|
||||
} else {
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS;
|
||||
mCurrentTaskPage = mLastPage;
|
||||
getPageData(mCurrentTaskId, mCurrentTaskPage);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHeaderRefresh() {
|
||||
if (mFirstPage > 0) {
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
mCurrentTaskType = TYPE_PRE_PAGE_KEEP_POS;
|
||||
mCurrentTaskPage = mFirstPage - 1;
|
||||
getPageData(mCurrentTaskId, mCurrentTaskPage);
|
||||
} else {
|
||||
doRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
private void doRefresh() {
|
||||
Log.d("doRefresh");
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
mCurrentTaskType = TYPE_REFRESH;
|
||||
mCurrentTaskPage = 0;
|
||||
getPageData(mCurrentTaskId, mCurrentTaskPage);
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
|
||||
mRefreshLayout.setHeaderRefreshing(true);
|
||||
doRefresh();
|
||||
}
|
||||
|
||||
public void goTo(int page) {
|
||||
if (page < 0 || page >= mPageNum) {
|
||||
throw new IndexOutOfBoundsException("Page number is " + mPageNum + ", page is " + page);
|
||||
if (page < 0 || page >= mPageSize) {
|
||||
throw new IndexOutOfBoundsException("Page size is " + mPageSize + ", page is " + page);
|
||||
} else if (page >= mFirstPage && page < mLastPage) {
|
||||
mCurrentPage = page;
|
||||
mFirstIndex = mPageVolume * (page - mFirstPage);
|
||||
mLastIndex = mFirstIndex + mPageVolume;
|
||||
int position = mFirstIndex;
|
||||
mRecyclerView.stopScroll();
|
||||
mLayoutManager.scrollToPositionWithOffset(position, 0);
|
||||
} else if (page == mFirstPage - 1) {
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
mCurrentTaskType = TYPE_PRE_PAGE;
|
||||
mCurrentTaskPage = page;
|
||||
getPageData(mCurrentTaskId, mCurrentTaskPage);
|
||||
} else if (page == mLastPage) {
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
mCurrentTaskType = TYPE_NEXT_PAGE;
|
||||
mCurrentTaskPage = page;
|
||||
getPageData(mCurrentTaskId, mCurrentTaskPage);
|
||||
} else {
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
mCurrentTaskType = TYPE_SOMEWHERE;
|
||||
mCurrentTaskPage = page;
|
||||
getPageData(mCurrentTaskId, mCurrentTaskPage);
|
||||
}
|
||||
}
|
||||
|
||||
if (page > mFirstIndex) {
|
||||
|
||||
}
|
||||
public void reload() {
|
||||
notifyDataSetChanged();
|
||||
mCurrentPage = mFirstPage;
|
||||
mFirstIndex = 0;
|
||||
mLastIndex = mPageVolume;
|
||||
mRecyclerView.stopScroll();
|
||||
mLayoutManager.scrollToPositionWithOffset(0, 0);
|
||||
}
|
||||
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mData.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,12 @@ public class AssertUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNotEquals(String message, int expected, int actual) {
|
||||
if (expected == actual) {
|
||||
throw new AssertError(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertInstanceof(String message, Object obj, Class clazz) {
|
||||
if (!clazz.isInstance(obj)) {
|
||||
throw new AssertError(message);
|
||||
@@ -62,6 +68,13 @@ public class AssertUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNotEqualsEx(String message, int expected, int actual)
|
||||
throws AssertException {
|
||||
if (expected == actual) {
|
||||
throw new AssertException(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertInstanceofEx(String message, Object obj, Class clazz)
|
||||
throws AssertException {
|
||||
if (!clazz.isInstance(obj)) {
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.util.ViewUtils;
|
||||
|
||||
public class Snackbar extends LinearLayout {
|
||||
|
||||
private TextView mMessageTxt;
|
||||
private View mSpace;
|
||||
private TextView mActionTxt;
|
||||
|
||||
public Snackbar(Context context) {
|
||||
super(context);
|
||||
init(context, null);
|
||||
}
|
||||
|
||||
public Snackbar(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public Snackbar(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
Resources resources = context.getResources();
|
||||
setBackgroundColor(resources.getColor(R.color.snackbar_background));
|
||||
setPadding(resources.getDimensionPixelOffset(R.dimen.snackbar_padding_left),
|
||||
resources.getDimensionPixelOffset(R.dimen.snackbar_padding_top),
|
||||
resources.getDimensionPixelOffset(R.dimen.snackbar_padding_right),
|
||||
resources.getDimensionPixelOffset(R.dimen.snackbar_padding_bottom));
|
||||
setOrientation(LinearLayout.HORIZONTAL);
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.widget_snackbar, this);
|
||||
mMessageTxt = (TextView) getChildAt(0);
|
||||
mSpace = getChildAt(1);
|
||||
mActionTxt = (TextView) getChildAt(2);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(
|
||||
attrs, R.styleable.Snackbar);
|
||||
setMessage(a.getString(R.styleable.Snackbar_message));
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
mMessageTxt.setText(message);
|
||||
}
|
||||
|
||||
public void setAction(String actionText, View.OnClickListener action) {
|
||||
if (TextUtils.isEmpty(actionText)) {
|
||||
mActionTxt.setOnClickListener(null);
|
||||
mActionTxt.setClickable(false);
|
||||
ViewUtils.setVisibility(mSpace, View.GONE);
|
||||
ViewUtils.setVisibility(mActionTxt, View.GONE);
|
||||
} else {
|
||||
mActionTxt.setText(actionText);
|
||||
mActionTxt.setOnClickListener(action);
|
||||
ViewUtils.setVisibility(mSpace, View.VISIBLE);
|
||||
ViewUtils.setVisibility(mActionTxt, View.VISIBLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1064,10 +1064,10 @@ public class RefreshLayout extends ViewGroup {
|
||||
* triggers a refresh should implement this interface.
|
||||
*/
|
||||
public interface OnHeaderRefreshListener {
|
||||
public void onHeaderRefresh();
|
||||
void onHeaderRefresh();
|
||||
}
|
||||
|
||||
public interface OnFooterRefreshListener {
|
||||
public boolean onFooterRefresh();
|
||||
boolean onFooterRefresh();
|
||||
}
|
||||
}
|
||||
@@ -60,4 +60,12 @@
|
||||
|
||||
</com.hippo.widget.refreshlayout.RefreshLayout>
|
||||
|
||||
<com.hippo.widget.Snackbar
|
||||
xmlns:auto="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/snackbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
auto:message="@string/refresh_snackbar_message"/>
|
||||
|
||||
</merge>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?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">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="20dp"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="@color/primary_text_dark"/>
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:minWidth="@dimen/snackbar_interval"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@color/snackbar_action"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</merge>
|
||||
@@ -15,6 +15,9 @@
|
||||
-->
|
||||
<resources>
|
||||
|
||||
<!-- Snackbar -->
|
||||
<dimen name="snackbar_interval">48dp</dimen>
|
||||
|
||||
<!-- Content -->
|
||||
<dimen name="content_padding_start">52dp</dimen>
|
||||
<dimen name="content_padding_end">52dp</dimen>
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
<attr name="statusBarColor" format="color"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="Snackbar">
|
||||
<attr name="message" format="string"/>
|
||||
</declare-styleable>
|
||||
|
||||
<!-- ********** -->
|
||||
<!-- For Vector -->
|
||||
<!-- ********** -->
|
||||
|
||||
@@ -84,4 +84,8 @@
|
||||
<!-- CheckTextView -->
|
||||
<color name="check_text_view_mask">#8a000000</color>
|
||||
|
||||
<!-- Snackbar -->
|
||||
<color name="snackbar_background">#ff333333</color>
|
||||
<color name="snackbar_action">#ffeeff41</color>
|
||||
|
||||
</resources>
|
||||
@@ -19,6 +19,13 @@
|
||||
<dimen name="stats_text_view_padding_top">24dp</dimen>
|
||||
<dimen name="stats_text_view_padding_right">16dp</dimen>
|
||||
|
||||
<!-- Snackbar -->
|
||||
<dimen name="snackbar_padding_left">24dp</dimen>
|
||||
<dimen name="snackbar_padding_right">24dp</dimen>
|
||||
<dimen name="snackbar_padding_top">14dp</dimen>
|
||||
<dimen name="snackbar_padding_bottom">14dp</dimen>
|
||||
<dimen name="snackbar_interval">24dp</dimen>
|
||||
|
||||
<!-- FloatingActionBarLayout -->
|
||||
<dimen name="floating_action_bar_layout_interval">16dp</dimen>
|
||||
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
|
||||
<string name="search_tag_help">Searching via specify tag is precise. One tag each searching. Searching format is <tag> or <namespace>:<tag>. Other searching options will be ignored when specify tag is checked.</string>
|
||||
|
||||
<!-- Content Layout Snackbar-->
|
||||
<string name="refresh_snackbar_message">Can\'t get next page</string>
|
||||
|
||||
<!-- search_min_rating -->
|
||||
<string name="star_2">2 stars</string>
|
||||
<string name="star_3">3 stars</string>
|
||||
@@ -74,5 +77,6 @@
|
||||
|
||||
<string name="keyword">Keyword</string>
|
||||
<string name="search">Search</string>
|
||||
<string name="retry">Retry</string>
|
||||
|
||||
</resources>
|
||||
Reference in new issue
Block a user