diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhClient.java b/app/src/main/java/com/hippo/ehviewer/client/EhClient.java index acda3e7b5..3ba60a038 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhClient.java +++ b/app/src/main/java/com/hippo/ehviewer/client/EhClient.java @@ -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 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 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) objs[0]; mPageNum = (int) objs[1]; } @Override public void doSuccessCallback() { - mListener.onSuccess(mGlArray, mPageNum); + mListener.onSuccess(mGlList, mPageNum); } } diff --git a/app/src/main/java/com/hippo/ehviewer/client/ListParser.java b/app/src/main/java/com/hippo/ehviewer/client/ListParser.java index 99a894e9a..3743a5f70 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/ListParser.java +++ b/app/src/main/java/com/hippo/ehviewer/client/ListParser.java @@ -42,7 +42,7 @@ public class ListParser { */ public int pageNum; - public GalleryInfo[] giArray; + public List giList; private void parse(String body) throws EhException { Pattern p; @@ -61,7 +61,7 @@ public class ListParser { } // Get gallery - List giList = new ArrayList<>(DEFAULT_LIST_SIZE); + giList = new ArrayList<>(DEFAULT_LIST_SIZE); p = Pattern.compile("(?:)?(?:)?" // category + "(.+?)" // 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 lgiList = new ArrayList<>(DEFAULT_LIST_SIZE); + giList = new ArrayList<>(DEFAULT_LIST_SIZE); p = Pattern.compile("" // detail url + "" // thumb url + ".+?(.+?)" // 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")) { pageNum = 0; } else if (body.contains("No more hits found")) { @@ -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()); } 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 05dca558e..31a1f6988 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 @@ -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 { + + @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 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); + } + } } 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 0cc5181a5..00d4dcc3a 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java @@ -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 + public void showContent() { + ViewUtils.setVisibility(mProgressBar, View.GONE); + ViewUtils.setVisibility(mItView, View.GONE); + ViewUtils.setVisibility(mRefreshLayout, View.VISIBLE); + } + + public abstract static class ContentHelper extends EasyRecyclerView.Adapter 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 mList; + private List 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 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(); + } } } diff --git a/app/src/main/java/com/hippo/util/AssertUtils.java b/app/src/main/java/com/hippo/util/AssertUtils.java index 929e186a2..afde24131 100644 --- a/app/src/main/java/com/hippo/util/AssertUtils.java +++ b/app/src/main/java/com/hippo/util/AssertUtils.java @@ -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)) { diff --git a/app/src/main/java/com/hippo/widget/Snackbar.java b/app/src/main/java/com/hippo/widget/Snackbar.java new file mode 100644 index 000000000..eaa045442 --- /dev/null +++ b/app/src/main/java/com/hippo/widget/Snackbar.java @@ -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); + } + } +} diff --git a/app/src/main/java/com/hippo/widget/refreshlayout/RefreshLayout.java b/app/src/main/java/com/hippo/widget/refreshlayout/RefreshLayout.java index 54129e748..00bec6b15 100644 --- a/app/src/main/java/com/hippo/widget/refreshlayout/RefreshLayout.java +++ b/app/src/main/java/com/hippo/widget/refreshlayout/RefreshLayout.java @@ -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(); } } diff --git a/app/src/main/res/layout/widget_content_layout.xml b/app/src/main/res/layout/widget_content_layout.xml index 7ab42f834..509258b5c 100644 --- a/app/src/main/res/layout/widget_content_layout.xml +++ b/app/src/main/res/layout/widget_content_layout.xml @@ -60,4 +60,12 @@ + + diff --git a/app/src/main/res/layout/widget_snackbar.xml b/app/src/main/res/layout/widget_snackbar.xml new file mode 100644 index 000000000..5a20c9a93 --- /dev/null +++ b/app/src/main/res/layout/widget_snackbar.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + diff --git a/app/src/main/res/values-sw600dp/dimens.xml b/app/src/main/res/values-sw600dp/dimens.xml index 0fbf5c47d..9e8082610 100644 --- a/app/src/main/res/values-sw600dp/dimens.xml +++ b/app/src/main/res/values-sw600dp/dimens.xml @@ -15,6 +15,9 @@ --> + + 48dp + 52dp 52dp diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 9853ae832..4e8281158 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -50,6 +50,10 @@ + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 3d7cf7fe3..d7beba4a5 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -84,4 +84,8 @@ #8a000000 + + #ff333333 + #ffeeff41 + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 9e1499aa4..bea43eed1 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -19,6 +19,13 @@ 24dp 16dp + + 24dp + 24dp + 14dp + 14dp + 24dp + 16dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fe21be186..17f6d31a3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -65,6 +65,9 @@ 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. + + Can\'t get next page + 2 stars 3 stars @@ -74,5 +77,6 @@ Keyword Search + Retry