diff --git a/app/src/main/java/com/hippo/ehviewer/client/GalleryDetailParser.java b/app/src/main/java/com/hippo/ehviewer/client/GalleryDetailParser.java index 3669aabb2..510a987ed 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/GalleryDetailParser.java +++ b/app/src/main/java/com/hippo/ehviewer/client/GalleryDetailParser.java @@ -72,6 +72,10 @@ public class GalleryDetailParser { public int previewPageCount; private String sortOut(String str) { + // Avoid null + if (str == null) { + str = ""; + } return Utils.unescapeXml(str).trim(); } @@ -137,7 +141,7 @@ public class GalleryDetailParser { + ".+?" + "([\\d|,]+)" // 18 ratedTimes + "" - + "]*>Average: ([^<>]+)" // 19 rating "Average: x.xx" or "Not Yet Rated" + + "]*>([^<>]+)" // 19 rating "Average: x.xx" or "Not Yet Rated" + ".+?" + "]*>(.+?)", Pattern.DOTALL); // 20 isFavored "Favorite Gallery" for favorite m = p.matcher(body); diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java index 836377a37..66e7d6129 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryDetailScene.java @@ -16,61 +16,236 @@ package com.hippo.ehviewer.ui.scene; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.support.annotation.Nullable; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextSwitcher; import android.widget.TextView; +import android.widget.ViewSwitcher; import com.hippo.conaco.Conaco; +import com.hippo.effect.ViewTransition; import com.hippo.ehviewer.EhApplication; import com.hippo.ehviewer.EhImageKeyFactory; import com.hippo.ehviewer.R; +import com.hippo.ehviewer.client.EhClient; +import com.hippo.ehviewer.data.GalleryDetail; import com.hippo.ehviewer.data.GalleryInfo; +import com.hippo.ehviewer.util.Config; +import com.hippo.ehviewer.util.EhUtils; import com.hippo.ehviewer.widget.LoadImageView; +import com.hippo.ehviewer.widget.RatingView; +import com.hippo.rippleold.RippleSalon; +import com.hippo.scene.Announcer; import com.hippo.scene.Scene; +import com.hippo.util.Log; -public class GalleryDetailScene extends Scene { +public class GalleryDetailScene extends Scene implements View.OnClickListener { public static final String KEY_GALLERY_INFO = "gallery_info"; - private LoadImageView mThumb; - private TextView mTitle; - private TextView mUploader; + private ViewGroup mHeader; + LoadImageView mThumb; + TextView mTitle; + TextView mUploader; + TextView mCategory; + private ViewGroup mActionCard; + private View mRead; + private View mDownload; + + private ViewGroup mContent; + private TextView mLanguage; + private TextView mPages; + private TextView mSize; + private TextView mPosted; + private TextView mResize; + private TextView mFavoredTimes; + private TextSwitcher mRatingText; + private RatingView mRating; + private TextView mFavorite; + private TextView mTorrent; + private TextView mShare; + private TextView mRate; + + private View mProgressBar; + + private ViewTransition mViewTransition; + + private void handleAnnouncer(Announcer announcer) { + GalleryInfo gi; + + if (announcer == null) { + Log.e("No announcer in GalleryDetailScene, finish itself"); + finish(); + return; + } else if (null != (gi = announcer.getParcelableExtra(KEY_GALLERY_INFO))){ + Conaco conaco = EhApplication.getConaco(getStageActivity()); + conaco.load(mThumb, EhImageKeyFactory.getThumbKey(gi.gid), gi.thumb); + mTitle.setText(gi.title); + mUploader.setText(gi.uploader); + mCategory.setText(EhUtils.getCategory(gi.category)); + mCategory.setTextColor(EhUtils.getCategoryColor(gi.category)); + + EhClient.getInstance().getGalleryDetail(Config.getEhSource(), + EhClient.getDetailUrl(Config.getEhSource(), gi.gid, gi.token, 0), + new EhDetailListener()); + } + + Context context = getStageActivity(); + Resources resources = context.getResources(); + + mViewTransition.showView(1); + + RippleSalon.addRipple(mRead, false); + RippleSalon.addRipple(mDownload, false); + + mRead.setOnClickListener(this); + mDownload.setOnClickListener(this); + + mRatingText.setFactory(new RatingTextViewFactory()); + + Drawable favoriteDrawable = resources.getDrawable(R.drawable.ic_heart_theme_primary); + Drawable torrentDrawable = resources.getDrawable(R.drawable.ic_water_pump_theme_primary); + Drawable shareDrawable = resources.getDrawable(R.drawable.ic_share_theme_primary); + Drawable rateDrawable = resources.getDrawable(R.drawable.ic_thumbs_up_down_theme_primary); + + int drawableSize = resources.getDimensionPixelOffset(R.dimen.detail_action_size); + favoriteDrawable.setBounds(0, 0, drawableSize, drawableSize); + torrentDrawable.setBounds(0, 0, drawableSize, drawableSize); + shareDrawable.setBounds(0, 0, drawableSize, drawableSize); + rateDrawable.setBounds(0, 0, drawableSize, drawableSize); + + mFavorite.setCompoundDrawables(null, favoriteDrawable, null, null); + mTorrent.setCompoundDrawables(null, torrentDrawable, null, null); + mShare.setCompoundDrawables(null, shareDrawable, null, null); + mRate.setCompoundDrawables(null, rateDrawable, null, null); + } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.scene_gallery_detail); - GalleryInfo gi = getAnnouncer().getParcelableExtra(KEY_GALLERY_INFO); + mHeader = (ViewGroup) findViewById(R.id.header); + mThumb = (LoadImageView) mHeader.findViewById(R.id.thumb); + mTitle = (TextView) mHeader.findViewById(R.id.title); + mUploader = (TextView) mHeader.findViewById(R.id.uploader); + mCategory = (TextView) mHeader.findViewById(R.id.category); - mThumb = (LoadImageView) findViewById(R.id.thumb); - mThumb.bringToFront(); + mActionCard = (ViewGroup) findViewById(R.id.action_card); + mRead = mActionCard.findViewById(R.id.read); + mDownload = mActionCard.findViewById(R.id.download); - Conaco conaco = EhApplication.getConaco(getStageActivity()); - conaco.load(mThumb, EhImageKeyFactory.getThumbKey(gi.gid), gi.thumb); + mContent = (ViewGroup) findViewById(R.id.content); + mLanguage = (TextView) mContent.findViewById(R.id.language); + mPages = (TextView) mContent.findViewById(R.id.pages); + mSize = (TextView) mContent.findViewById(R.id.size); + mPosted = (TextView) mContent.findViewById(R.id.posted); + mResize = (TextView) mContent.findViewById(R.id.resize); + mFavoredTimes = (TextView) mContent.findViewById(R.id.favoredTimes); + mRatingText = (TextSwitcher) mContent.findViewById(R.id.rating_text); + mRating = (RatingView) mContent.findViewById(R.id.rating); + mFavorite = (TextView) mContent.findViewById(R.id.favorite); + mTorrent = (TextView) mContent.findViewById(R.id.torrent); + mShare = (TextView) mContent.findViewById(R.id.share); + mRate = (TextView) mContent.findViewById(R.id.rate); - mTitle = (TextView) findViewById(R.id.title); - mTitle.setText(gi.title); + mProgressBar = findViewById(R.id.progress_bar); - mUploader = (TextView) findViewById(R.id.uploader); - mUploader.setText(gi.uploader); + mViewTransition = new ViewTransition(mContent, mProgressBar); + handleAnnouncer(getAnnouncer()); + } + @Override + public void onClick(View v) { + if (v == mRead) { - /* - int source = Config.getEhSource(); - EhClient.getInstance().getGalleryDetail(source, EhClient.getDetailUrl(source, gi.gid, gi.token, 0), new EhClient.OnGetGalleryDetailListener() { - @Override - public void onSuccess(GalleryDetail galleryDetail) { - Log.d(galleryDetail.torrentUrl); - } + } else if (v == mDownload) { - @Override - public void onFailure(Exception e) { - Log.d("", e); - } - }); - */ + } + } + + private String getRatingText(float rating) { + String undefine = "(´_ゝ`)"; + if (rating == Float.NaN) { + return undefine; + } + + int resId = 0; + switch (Math.round(rating * 2)) { + case 0: + resId = R.string.rating0; break; + case 1: + resId = R.string.rating1; break; + case 2: + resId = R.string.rating2; break; + case 3: + resId = R.string.rating3; break; + case 4: + resId = R.string.rating4; break; + case 5: + resId = R.string.rating5; break; + case 6: + resId = R.string.rating6; break; + case 7: + resId = R.string.rating7; break; + case 8: + resId = R.string.rating8; break; + case 9: + resId = R.string.rating9; break; + case 10: + resId = R.string.rating10; break; + } + + if (resId == 0) { + return undefine; + } else { + return getStageActivity().getString(resId); + } + } + + private String getAllRatingText(float rating, int ratedTimes) { + return String.format(getStageActivity().getString(R.string.we_feel), getRatingText(rating)) + + " (" + rating + ", " + ratedTimes + ")"; + } + + private class RatingTextViewFactory implements ViewSwitcher.ViewFactory { + @Override + public View makeView() { + TextView tv = new TextView(getStageActivity()); + tv.setGravity(Gravity.CENTER); + return tv; + } + } + + private class EhDetailListener extends EhClient.OnGetGalleryDetailListener { + + @Override + public void onSuccess(GalleryDetail galleryDetail) { + Resources resources = getStageActivity().getResources(); + mLanguage.setText(galleryDetail.language); + mPages.setText(String.format(resources.getString(R.string.page_count), + galleryDetail.pageCount)); + mSize.setText(galleryDetail.size); + mPosted.setText(galleryDetail.posted); + mResize.setText(galleryDetail.resize); + mFavoredTimes.setText(String.format(resources.getString(R.string.favorited_times), + galleryDetail.favoredTimes)); + mRating.setRating(galleryDetail.rating); + mRatingText.setText(getAllRatingText(galleryDetail.rating, galleryDetail.ratedTimes)); + mViewTransition.showView(0); + } + + @Override + public void onFailure(Exception e) { + e.printStackTrace(); + } } } 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 25c68cdf7..e76e39fcb 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 @@ -56,7 +56,7 @@ import com.hippo.ehviewer.util.EhUtils; import com.hippo.ehviewer.widget.ContentLayout; import com.hippo.ehviewer.widget.LoadImageView; import com.hippo.ehviewer.widget.OffsetLayout; -import com.hippo.ehviewer.widget.RatingView; +import com.hippo.ehviewer.widget.SimpleRatingView; import com.hippo.ehviewer.widget.SearchBar; import com.hippo.ehviewer.widget.SearchDatabase; import com.hippo.ehviewer.widget.SearchLayout; @@ -757,25 +757,27 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper, @Override public View[] getFromViewSet(@NonNull Scene fromScene) { - View[] views = new View[3]; + View[] views = new View[4]; GalleryListScene scene = (GalleryListScene) fromScene; RecyclerView.ViewHolder viewHolder = scene.mContentRecyclerView.findViewHolderForAdapterPosition(mPosition); if (viewHolder != null) { GalleryHolder gh = (GalleryHolder) viewHolder; - views[0] = gh.thumb; - views[1] = gh.title; - views[2] = gh.uploader; + views[0] = gh.thumb; + views[1] = gh.title; + views[2] = gh.uploader; + views[3] = gh.category; } return views; } @Override public View[] getToViewSet(@NonNull Scene toScene) { - View[] views = new View[3]; - View sceneView = toScene.getSceneView(); - views[0] = sceneView.findViewById(R.id.thumb); - views[1] = sceneView.findViewById(R.id.title); - views[2] = sceneView.findViewById(R.id.uploader); + View[] views = new View[4]; + GalleryDetailScene scene = (GalleryDetailScene) toScene; + views[0] = scene.mThumb; + views[1] = scene.mTitle; + views[2] = scene.mUploader; + views[3] = scene.mCategory; return views; } } @@ -820,7 +822,7 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper, public LoadImageView thumb; public TextView title; public TextView uploader; - public RatingView rating; + public SimpleRatingView rating; public TextView category; public TextView posted; public TextView simpleLanguage; @@ -830,7 +832,7 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper, thumb = (LoadImageView) 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); + rating = (SimpleRatingView) 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); diff --git a/app/src/main/java/com/hippo/ehviewer/widget/RatingView.java b/app/src/main/java/com/hippo/ehviewer/widget/RatingView.java index 63b522b08..2ba380d85 100644 --- a/app/src/main/java/com/hippo/ehviewer/widget/RatingView.java +++ b/app/src/main/java/com/hippo/ehviewer/widget/RatingView.java @@ -1,95 +1,111 @@ -/* - * 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 - * distributed under the License is distributed on an "AS IS" BASIS, - * 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.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; import com.hippo.ehviewer.R; +import com.hippo.util.ViewUtils; public class RatingView extends View { private Drawable mStarDrawable; private Drawable mStarHalfDrawable; - private int mRatingSize; - private int mRatingInterval; + private Drawable mStarOutlineDrawable; + private float mStarSize; + private float mStarInterval; + private int mStarCount; + private boolean mIndicator; + private float mMax; private float mRating; - private int mRatingInt; + + private int mShownStarCount; + private int mShownStarHalfCount; + private int mShownStarOutlineCount; + + private OnRatingChangeListener mOnRatingChangeListener; public RatingView(Context context) { super(context); - init(context); + init(context, null); } public RatingView(Context context, AttributeSet attrs) { super(context, attrs); - init(context); + init(context, attrs); } public RatingView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - init(context); + init(context, attrs); } - 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); + private void init(Context context, AttributeSet attrs) { + mStarDrawable = context.getResources().getDrawable(R.drawable.ic_star_theme_accent); + mStarHalfDrawable = context.getResources().getDrawable(R.drawable.ic_star_half_theme_accent); + mStarOutlineDrawable = context.getResources().getDrawable(R.drawable.ic_star_outline_theme_accent); - mStarDrawable.setBounds(0, 0, mRatingSize, mRatingSize); - mStarHalfDrawable.setBounds(0, 0, mRatingSize, mRatingSize); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RatingView); + mStarSize = a.getDimension(R.styleable.RatingView_starSize, 10); + mStarInterval = a.getDimension(R.styleable.RatingView_starInterval, 10); + mStarCount = a.getInt(R.styleable.RatingView_starCount, 5); + mIndicator = a.getBoolean(R.styleable.RatingView_isIndicator, true); + mMax = a.getFloat(R.styleable.RatingView_max, 10f); + mRating = a.getFloat(R.styleable.RatingView_rating, 0f); + + a.recycle(); + + updateBounds(); + updateShownCount(); } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(mRatingSize * 5 + mRatingInterval * 4, mRatingSize); + private void updateBounds() { + int starSize = (int) mStarSize; + mStarDrawable.setBounds(0, 0, starSize, starSize); + mStarHalfDrawable.setBounds(0, 0, starSize, starSize); + mStarOutlineDrawable.setBounds(0, 0, starSize, starSize); } - @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); + private void updateShownCount() { + float step = mMax / mStarCount / 2; + int shown = Math.round(mRating / step); + if (shown >= mStarCount * 2) { + mShownStarCount = mStarCount; + mShownStarHalfCount = 0; + mShownStarOutlineCount = 0; + } else { + mShownStarCount = shown / 2; + mShownStarHalfCount = shown % 2; + mShownStarOutlineCount = mStarCount - mShownStarCount - mShownStarHalfCount; } - if (numStarHalf == 1) { - mStarHalfDrawable.draw(canvas); - } - canvas.restoreToCount(saved); + } + + public void setOnRatingChangeListener(OnRatingChangeListener listener) { + mOnRatingChangeListener = listener; + } + + public void setIndicator(boolean indicator) { + mIndicator = indicator; + } + + public boolean isIndicator() { + return mIndicator; } public void setRating(float rating) { if (mRating != rating) { + float oldRating = mRating; mRating = rating; - int ratingInt = Math.round(rating * 2); - if (mRatingInt != ratingInt) { - mRatingInt = ratingInt; - invalidate(); + updateShownCount(); + invalidate(); + if (mOnRatingChangeListener != null) { + mOnRatingChangeListener.onRatingChange(oldRating, rating, false, true); } } } @@ -97,4 +113,93 @@ public class RatingView extends View { public float getRating() { return mRating; } + + @Override + protected int getSuggestedMinimumWidth() { + return Math.max(super.getSuggestedMinimumWidth(), + (int) ((mStarSize * mStarCount) + (mStarInterval * (mStarCount - 1)))); + } + + @Override + protected int getSuggestedMinimumHeight() { + return Math.max(super.getSuggestedMinimumHeight(), (int) mStarSize); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(ViewUtils.getSuitableSize(getSuggestedMinimumWidth(), widthMeasureSpec), + ViewUtils.getSuitableSize(getSuggestedMinimumHeight(), heightMeasureSpec)); + } + + @Override + protected void onDraw(Canvas canvas) { + int saved = canvas.save(); + + float moveStep = mStarSize + mStarInterval; + int count = mShownStarCount; + while (count-- > 0) { + mStarDrawable.draw(canvas); + canvas.translate(moveStep, 0); + } + count = mShownStarHalfCount; + while (count-- > 0) { + mStarHalfDrawable.draw(canvas); + canvas.translate(moveStep, 0); + } + count = mShownStarOutlineCount; + while (count-- > 0) { + mStarOutlineDrawable.draw(canvas); + canvas.translate(moveStep, 0); + } + + canvas.restoreToCount(saved); + } + + private float getRatingByX(float x) { + float step = mStarSize + mStarInterval; + float sum = x + mStarInterval; + float ratingStep = mMax / mStarCount / 2; + int count = (int) (sum / step) * 2; + float remain = sum - (count / 2 * step); + if (remain > mStarInterval + (mStarSize / 2)) { + count += 2; + } else if (remain > mStarInterval) { + count += 1; + } + count = Math.min(mStarCount * 2, count); + return ratingStep * count; + } + + @Override + public boolean onTouchEvent(@NonNull MotionEvent event) { + if (!mIndicator) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_MOVE: + float rating = getRatingByX(event.getX()); + if (mRating != rating) { + float oldRating = mRating; + mRating = rating; + updateShownCount(); + invalidate(); + if (mOnRatingChangeListener != null) { + mOnRatingChangeListener.onRatingChange(oldRating, rating, true, false); + } + } + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (mOnRatingChangeListener != null) { + mOnRatingChangeListener.onRatingChange(mRating, mRating, true, true); + } + break; + } + return true; + } else { + return false; + } + } + + public interface OnRatingChangeListener { + void onRatingChange(float oldRating, float newRating, boolean byUser, boolean confirm); + } } diff --git a/app/src/main/java/com/hippo/ehviewer/widget/SimpleRatingView.java b/app/src/main/java/com/hippo/ehviewer/widget/SimpleRatingView.java new file mode 100644 index 000000000..a5423e4cd --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/widget/SimpleRatingView.java @@ -0,0 +1,109 @@ +/* + * 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 + * distributed under the License is distributed on an "AS IS" BASIS, + * 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 SimpleRatingView extends View { + + private Drawable mStarDrawable; + private Drawable mStarHalfDrawable; + private Drawable mStarOutlineDrawable; + private int mRatingSize; + private int mRatingInterval; + + private float mRating; + private int mRatingInt; + + public SimpleRatingView(Context context) { + super(context); + init(context); + } + + public SimpleRatingView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + } + + public SimpleRatingView(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); + mStarOutlineDrawable = resources.getDrawable(R.drawable.ic_star_outline); + 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); + mStarOutlineDrawable.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.translate(step, 0); + } + int numOutline = 5 - numStar - numStarHalf; + while (numOutline-- > 0) { + mStarOutlineDrawable.draw(canvas); + canvas.translate(step, 0); + } + 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/util/Utils.java b/app/src/main/java/com/hippo/util/Utils.java index 36f5415a5..0033e3586 100644 --- a/app/src/main/java/com/hippo/util/Utils.java +++ b/app/src/main/java/com/hippo/util/Utils.java @@ -274,21 +274,23 @@ public final class Utils { } private static final String[] ESCAPE_CHARATER_LIST = { - "&", - "<", - ">", - """, - "'", - "×" + "&", + "<", + ">", + """, + "'", + "×", + " " }; private static final String[] UNESCAPE_CHARATER_LIST = { - "&", - "<", - ">", - "\"", - "'", - "×" + "&", + "<", + ">", + "\"", + "'", + "×", + " " }; /** diff --git a/app/src/main/java/com/hippo/widget/CardButton.java b/app/src/main/java/com/hippo/widget/CardButton.java new file mode 100644 index 000000000..7e8b87c91 --- /dev/null +++ b/app/src/main/java/com/hippo/widget/CardButton.java @@ -0,0 +1,106 @@ +package com.hippo.widget; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.widget.Button; + +import com.hippo.cardsalon.CardHelper; +import com.hippo.cardsalon.CardViewDelegate; + +public class CardButton extends Button implements CardViewDelegate { + + private CardHelper mCardHelper; + + public CardButton(Context context) { + super(context); + init(context, null); + } + + public CardButton(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public CardButton(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + mCardHelper = new CardHelper(this); + mCardHelper.initialize(context, attrs); + } + + @Override + public void setBackgroundResource(int resid) { + // Empty + } + + @SuppressWarnings("deprecation") + @Override + public void setBackgroundDrawable(Drawable drawable) { + // Empty + } + + @Override + public void setRawPadding(int left, int top, int right, int bottom) { + super.setPadding(left, top, right, bottom); + } + + @SuppressWarnings("deprecation") + @Override + public void setRawBackgroundDrawable(Drawable drawable) { + super.setBackgroundDrawable(drawable); + } + + @Override + public void setCardRadius(float radius) { + mCardHelper.setCardRadius(radius); + } + + @Override + public float getCardRadius() { + return mCardHelper.getCardRadius(); + } + + @Override + public void setCardBackgroundColor(int color) { + mCardHelper.setCardBackgroundColor(color); + } + + @Override + public int getCardBackgroundColor() { + return mCardHelper.getCardBackgroundColor(); + } + + @Override + public void setCardBoundSize(float size) { + mCardHelper.setCardBoundSize(size); + } + + @Override + public float getCardBoundSize() { + return mCardHelper.getCardBoundSize(); + } + + @Override + public void setCardBoundColor(int color) { + mCardHelper.setCardBoundColor(color); + } + + @Override + public int getCardBoundColor() { + return mCardHelper.getCardBoundColor(); + } + + @Override + public void setCardElevation(float elevation) { + mCardHelper.setCardElevation(elevation); + } + + @Override + public float getCardElevation() { + return mCardHelper.getCardElevation(); + } +} diff --git a/app/src/main/java/com/hippo/widget/CardLinearLayout.java b/app/src/main/java/com/hippo/widget/CardLinearLayout.java new file mode 100644 index 000000000..93978f29e --- /dev/null +++ b/app/src/main/java/com/hippo/widget/CardLinearLayout.java @@ -0,0 +1,111 @@ +package com.hippo.widget; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.widget.LinearLayout; + +import com.hippo.cardsalon.CardHelper; +import com.hippo.cardsalon.CardViewDelegate; + +public class CardLinearLayout extends LinearLayout implements CardViewDelegate { + + private CardHelper mCardHelper; + + public CardLinearLayout(Context context) { + super(context); + init(context, null); + } + + public CardLinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public CardLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + mCardHelper = new CardHelper(this); + mCardHelper.initialize(context, attrs); + } + + @Override + public void setBackgroundResource(int resid) { + // Empty + } + + @SuppressWarnings("deprecation") + @Override + public void setBackgroundDrawable(Drawable drawable) { + // Empty + } + + @Override + public void setPadding(int left, int top, int right, int bottom) { + mCardHelper.setPadding(left, top, right, bottom); + } + + @Override + public void setRawPadding(int left, int top, int right, int bottom) { + super.setPadding(left, top, right, bottom); + } + + @SuppressWarnings("deprecation") + @Override + public void setRawBackgroundDrawable(Drawable drawable) { + super.setBackgroundDrawable(drawable); + } + + @Override + public void setCardRadius(float radius) { + mCardHelper.setCardRadius(radius); + } + + @Override + public float getCardRadius() { + return mCardHelper.getCardRadius(); + } + + @Override + public void setCardBackgroundColor(int color) { + mCardHelper.setCardBackgroundColor(color); + } + + @Override + public int getCardBackgroundColor() { + return mCardHelper.getCardBackgroundColor(); + } + + @Override + public void setCardBoundSize(float size) { + mCardHelper.setCardBoundSize(size); + } + + @Override + public float getCardBoundSize() { + return mCardHelper.getCardBoundSize(); + } + + @Override + public void setCardBoundColor(int color) { + mCardHelper.setCardBoundColor(color); + } + + @Override + public int getCardBoundColor() { + return mCardHelper.getCardBoundColor(); + } + + @Override + public void setCardElevation(float elevation) { + mCardHelper.setCardElevation(elevation); + } + + @Override + public float getCardElevation() { + return mCardHelper.getCardElevation(); + } +} diff --git a/app/src/main/res/anim/fade_in.xml b/app/src/main/res/anim/fade_in.xml new file mode 100644 index 000000000..d9353fdd4 --- /dev/null +++ b/app/src/main/res/anim/fade_in.xml @@ -0,0 +1,20 @@ + + + diff --git a/app/src/main/res/anim/fade_out.xml b/app/src/main/res/anim/fade_out.xml new file mode 100644 index 000000000..fe4132b74 --- /dev/null +++ b/app/src/main/res/anim/fade_out.xml @@ -0,0 +1,20 @@ + + + diff --git a/app/src/main/res/drawable/ic_heart_theme_primary.xml b/app/src/main/res/drawable/ic_heart_theme_primary.xml new file mode 100644 index 000000000..8c6b800a3 --- /dev/null +++ b/app/src/main/res/drawable/ic_heart_theme_primary.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_share_theme_primary.xml b/app/src/main/res/drawable/ic_share_theme_primary.xml new file mode 100644 index 000000000..3f0084620 --- /dev/null +++ b/app/src/main/res/drawable/ic_share_theme_primary.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_star.xml b/app/src/main/res/drawable/ic_star.xml index 08d5731bd..20ccfbfe3 100644 --- a/app/src/main/res/drawable/ic_star.xml +++ b/app/src/main/res/drawable/ic_star.xml @@ -1,5 +1,4 @@ - - + + + + + + diff --git a/app/src/main/res/drawable/ic_star_outline.xml b/app/src/main/res/drawable/ic_star_outline.xml new file mode 100644 index 000000000..bbc03d9c4 --- /dev/null +++ b/app/src/main/res/drawable/ic_star_outline.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_star_outline_theme_accent.xml b/app/src/main/res/drawable/ic_star_outline_theme_accent.xml new file mode 100644 index 000000000..6b1f06246 --- /dev/null +++ b/app/src/main/res/drawable/ic_star_outline_theme_accent.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_star_theme_accent.xml b/app/src/main/res/drawable/ic_star_theme_accent.xml new file mode 100644 index 000000000..98529e229 --- /dev/null +++ b/app/src/main/res/drawable/ic_star_theme_accent.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_thumbs_up_down_theme_primary.xml b/app/src/main/res/drawable/ic_thumbs_up_down_theme_primary.xml new file mode 100644 index 000000000..fda917a3d --- /dev/null +++ b/app/src/main/res/drawable/ic_thumbs_up_down_theme_primary.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/app/src/main/res/drawable/ic_water_pump_theme_primary.xml b/app/src/main/res/drawable/ic_water_pump_theme_primary.xml new file mode 100644 index 000000000..fba2a1179 --- /dev/null +++ b/app/src/main/res/drawable/ic_water_pump_theme_primary.xml @@ -0,0 +1,39 @@ + + + + + + + diff --git a/app/src/main/res/layout-land/widget_select_search_image_layout.xml b/app/src/main/res/layout-land/widget_select_search_image_layout.xml index 33f5e30ac..f377868b1 100644 --- a/app/src/main/res/layout-land/widget_select_search_image_layout.xml +++ b/app/src/main/res/layout-land/widget_select_search_image_layout.xml @@ -25,7 +25,7 @@ diff --git a/app/src/main/res/layout-sw600dp/widget_select_search_image_layout.xml b/app/src/main/res/layout-sw600dp/widget_select_search_image_layout.xml index 33f5e30ac..f377868b1 100644 --- a/app/src/main/res/layout-sw600dp/widget_select_search_image_layout.xml +++ b/app/src/main/res/layout-sw600dp/widget_select_search_image_layout.xml @@ -25,7 +25,7 @@ - - - - - - - - + android:layout_height="match_parent"> + android:layout_height="wrap_content"> - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_height="wrap_content" + android:background="@color/theme_primary" + android:elevation="4dp"> + + - + + + + + + + + + + + + + + + + + + + - - diff --git a/app/src/main/res/layout/item_gallery_list_detail.xml b/app/src/main/res/layout/item_gallery_list_detail.xml index 971acd442..a26cc6c0f 100644 --- a/app/src/main/res/layout/item_gallery_list_detail.xml +++ b/app/src/main/res/layout/item_gallery_list_detail.xml @@ -52,7 +52,7 @@ android:layout_marginTop="2dp" tools:ignore="RtlHardcoded"/> - + + + + + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index ec3286238..8066bcb69 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -52,6 +52,7 @@ #fff06292 @android:color/black + #ffe91e63 #ff009688 #ff00796b #ffff5722 @@ -62,6 +63,8 @@ #ff7cb342 #fff9a825 #ffff7043 + #ff3f51b5 + #ff303f9f #de000000 @@ -74,9 +77,9 @@ #ffeeeeee #ffe1e1e0 - #ff3367d6 - #ff2451b2 - #ffd63367 + @color/material_indigo_500 + @color/material_indigo_700 + @color/material_pink_500 @android:color/white diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 57231265e..cc661e167 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -93,6 +93,8 @@ 8dp + 48dp + 16dp diff --git a/app/src/main/res/values/pathdata.xml b/app/src/main/res/values/pathdata.xml index 43621cc1f..3ffa905fe 100644 --- a/app/src/main/res/values/pathdata.xml +++ b/app/src/main/res/values/pathdata.xml @@ -23,6 +23,7 @@ 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 + M12,15.39L8.24,17.66L9.23,13.38L5.91,10.5L10.29,10.13L12,6.09L13.71,10.13L18.09,10.5L14.77,13.38L15.76,17.66M22,9.24L14.81,8.63L12,2L9.19,8.63L2,9.24L7.45,13.97L5.82,21L12,17.27L18.18,21L16.54,13.97L22,9.24Z M10,20V14H14V20H19V12H22L12,3L2,12H5V20H10Z M11.71,19C9.93,19 8.5,17.59 8.5,15.86C8.5,14.24 9.53,13.1 11.3,12.74C13.07,12.38 14.9,11.53 15.92,10.16C16.31,11.45 16.5,12.81 16.5,14.2C16.5,16.84 14.36,19 11.71,19M13.5,0.67C13.5,0.67 14.24,3.32 14.24,5.47C14.24,7.53 12.89,9.2 10.83,9.2C8.76,9.2 7.2,7.53 7.2,5.47L7.23,5.1C5.21,7.5 4,10.61 4,14A8,8 0 0,0 12,22A8,8 0 0,0 20,14C20,8.6 17.41,3.8 13.5,0.67Z M11,7V12.11L15.71,14.9L16.5,13.62L12.5,11.25V7M12.5,2C8.97,2 5.91,3.92 4.27,6.77L2,4.5V11H8.5L5.75,8.25C6.96,5.73 9.5,4 12.5,4A7.5,7.5 0 0,1 20,11.5A7.5,7.5 0 0,1 12.5,19C9.23,19 6.47,16.91 5.44,14H3.34C4.44,18.03 8.11,21 12.5,21C17.74,21 22,16.75 22,11.5A9.5,9.5 0 0,0 12.5,2Z @@ -34,5 +35,8 @@ M3 10v-5a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v5l-6 2l-6 -4l-6 2M3 14v5a2 2 0 0 0 2 2h14a2 2 0 0 0 2 -2v-5l-6 2l-6 -4l-6 2z M10,2A2,2 0 0,1 12,4V8.5C12,8.5 14,8.25 14,9.25C14,9.25 16,9 16,10C16,10 18,9.75 18,10.75C18,10.75 20,10.5 20,11.5V15C20,16 17,21 17,22H9C9,22 7,15 4,13C4,13 3,7 8,12V4A2,2 0 0,1 10,2Z M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12C4,14.39 5.05,16.53 6.71,18H9V12H17L19.15,15.59C19.69,14.5 20,13.29 20,12A8,8 0 0,0 12,4Z + M19,14.5C19,14.5 21,16.67 21,18A2,2 0 0,1 19,20A2,2 0 0,1 17,18C17,16.67 19,14.5 19,14.5M5,18V9A2,2 0 0,1 3,7A2,2 0 0,1 5,5V4A2,2 0 0,1 7,2H9A2,2 0 0,1 11,4V5H19A2,2 0 0,1 21,7V9L21,11A1,1 0 0,1 22,12A1,1 0 0,1 21,13H17A1,1 0 0,1 16,12A1,1 0 0,1 17,11V9H11V18H12A2,2 0 0,1 14,20V22H2V20A2,2 0 0,1 4,18H5Z + M18,16.08C17.24,16.08 16.56,16.38 16.04,16.85L8.91,12.7C8.96,12.47 9,12.24 9,12C9,11.76 8.96,11.53 8.91,11.3L15.96,7.19C16.5,7.69 17.21,8 18,8A3,3 0 0,0 21,5A3,3 0 0,0 18,2A3,3 0 0,0 15,5C15,5.24 15.04,5.47 15.09,5.7L8.04,9.81C7.5,9.31 6.79,9 6,9A3,3 0 0,0 3,12A3,3 0 0,0 6,15C6.79,15 7.5,14.69 8.04,14.19L15.16,18.34C15.11,18.55 15.08,18.77 15.08,19C15.08,20.61 16.39,21.91 18,21.91C19.61,21.91 20.92,20.61 20.92,19A2.92,2.92 0 0,0 18,16.08Z + M22.5,10.5H15.75C15.13,10.5 14.6,10.88 14.37,11.41L12.11,16.7C12.04,16.87 12,17.06 12,17.25V18.5A1,1 0 0,0 13,19.5H18.18L17.5,22.68V22.92C17.5,23.23 17.63,23.5 17.83,23.72L18.62,24.5L23.56,19.56C23.83,19.29 24,18.91 24,18.5V12A1.5,1.5 0 0,0 22.5,10.5M12,6.5A1,1 0 0,0 11,5.5H5.82L6.5,2.32V2.09C6.5,1.78 6.37,1.5 6.17,1.29L5.38,0.5L0.44,5.44C0.17,5.71 0,6.09 0,6.5V13A1.5,1.5 0 0,0 1.5,14.5H8.25C8.87,14.5 9.4,14.12 9.63,13.59L11.89,8.3C11.96,8.13 12,7.94 12,7.75V6.5Z diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cfd2d43ac..a575cfd44 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -77,6 +77,24 @@ Please enter a number The page is invaild + + %d pages + %d \u2665 + We feel %s + + + MASTERPIECE + AMAZING + GREAT + GOOD + OKAY + MEDIOCRE + BAD + AWFUL + PAINFUL + UNBEARABLE + DISASTER + Timeout Unknown host @@ -122,4 +140,8 @@ Username Password + Read + Torrent + Share + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 2bffea35b..38c16a911 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -62,7 +62,7 @@ @dimen/category_table_item_height - + + + + + +