diff --git a/app/app.iml b/app/app.iml index 278e7237f..421c9fdf9 100644 --- a/app/app.iml +++ b/app/app.iml @@ -87,8 +87,14 @@ + + + + + + diff --git a/app/build.gradle b/app/build.gradle index 66bd1f9b3..eb83cb6e3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,5 +28,6 @@ dependencies { compile 'com.android.support:appcompat-v7:22.1.1' compile 'com.android.support:recyclerview-v7:22.1.1' compile 'com.github.japgolly.android:svg-android:2.0.6' + compile 'com.facebook.fresco:fresco:0.4.0' compile fileTree(dir: 'libs', include: ['*.jar']) } diff --git a/app/src/main/java/com/hippo/ehviewer/EhApplication.java b/app/src/main/java/com/hippo/ehviewer/EhApplication.java index 42c47d85e..c35a6b2b7 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhApplication.java +++ b/app/src/main/java/com/hippo/ehviewer/EhApplication.java @@ -17,6 +17,7 @@ package com.hippo.ehviewer; import android.content.Context; +import com.facebook.drawee.backends.pipeline.Fresco; import com.hippo.content.VectorContext; import com.hippo.scene.SceneApplication; import com.hippo.util.Log; @@ -26,6 +27,8 @@ public class EhApplication extends SceneApplication { @Override public void onCreate() { super.onCreate(); + + Fresco.initialize(this); } @Override @@ -34,7 +37,9 @@ public class EhApplication extends SceneApplication { } @Override - public void onTrimMemory (int level) { + public void onTrimMemory(int level) { + super.onTrimMemory(level); + if (level == TRIM_MEMORY_UI_HIDDEN) { Log.d("Application hiden"); } 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 3ba60a038..ac83497e1 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhClient.java +++ b/app/src/main/java/com/hippo/ehviewer/client/EhClient.java @@ -108,7 +108,7 @@ public final class EhClient { } public abstract static class OnGetGalleryListListener implements EhClientListener { - public abstract void onSuccess(List glArray, int pageNum); + public abstract void onSuccess(List glList, int pageNum); } private void doBgJob(BgJobHelper bjh) { 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 026ceaa50..32fb033d7 100644 --- a/app/src/main/java/com/hippo/ehviewer/data/ListUrlBuilder.java +++ b/app/src/main/java/com/hippo/ehviewer/data/ListUrlBuilder.java @@ -43,13 +43,11 @@ public class ListUrlBuilder { private int mPageIndex = 0; private int mCategory = EhUtils.NONE; - private String mSearchKey = null; + private String mKeyword = null; private int mAdvanceSearch = -1; private int mMinRating = -1; - private String mSearchTag = null; - public int getMode() { return mMode; } @@ -74,12 +72,12 @@ public class ListUrlBuilder { mCategory = category; } - public String getSearchKey() { - return mSearchKey; + public String getKeyword() { + return mKeyword; } - public void setSearchKey(String searchKey) { - mSearchKey = searchKey; + public void setKeyword(String keyword) { + mKeyword = keyword; } public int getAdvanceSearch() { @@ -98,14 +96,6 @@ public class ListUrlBuilder { mMinRating = minRating; } - public String getSearchTag() { - return mSearchTag; - } - - public void setSearchTag(String searchTag) { - mSearchTag = searchTag; - } - /** * Make them the same * @param glub The template @@ -114,10 +104,9 @@ public class ListUrlBuilder { mMode = glub.mMode; mPageIndex = glub.mPageIndex; mCategory = glub.mCategory; - mSearchKey = glub.mSearchKey; + mKeyword = glub.mKeyword; mAdvanceSearch = glub.mAdvanceSearch; mMinRating = glub.mMinRating; - mSearchTag = glub.mSearchTag; } public String build(int source) throws UnsupportedSearch { @@ -141,9 +130,9 @@ public class ListUrlBuilder { filter = true; } // Search key - if (mSearchKey != null) { + if (mKeyword != null) { try { - ub.addQuery("f_search", URLEncoder.encode(mSearchKey, "UTF-8")); + ub.addQuery("f_search", URLEncoder.encode(mKeyword, "UTF-8")); filter = true; } catch (UnsupportedEncodingException e) { // Empty @@ -184,7 +173,7 @@ public class ListUrlBuilder { StringBuilder sb = new StringBuilder(EhClient.getUrlHeader(source)); sb.append("tag/"); try { - sb.append(URLEncoder.encode(mSearchTag, "UTF-8")); + sb.append(URLEncoder.encode(mKeyword, "UTF-8")); } catch (UnsupportedEncodingException e) { // Empty } 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 31a1f6988..9b28cd4f2 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 @@ -21,27 +21,33 @@ import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.content.res.Resources; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; import android.util.SparseArray; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.widget.TextView; +import com.facebook.drawee.view.SimpleDraweeView; 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.client.ListParser; import com.hippo.ehviewer.data.GalleryInfo; import com.hippo.ehviewer.ui.ContentActivity; +import com.hippo.ehviewer.util.EhUtils; import com.hippo.ehviewer.widget.ContentLayout; import com.hippo.ehviewer.widget.OffsetLayout; +import com.hippo.ehviewer.widget.RatingView; import com.hippo.ehviewer.widget.SearchBar; import com.hippo.ehviewer.widget.SearchDatabase; import com.hippo.ehviewer.widget.SearchLayout; @@ -56,6 +62,7 @@ import com.hippo.widget.FloatingActionButton; import java.util.List; +// TODO Must refresh when change source // TODO disable click action when animating public class GalleryListScene extends Scene implements SearchBar.Helper, View.OnClickListener, FabLayout.OnCancelListener, @@ -134,7 +141,9 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, ViewUtils.removeOnGlobalLayoutListener(mSearchBar.getViewTreeObserver(), this); mSearchBarOriginalTop = mSearchBar.getTop(); mSearchBarOriginalBottom = mSearchBar.getBottom(); - mSearchLayout.setFitPaddingTop(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); } }); mSearchLayout.setHelper(this); @@ -142,7 +151,6 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, // Content Layout mGalleryListHelper = new GalleryListHelper(); mContentLayout.setHelper(mGalleryListHelper); - mContentLayout.showContent(); // Fab Layout mFabLayout.setOnCancelListener(this); @@ -159,8 +167,10 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, mSearchDrawable = mResources.getDrawable(R.drawable.ic_search_dark); mCornerFab.setDrawable(mAddDeleteDrawable); - // TEST - mGalleryListHelper.refresh(); + // When scene start + if (savedInstanceState == null) { + mGalleryListHelper.refresh(); + } } @Override @@ -488,42 +498,103 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, private class GalleryHolder extends RecyclerView.ViewHolder { + public SimpleDraweeView thumb; + public TextView title; + public TextView uploader; + public RatingView rating; + public TextView category; + public TextView posted; + public TextView simpleLanguage; + public GalleryHolder(View itemView) { super(itemView); + thumb = (SimpleDraweeView) itemView.findViewById(R.id.thumb); + title = (TextView) itemView.findViewById(R.id.title); + uploader = (TextView) itemView.findViewById(R.id.uploader); + rating = (RatingView) itemView.findViewById(R.id.rating); + category = (TextView) itemView.findViewById(R.id.category); + posted = (TextView) itemView.findViewById(R.id.posted); + simpleLanguage = (TextView) itemView.findViewById(R.id.simple_language); } } private class GalleryListHelper extends ContentLayout.ContentHelper { - @Override - protected StaggeredGridLayoutManager generateLayoutManager() { - return new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL); + private LayoutInflater mInflater; + + public GalleryListHelper() { + super(); + mInflater = mActivity.getLayoutInflater(); } @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); - } + protected RecyclerView.LayoutManager generateLayoutManager() { + // TODO StaggeredGridLayoutManager item dislocation for setPaddingTop + return new LinearLayoutManager(mActivity); + //return new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL); + } - @Override - public void onFailure(Exception e) { - Log.d("onFailure", e); - } - }); + @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); } @Override public GalleryHolder onCreateViewHolder(ViewGroup parent, int viewType) { - return new GalleryHolder(new TextView(mActivity)); + View view = mInflater.inflate(R.layout.item_gallery_list_detail, parent, false); + return new GalleryHolder(view); } @Override public void onBindViewHolder(GalleryHolder holder, int position) { - ((TextView) holder.itemView).setText(getDataAt(position).title); + GalleryInfo gi = getDataAt(position); + holder.thumb.setImageURI(Uri.parse(gi.thumb)); + holder.title.setText(gi.title); + holder.uploader.setText(gi.uploader); + holder.rating.setRating(gi.rating); + TextView category = holder.category; + String newCategoryText = EhUtils.getCategory(gi.category); + if (!newCategoryText.equals(category.getText())) { + category.setText(newCategoryText); + category.setBackgroundColor(EhUtils.getCategoryColor(gi.category)); + } + holder.posted.setText(gi.posted); + holder.simpleLanguage.setText(gi.simpleLanguage); + } + } + + private class GalleryListListener extends EhClient.OnGetGalleryListListener { + + private int mTaskId; + private int mTaskType; + private int mTargetPage; + private int mSource; + + public GalleryListListener(int taskId, int taskType, int targetPage, int source) { + mTaskId = taskId; + mTaskType = taskType; + mTargetPage = targetPage; + mSource = source; + } + + @Override + public void onSuccess(List glList, int pageNum) { + if (mSource == EhClient.SOURCE_LOFI) { + if (pageNum == ListParser.CURRENT_PAGE_IS_LAST) { + mGalleryListHelper.setPageSize(mTargetPage); + } else if (mTaskType == ContentLayout.ContentHelper.TYPE_REFRESH) { + mGalleryListHelper.setPageSize(Integer.MAX_VALUE); + } + } else { + mGalleryListHelper.setPageSize(pageNum); + } + mGalleryListHelper.onGetPageData(mTaskId, glList); + } + + @Override + public void onFailure(Exception e) { + mGalleryListHelper.onGetPageData(mTaskId, e); } } } diff --git a/app/src/main/java/com/hippo/ehviewer/util/EhUtils.java b/app/src/main/java/com/hippo/ehviewer/util/EhUtils.java index 567c599eb..b0a8aeb1b 100644 --- a/app/src/main/java/com/hippo/ehviewer/util/EhUtils.java +++ b/app/src/main/java/com/hippo/ehviewer/util/EhUtils.java @@ -15,6 +15,8 @@ package com.hippo.ehviewer.util; +import android.graphics.Color; + public final class EhUtils { public static final String EH_DOWNLOAD_FILENAME = ".ehviewer"; @@ -32,6 +34,18 @@ public final class EhUtils { public static final int WESTERN = 0x200; public static final int UNKNOWN = 0x400; + public static final int BG_COLOR_DOUJINSHI = 0xfff44336; + public static final int BG_COLOR_MANGA = 0xffff9800; + public static final int BG_COLOR_ARTIST_CG = 0xfffbc02d; + public static final int BG_COLOR_GAME_CG = 0xff4caf50; + public static final int BG_COLOR_WESTERN = 0xff8bc34a; + public static final int BG_COLOR_NON_H = 0xff2196f3; + public static final int BG_COLOR_IMAGE_SET = 0xff3f51b5; + public static final int BG_COLOR_COSPLAY = 0xff9c27b0; + public static final int BG_COLOR_ASIAN_PORN = 0xff9575cd; + public static final int BG_COLOR_MISC = 0xfff06292; + public static final int BG_COLOR_UNKNOWN = Color.BLACK; + private static final int[] CATEGORY_VALUES = { MISC, DOUJINSHI, @@ -78,4 +92,31 @@ public final class EhUtils { } return CATEGORY_STRINGS[i][0]; } + + public static int getCategoryColor(int category) { + switch (category) { + case DOUJINSHI: + return BG_COLOR_DOUJINSHI; + case MANGA: + return BG_COLOR_MANGA; + case ARTIST_CG: + return BG_COLOR_ARTIST_CG; + case GAME_CG: + return BG_COLOR_GAME_CG; + case WESTERN: + return BG_COLOR_WESTERN; + case NON_H: + return BG_COLOR_NON_H; + case IMAGE_SET: + return BG_COLOR_IMAGE_SET; + case COSPLAY: + return BG_COLOR_COSPLAY; + case ASIAN_PORN: + return BG_COLOR_ASIAN_PORN; + case MISC: + return BG_COLOR_MISC; + default: + return BG_COLOR_UNKNOWN; + } + } } 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 00d4dcc3a..7a6b986b7 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/ContentLayout.java @@ -17,7 +17,6 @@ package com.hippo.ehviewer.widget; import android.content.Context; import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; @@ -28,7 +27,8 @@ import android.widget.TextView; import com.hippo.ehviewer.R; import com.hippo.util.IntIdGenerator; -import com.hippo.util.Log; +import com.hippo.util.LayoutManagerUtils; +import com.hippo.util.UiUtils; import com.hippo.util.ViewUtils; import com.hippo.widget.Snackbar; import com.hippo.widget.recyclerview.EasyRecyclerView; @@ -47,10 +47,8 @@ public class ContentLayout extends FrameLayout { private TextView mTextView; private Snackbar mSnackbar; - private StaggeredGridLayoutManager mLayoutManager; - - private ContentHelper mHelper; - + private int mRecyclerViewOriginTop; + private int mRecyclerViewOriginBottom; private int mSnackbarOriginBottom; public ContentLayout(Context context) { @@ -79,12 +77,16 @@ public class ContentLayout extends FrameLayout { mImageView = mItView.getChildAt(0); mTextView = (TextView) mItView.getChildAt(1); + // + mRecyclerViewOriginTop = mRecyclerView.getPaddingTop(); + mRecyclerViewOriginBottom = mRecyclerView.getPaddingBottom(); + // Snackbar mSnackbarOriginBottom = mSnackbar.getPaddingBottom(); mSnackbar.setAction(context.getString(R.string.retry), new View.OnClickListener() { @Override public void onClick(View v) { - + // TODO } }); } @@ -94,39 +96,29 @@ public class ContentLayout extends FrameLayout { } public void setHelper(ContentHelper helper) { - mHelper = helper; - mLayoutManager = helper.generateLayoutManager(); - mRecyclerView.setLayoutManager(mLayoutManager); - mRecyclerView.setAdapter(helper); - helper.init(mRefreshLayout, mRecyclerView, mLayoutManager); - mRefreshLayout.setOnHeaderRefreshListener(helper); - mRefreshLayout.setOnFooterRefreshListener(helper); - mRecyclerView.addOnScrollListener(helper.getOnScrollListener()); + helper.init(this); + } + + public void setFitPaddingTop(int fitPaddingTop) { + // RecyclerView + mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), + mRecyclerViewOriginTop + fitPaddingTop, + mRecyclerView.getPaddingRight(), + mRecyclerView.getPaddingBottom()); + // RefreshLayout + mRefreshLayout.setProgressViewOffset(false, fitPaddingTop, + fitPaddingTop + UiUtils.dp2pix(getContext(), 32)); // TODO } public void setFitPaddingBottom(int fitPaddingBottom) { + // RecyclerView + mRecyclerView.setPadding(mRecyclerView.getPaddingLeft(), + mRecyclerView.getPaddingTop(), mRecyclerView.getPaddingRight(), + mRecyclerViewOriginBottom + 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); - ViewUtils.setVisibility(mRefreshLayout, View.GONE); - } - - public void showText(CharSequence text) { - ViewUtils.setVisibility(mProgressBar, View.GONE); - ViewUtils.setVisibility(mItView, View.VISIBLE); - ViewUtils.setVisibility(mRefreshLayout, View.GONE); - - mTextView.setText(text); - } - - public void showContent() { - ViewUtils.setVisibility(mProgressBar, View.GONE); - ViewUtils.setVisibility(mItView, View.GONE); - ViewUtils.setVisibility(mRefreshLayout, View.VISIBLE); + mSnackbar.setPadding(mSnackbar.getPaddingLeft(), + mSnackbar.getPaddingTop(), mSnackbar.getPaddingRight(), + mSnackbarOriginBottom + fitPaddingBottom); } public abstract static class ContentHelper @@ -134,16 +126,21 @@ public class ContentLayout extends FrameLayout { 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; + public static final int TYPE_REFRESH = 0; + public static final int TYPE_PRE_PAGE = 1; + public static final int TYPE_PRE_PAGE_KEEP_POS = 2; + public static final int TYPE_NEXT_PAGE = 3; + public static final int TYPE_NEXT_PAGE_KEEP_POS = 4; + public static final int TYPE_SOMEWHERE = 5; + private ProgressBar mProgressBar; + private ViewGroup mItView; private RefreshLayout mRefreshLayout; - private RecyclerView mRecyclerView; - private StaggeredGridLayoutManager mLayoutManager; + private EasyRecyclerView mRecyclerView; + private View mImageView; + private TextView mTextView; + private Snackbar mSnackbar; + private RecyclerView.LayoutManager mLayoutManager; private RecyclerView.OnScrollListener mOnScrollListener = new RecyclerView.OnScrollListener() { @Override @@ -191,18 +188,48 @@ public class ContentLayout extends FrameLayout { mIdGenerator = IntIdGenerator.create(); } - private void init(RefreshLayout refreshLayout, RecyclerView recyclerView, - StaggeredGridLayoutManager layoutManager) { - mRefreshLayout = refreshLayout; - mRecyclerView = recyclerView; - mLayoutManager = layoutManager; + private void init(ContentLayout contentLayout) { + mProgressBar = contentLayout.mProgressBar; + mItView = contentLayout.mItView; + mRefreshLayout = contentLayout.mRefreshLayout; + mSnackbar = contentLayout.mSnackbar; + mRecyclerView = contentLayout.mRecyclerView; + mImageView = contentLayout.mImageView; + mTextView = contentLayout.mTextView; + mLayoutManager = generateLayoutManager(); + + mRecyclerView.setLayoutManager(mLayoutManager); + mRecyclerView.setAdapter(this); + mRecyclerView.addOnScrollListener(mOnScrollListener); + mRefreshLayout.setOnHeaderRefreshListener(this); + mRefreshLayout.setOnFooterRefreshListener(this); } private RecyclerView.OnScrollListener getOnScrollListener() { return mOnScrollListener; } - protected abstract StaggeredGridLayoutManager generateLayoutManager(); + protected abstract RecyclerView.LayoutManager generateLayoutManager(); + + public void showProgressBar() { + ViewUtils.setVisibility(mProgressBar, View.VISIBLE); + ViewUtils.setVisibility(mItView, View.GONE); + ViewUtils.setVisibility(mRefreshLayout, View.GONE); + } + + public void showText(CharSequence text) { + ViewUtils.setVisibility(mProgressBar, View.GONE); + ViewUtils.setVisibility(mItView, View.VISIBLE); + ViewUtils.setVisibility(mRefreshLayout, View.GONE); + + mTextView.setText(text); + } + + public void showContent() { + ViewUtils.setVisibility(mProgressBar, View.GONE); + ViewUtils.setVisibility(mItView, View.GONE); + ViewUtils.setVisibility(mRefreshLayout, View.VISIBLE); + } /** * @throws IndexOutOfBoundsException @@ -218,13 +245,22 @@ public class ContentLayout extends FrameLayout { * @param taskId task id * @param page the page to get */ - protected abstract void getPageData(int taskId, int page); + protected abstract void getPageData(int taskId, int type, int page); public void setPageSize(int pageSize) { mPageSize = pageSize; } + public int getPageSize() { + return mPageSize; + } + + public void resetPageSize() { + mPageSize = Integer.MAX_VALUE; + } + public void onGetPageData(int taskId, List data) { + showContent(); int pageVolume = data.size(); mPageVolume = pageVolume; if (mCurrentTaskId == taskId) { @@ -241,7 +277,7 @@ public class ContentLayout extends FrameLayout { notifyDataSetChanged(); mRecyclerView.stopScroll(); - mLayoutManager.scrollToPositionWithOffset(0, 0); + LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, 0, 0); break; case TYPE_PRE_PAGE: case TYPE_PRE_PAGE_KEEP_POS: @@ -259,7 +295,7 @@ public class ContentLayout extends FrameLayout { mLastIndex = pageVolume; mRecyclerView.stopScroll(); - mLayoutManager.scrollToPositionWithOffset(0, 0); + LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, 0, 0); } break; case TYPE_NEXT_PAGE: @@ -275,7 +311,7 @@ public class ContentLayout extends FrameLayout { mLastIndex = mData.size(); mRecyclerView.stopScroll(); - mLayoutManager.scrollToPositionWithOffset(mFirstIndex, 0); + LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, mFirstIndex, 0); } break; case TYPE_SOMEWHERE: @@ -290,7 +326,7 @@ public class ContentLayout extends FrameLayout { mLastIndex = pageVolume; mRecyclerView.stopScroll(); - mLayoutManager.scrollToPositionWithOffset(0, 0); + LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, 0, 0); break; } } @@ -299,6 +335,14 @@ public class ContentLayout extends FrameLayout { mRefreshLayout.setFooterRefreshing(false); } + public void onGetPageData(int taskId, Exception e) { + if (mCurrentTaskId == taskId) { + mRefreshLayout.setHeaderRefreshing(false); + mRefreshLayout.setFooterRefreshing(false); + showText(e.getClass().getName()); + } + } + @Override public boolean onFooterRefresh() { if (mLastPage >= mPageSize) { @@ -307,7 +351,7 @@ public class ContentLayout extends FrameLayout { mCurrentTaskId = mIdGenerator.nextId(); mCurrentTaskType = TYPE_NEXT_PAGE_KEEP_POS; mCurrentTaskPage = mLastPage; - getPageData(mCurrentTaskId, mCurrentTaskPage); + getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage); return true; } } @@ -318,21 +362,24 @@ public class ContentLayout extends FrameLayout { mCurrentTaskId = mIdGenerator.nextId(); mCurrentTaskType = TYPE_PRE_PAGE_KEEP_POS; mCurrentTaskPage = mFirstPage - 1; - getPageData(mCurrentTaskId, mCurrentTaskPage); + getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage); } else { doRefresh(); } } private void doRefresh() { - Log.d("doRefresh"); mCurrentTaskId = mIdGenerator.nextId(); mCurrentTaskType = TYPE_REFRESH; mCurrentTaskPage = 0; - getPageData(mCurrentTaskId, mCurrentTaskPage); + getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage); } + /** + * Show progress bar first, than do refresh + */ public void refresh() { + showProgressBar(); mRefreshLayout.setHeaderRefreshing(true); doRefresh(); } @@ -346,22 +393,22 @@ public class ContentLayout extends FrameLayout { mLastIndex = mFirstIndex + mPageVolume; int position = mFirstIndex; mRecyclerView.stopScroll(); - mLayoutManager.scrollToPositionWithOffset(position, 0); + LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, position, 0); } else if (page == mFirstPage - 1) { mCurrentTaskId = mIdGenerator.nextId(); mCurrentTaskType = TYPE_PRE_PAGE; mCurrentTaskPage = page; - getPageData(mCurrentTaskId, mCurrentTaskPage); + getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage); } else if (page == mLastPage) { mCurrentTaskId = mIdGenerator.nextId(); mCurrentTaskType = TYPE_NEXT_PAGE; mCurrentTaskPage = page; - getPageData(mCurrentTaskId, mCurrentTaskPage); + getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage); } else { mCurrentTaskId = mIdGenerator.nextId(); mCurrentTaskType = TYPE_SOMEWHERE; mCurrentTaskPage = page; - getPageData(mCurrentTaskId, mCurrentTaskPage); + getPageData(mCurrentTaskId, mCurrentTaskType, mCurrentTaskPage); } } @@ -371,7 +418,7 @@ public class ContentLayout extends FrameLayout { mFirstIndex = 0; mLastIndex = mPageVolume; mRecyclerView.stopScroll(); - mLayoutManager.scrollToPositionWithOffset(0, 0); + LayoutManagerUtils.scrollToPositionWithOffset(mLayoutManager, 0, 0); } public void onScrolled(RecyclerView recyclerView, int dx, int dy) { diff --git a/app/src/main/java/com/hippo/ehviewer/widget/RatingView.java b/app/src/main/java/com/hippo/ehviewer/widget/RatingView.java new file mode 100644 index 000000000..c14b2a12d --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/widget/RatingView.java @@ -0,0 +1,99 @@ +/* + * 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.widget; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; + +import com.hippo.ehviewer.R; + +public class RatingView extends View { + + private Drawable mStarDrawable; + private Drawable mStarHalfDrawable; + private int mRatingSize; + private int mRatingInterval; + + private float mRating; + private int mRatingInt; + + public RatingView(Context context) { + super(context); + init(context); + } + + public RatingView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public RatingView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + Resources resources = context.getResources(); + mStarDrawable = resources.getDrawable(R.drawable.ic_star); + mStarHalfDrawable = resources.getDrawable(R.drawable.ic_star_half); + mRatingSize = resources.getDimensionPixelOffset(R.dimen.rating_size); + mRatingInterval = resources.getDimensionPixelOffset(R.dimen.rating_interval); + + mStarDrawable.setBounds(0, 0, mRatingSize, mRatingSize); + mStarHalfDrawable.setBounds(0, 0, mRatingSize, mRatingSize); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(mRatingSize * 5 + mRatingInterval * 4, mRatingSize); + } + + @Override + protected void onDraw(Canvas canvas) { + int ratingInt = mRatingInt; + int step = mRatingSize + mRatingInterval; + int numStar = ratingInt / 2; + int numStarHalf = ratingInt % 2; + int saved = canvas.save(); + while (numStar-- > 0) { + mStarDrawable.draw(canvas); + canvas.translate(step, 0); + } + if (numStarHalf == 1) { + mStarHalfDrawable.draw(canvas); + } + canvas.restoreToCount(saved); + } + + public void setRating(float rating) { + if (mRating != rating) { + mRating = rating; + int ratingInt = Math.round(rating * 2); + if (mRatingInt != ratingInt) { + mRatingInt = ratingInt; + invalidate(); + } + } + } + + public float getRating() { + return mRating; + } +} diff --git a/app/src/main/java/com/hippo/network/HttpHelper.java b/app/src/main/java/com/hippo/network/HttpHelper.java index edca591c0..0e6427892 100644 --- a/app/src/main/java/com/hippo/network/HttpHelper.java +++ b/app/src/main/java/com/hippo/network/HttpHelper.java @@ -75,10 +75,6 @@ public class HttpHelper { private int mResponseCode = -1; - static { - System.setProperty("file.encoding", DEFAULT_CHARSET); - } - public void reset() { mResponseCode = -1; } diff --git a/app/src/main/java/com/hippo/util/LayoutManagerUtils.java b/app/src/main/java/com/hippo/util/LayoutManagerUtils.java new file mode 100644 index 000000000..cb024ffd1 --- /dev/null +++ b/app/src/main/java/com/hippo/util/LayoutManagerUtils.java @@ -0,0 +1,35 @@ +/* + * 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.util; + +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; + +public final class LayoutManagerUtils { + + public static void scrollToPositionWithOffset( + RecyclerView.LayoutManager layoutManager,int position, int offset) { + if (layoutManager instanceof LinearLayoutManager) { + ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(position, offset); + } else if (layoutManager instanceof StaggeredGridLayoutManager) { + ((StaggeredGridLayoutManager) layoutManager).scrollToPositionWithOffset(position, offset); + } else { + throw new IllegalStateException("Can't do scrollToPositionWithOffset for " + + layoutManager.getClass().getName()); + } + } +} diff --git a/app/src/main/res/drawable/ic_star.xml b/app/src/main/res/drawable/ic_star.xml new file mode 100644 index 000000000..08d5731bd --- /dev/null +++ b/app/src/main/res/drawable/ic_star.xml @@ -0,0 +1,40 @@ + + + + + + + + diff --git a/app/src/main/res/drawable/ic_star_half.xml b/app/src/main/res/drawable/ic_star_half.xml new file mode 100644 index 000000000..1c1cdfd4d --- /dev/null +++ b/app/src/main/res/drawable/ic_star_half.xml @@ -0,0 +1,41 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/item_gallery_list_detail.xml b/app/src/main/res/layout/item_gallery_list_detail.xml new file mode 100644 index 000000000..da7dcad30 --- /dev/null +++ b/app/src/main/res/layout/item_gallery_list_detail.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/widget_content_layout.xml b/app/src/main/res/layout/widget_content_layout.xml index 509258b5c..bb5d931e5 100644 --- a/app/src/main/res/layout/widget_content_layout.xml +++ b/app/src/main/res/layout/widget_content_layout.xml @@ -17,10 +17,11 @@ + xmlns:tools="http://schemas.android.com/tools" + xmlns:auto="http://schemas.android.com/apk/res-auto"> @@ -51,21 +52,24 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index bea43eed1..4c489ee69 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -15,6 +15,10 @@ --> + + 16dp + 1dp + 24dp 16dp @@ -26,6 +30,9 @@ 14dp 24dp + 80dp + 120dp + 16dp @@ -49,6 +56,10 @@ 8dp 8dp + + 8dp + 8dp + 16dp 16dp diff --git a/app/src/main/res/values/pathdata.xml b/app/src/main/res/values/pathdata.xml index 60842c05f..33f7d8b14 100644 --- a/app/src/main/res/values/pathdata.xml +++ b/app/src/main/res/values/pathdata.xml @@ -23,5 +23,7 @@ M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z M13,20H11V8L5.5,13.5L4.08,12.08L12,4.16L19.92,12.08L18.5,13.5L13,8V20Z M10.5,7A6.5,6.5 0 0,0 4,13.5A6.5,6.5 0 0,0 10.5,20H14V18H10.5C8,18 6,16 6,13.5C6,11 8,9 10.5,9H16.17L13.09,12.09L14.5,13.5L20,8L14.5,2.5L13.08,3.91L16.17,7H10.5M18,18H16V20H18V18Z + M12,17.27L18.18,21L16.54,13.97L22,9.24L14.81,8.62L12,2L9.19,8.62L2,9.24L7.45,13.97L5.82,21L12,17.27Z + M12,15.89V6.59L13.71,10.63L18.09,11L14.77,13.88L15.76,18.16M22,9.74L14.81,9.13L12,2.5L9.19,9.13L2,9.74L7.45,14.47L5.82,21.5L12,17.77L18.18,21.5L16.54,14.47L22,9.74Z diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 7a02e934c..bbfeacd33 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -93,6 +93,28 @@ @drawable/progress_large_material + + + + + + + + +