Update detail scene
This commit is contained in:
1 parent
a26686c31b
commit
57acf0585d
15 files changed
+973
-71
No files matched your search
@@ -0,0 +1,53 @@
|
||||
package com.hippo.drawable;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.conaco.Unikery;
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class UnikeryDrawable extends WrapDrawable implements Unikery {
|
||||
|
||||
private int mTaskId;
|
||||
|
||||
private View mView;
|
||||
|
||||
public UnikeryDrawable(View view) {
|
||||
mView = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBitmap(Bitmap bitmap, Conaco.Source source) {
|
||||
setDrawable(new BitmapDrawable(mView.getResources(), bitmap));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDrawable(Drawable drawable) {
|
||||
super.setDrawable(drawable);
|
||||
updateBounds();
|
||||
mView.requestLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTaskId(int id) {
|
||||
mTaskId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTaskId() {
|
||||
return mTaskId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure() {
|
||||
setDrawable(mView.getResources().getDrawable(R.drawable.ic_sad));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.hippo.drawable;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
public class WrapDrawable extends Drawable {
|
||||
|
||||
private Drawable mDrawable;
|
||||
|
||||
public void setDrawable(Drawable drawable) {
|
||||
mDrawable = drawable;
|
||||
}
|
||||
|
||||
public void updateBounds() {
|
||||
setBounds(0, 0, getIntrinsicWidth(), getIntrinsicHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBounds(int left, int top, int right, int bottom) {
|
||||
super.setBounds(left, top, right, bottom);
|
||||
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setBounds(left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBounds(Rect bounds) {
|
||||
super.setBounds(bounds);
|
||||
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setBounds(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChangingConfigurations(int configs) {
|
||||
super.setChangingConfigurations(configs);
|
||||
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setChangingConfigurations(configs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChangingConfigurations() {
|
||||
if (mDrawable != null) {
|
||||
return mDrawable.getChangingConfigurations();
|
||||
} else {
|
||||
return super.getChangingConfigurations();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDither(boolean dither) {
|
||||
super.setDither(dither);
|
||||
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setDither(dither);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFilterBitmap(boolean filter) {
|
||||
super.setFilterBitmap(filter);
|
||||
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setFilterBitmap(filter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setColorFilter(cf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
if (mDrawable != null) {
|
||||
return mDrawable.getOpacity();
|
||||
} else {
|
||||
return PixelFormat.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
if (mDrawable != null) {
|
||||
return mDrawable.getIntrinsicWidth();
|
||||
} else {
|
||||
return super.getIntrinsicWidth();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicHeight() {
|
||||
if (mDrawable != null) {
|
||||
return mDrawable.getIntrinsicHeight();
|
||||
} else {
|
||||
return super.getIntrinsicHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,15 +22,28 @@ import com.hippo.ehviewer.util.EhUtils;
|
||||
import com.hippo.util.AssertUtils;
|
||||
import com.hippo.util.Utils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class GalleryDetailParser {
|
||||
|
||||
private static final DateFormat WEB_COMMENT_DATA_FORMAT = new SimpleDateFormat("dd MMMMM yyyy, HH:mm z", Locale.US);
|
||||
private static final DateFormat OUT_COMMENT_DATA_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.US);
|
||||
|
||||
static {
|
||||
WEB_COMMENT_DATA_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
OUT_COMMENT_DATA_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
}
|
||||
|
||||
private static final String OFFENSIVE_STRING =
|
||||
"<p>(And if you choose to ignore this warning, you lose all rights to complain about it in the future.)</p>";
|
||||
private static final String PINING_STRING =
|
||||
@@ -209,6 +222,7 @@ public class GalleryDetailParser {
|
||||
TagGroup tagGroup = new TagGroup();
|
||||
tagGroup.groupName = sortOut(m.group(1));
|
||||
parseTagGroup(tagGroup, m.group(0));
|
||||
tags.add(tagGroup);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +246,15 @@ public class GalleryDetailParser {
|
||||
m = p.matcher(body);
|
||||
comments = new LinkedList<>();
|
||||
while (m.find()) {
|
||||
comments.add(new Comment(sortOut(m.group(1)), sortOut(m.group(2)), m.group(3)));
|
||||
String webDateString = sortOut(m.group(1));
|
||||
Date date;
|
||||
try {
|
||||
date = WEB_COMMENT_DATA_FORMAT.parse(webDateString);
|
||||
} catch (java.text.ParseException e) {
|
||||
date = new Date(0l);
|
||||
}
|
||||
String outDateString = OUT_COMMENT_DATA_FORMAT.format(date);
|
||||
comments.add(new Comment(outDateString, date, sortOut(m.group(2)), m.group(3)));
|
||||
}
|
||||
Collections.sort(comments, COMMENT_SORTER);
|
||||
}
|
||||
@@ -257,67 +279,10 @@ public class GalleryDetailParser {
|
||||
}
|
||||
|
||||
static class CommentSort implements Comparator<Comment> {
|
||||
private int compareNum(String n1, String n2, int median) {
|
||||
int re = 0;
|
||||
for (int i = 0; i < median; i++) {
|
||||
re *= 10;
|
||||
re += n1.charAt(i) - n2.charAt(i);
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
private int getMonth(String m) {
|
||||
if (m.equals("January"))
|
||||
return 1;
|
||||
else if (m.equals("February"))
|
||||
return 2;
|
||||
else if (m.equals("March"))
|
||||
return 3;
|
||||
else if (m.equals("April"))
|
||||
return 4;
|
||||
else if (m.equals("May"))
|
||||
return 5;
|
||||
else if (m.equals("June"))
|
||||
return 6;
|
||||
else if (m.equals("July"))
|
||||
return 7;
|
||||
else if (m.equals("August"))
|
||||
return 8;
|
||||
else if (m.equals("September"))
|
||||
return 9;
|
||||
else if (m.equals("October"))
|
||||
return 10;
|
||||
else if (m.equals("November"))
|
||||
return 11;
|
||||
else if (m.equals("December"))
|
||||
return 12;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(Comment c1, Comment c2) {
|
||||
int re = 0;
|
||||
Pattern p = Pattern.compile("(\\d{2}) (\\w+) (\\d{4}), (\\d{2}):(\\d{2})");
|
||||
Matcher m1 = p.matcher(c1.time);
|
||||
Matcher m2 = p.matcher(c2.time);
|
||||
if (!m1.find() || !m2.find())
|
||||
return 0;
|
||||
// year
|
||||
re += compareNum(m1.group(3), m2.group(3), 4);
|
||||
re <<= 4;
|
||||
// Month
|
||||
re += getMonth(m1.group(2)) - getMonth(m2.group(2));
|
||||
re <<= 5;
|
||||
// Day
|
||||
re += compareNum(m1.group(1), m2.group(1), 2);
|
||||
re <<= 5;
|
||||
// Hour
|
||||
re += compareNum(m1.group(4), m2.group(4), 2);
|
||||
re <<= 6;
|
||||
// Minute
|
||||
re += compareNum(m1.group(5), m2.group(5), 2);
|
||||
return re;
|
||||
return c1.date.compareTo(c2.date);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,17 @@
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class Comment {
|
||||
public String time;
|
||||
public Date date;
|
||||
public String user;
|
||||
public String comment;
|
||||
|
||||
public Comment (String time, String user, String comment) {
|
||||
public Comment (String time, Date date, String user, String comment) {
|
||||
this.time = time;
|
||||
this.date = date;
|
||||
this.user = user;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
@@ -16,14 +16,19 @@
|
||||
|
||||
package com.hippo.ehviewer.ui.scene;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
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.text.Html;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextSwitcher;
|
||||
import android.widget.TextView;
|
||||
import android.widget.ViewSwitcher;
|
||||
@@ -34,21 +39,31 @@ 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.Comment;
|
||||
import com.hippo.ehviewer.data.GalleryDetail;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.data.TagGroup;
|
||||
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.miscellaneous.StartActivityHelper;
|
||||
import com.hippo.rippleold.RippleSalon;
|
||||
import com.hippo.scene.Announcer;
|
||||
import com.hippo.scene.Scene;
|
||||
import com.hippo.util.Log;
|
||||
import com.hippo.util.URLImageGetter;
|
||||
import com.hippo.util.UiUtils;
|
||||
import com.hippo.widget.AutoWrapLayout;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
|
||||
public static final String KEY_GALLERY_INFO = "gallery_info";
|
||||
|
||||
private FrameLayout mDetailFrameLayout;
|
||||
|
||||
private ViewGroup mHeader;
|
||||
LoadImageView mThumb;
|
||||
TextView mTitle;
|
||||
@@ -72,11 +87,16 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
private TextView mTorrent;
|
||||
private TextView mShare;
|
||||
private TextView mRate;
|
||||
private LinearLayout mTag;
|
||||
private LinearLayout mComment;
|
||||
private TextView mCommentMore;
|
||||
|
||||
private View mProgressBar;
|
||||
|
||||
private ViewTransition mViewTransition;
|
||||
|
||||
private GalleryDetail mGalleryDetail;
|
||||
|
||||
private void handleAnnouncer(Announcer announcer) {
|
||||
GalleryInfo gi;
|
||||
|
||||
@@ -100,13 +120,7 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
Context context = getStageActivity();
|
||||
Resources resources = context.getResources();
|
||||
|
||||
mViewTransition.showView(1);
|
||||
|
||||
RippleSalon.addRipple(mRead, false);
|
||||
RippleSalon.addRipple(mDownload, false);
|
||||
|
||||
mRead.setOnClickListener(this);
|
||||
mDownload.setOnClickListener(this);
|
||||
mViewTransition.showView(1, false);
|
||||
|
||||
mRatingText.setFactory(new RatingTextViewFactory());
|
||||
|
||||
@@ -125,6 +139,20 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
mTorrent.setCompoundDrawables(null, torrentDrawable, null, null);
|
||||
mShare.setCompoundDrawables(null, shareDrawable, null, null);
|
||||
mRate.setCompoundDrawables(null, rateDrawable, null, null);
|
||||
|
||||
mRead.setOnClickListener(this);
|
||||
mDownload.setOnClickListener(this);
|
||||
mFavorite.setOnClickListener(this);
|
||||
mTorrent.setOnClickListener(this);
|
||||
mShare.setOnClickListener(this);
|
||||
mRate.setOnClickListener(this);
|
||||
|
||||
RippleSalon.addRipple(mRead, false);
|
||||
RippleSalon.addRipple(mDownload, false);
|
||||
RippleSalon.addRipple(mFavorite, false);
|
||||
RippleSalon.addRipple(mTorrent, false);
|
||||
RippleSalon.addRipple(mShare, false);
|
||||
RippleSalon.addRipple(mRate, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,6 +160,8 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.scene_gallery_detail);
|
||||
|
||||
mDetailFrameLayout = (FrameLayout) findViewById(R.id.detail_frame_layout);
|
||||
|
||||
mHeader = (ViewGroup) findViewById(R.id.header);
|
||||
mThumb = (LoadImageView) mHeader.findViewById(R.id.thumb);
|
||||
mTitle = (TextView) mHeader.findViewById(R.id.title);
|
||||
@@ -155,6 +185,9 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
mTorrent = (TextView) mContent.findViewById(R.id.torrent);
|
||||
mShare = (TextView) mContent.findViewById(R.id.share);
|
||||
mRate = (TextView) mContent.findViewById(R.id.rate);
|
||||
mTag = (LinearLayout) mContent.findViewById(R.id.tag);
|
||||
mComment = (LinearLayout) mContent.findViewById(R.id.comment);
|
||||
mCommentMore = (TextView) mContent.findViewById(R.id.comment_more);
|
||||
|
||||
mProgressBar = findViewById(R.id.progress_bar);
|
||||
|
||||
@@ -163,18 +196,35 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
handleAnnouncer(getAnnouncer());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onGetFitPaddingBottom(int b) {
|
||||
mDetailFrameLayout.setPadding(0, 0, 0, b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
GalleryDetail gd = mGalleryDetail;
|
||||
if (gd == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (v == mRead) {
|
||||
|
||||
} else if (v == mDownload) {
|
||||
|
||||
} else if (v == mFavorite) {
|
||||
|
||||
} else if (v == mTorrent) {
|
||||
|
||||
} else if (v == mShare) {
|
||||
StartActivityHelper.share(getStageActivity(),
|
||||
EhClient.getDetailUrl(Config.getEhSource(), gd.gid, gd.token, 0));
|
||||
}
|
||||
}
|
||||
|
||||
private String getRatingText(float rating) {
|
||||
String undefine = "(´_ゝ`)";
|
||||
if (rating == Float.NaN) {
|
||||
if (Float.isNaN(rating)) {
|
||||
return undefine;
|
||||
}
|
||||
|
||||
@@ -216,6 +266,72 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
" (" + rating + ", " + ratedTimes + ")";
|
||||
}
|
||||
|
||||
private void fillTags(List<TagGroup> tags) {
|
||||
Context context = getStageActivity();
|
||||
LayoutInflater inflater = getStageActivity().getLayoutInflater();
|
||||
int x = UiUtils.dp2pix(context, 2);
|
||||
int y = UiUtils.dp2pix(context, 4);
|
||||
|
||||
for (TagGroup tagGroup : tags) {
|
||||
LinearLayout tagGroupLayout = new LinearLayout(context);
|
||||
tagGroupLayout.setOrientation(LinearLayout.HORIZONTAL);
|
||||
AutoWrapLayout tagLayout = new AutoWrapLayout(context);
|
||||
|
||||
// Group name
|
||||
@SuppressLint("InflateParams")
|
||||
TextView groupNameView = (TextView) inflater.inflate(R.layout.tag_group, null);
|
||||
groupNameView.setText(tagGroup.groupName);
|
||||
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
lp.setMargins(x, y, x, y);
|
||||
tagGroupLayout.addView(groupNameView, lp);
|
||||
|
||||
int count = tagGroup.getTagCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
@SuppressLint("InflateParams")
|
||||
TextView tagView = (TextView) inflater.inflate(R.layout.tag, null);
|
||||
tagView.setText(tagGroup.getTagAt(i));
|
||||
/*
|
||||
tagView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(GalleryDetailActivity.this,
|
||||
GalleryListActivity.class);
|
||||
intent.setAction(GalleryListActivity.ACTION_GALLERY_LIST);
|
||||
intent.putExtra(GalleryListActivity.KEY_MODE,
|
||||
ListUrls.MODE_TAG);
|
||||
intent.putExtra(GalleryListActivity.KEY_TAG, groupName + ":" + tag);
|
||||
intent.setAction(GalleryListActivity.ACTION_GALLERY_LIST);
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
*/
|
||||
AutoWrapLayout.LayoutParams alp = new AutoWrapLayout.LayoutParams();
|
||||
alp.setMargins(x, y, x, y);
|
||||
tagLayout.addView(tagView, alp);
|
||||
}
|
||||
tagGroupLayout.addView(tagLayout);
|
||||
mTag.addView(tagGroupLayout);
|
||||
}
|
||||
}
|
||||
|
||||
private View createCommentView(Comment comment) {
|
||||
View view = LayoutInflater.from(getStageActivity()).inflate(R.layout.item_comment, null);
|
||||
((TextView) view.findViewById(R.id.user)).setText(comment.user);
|
||||
((TextView) view.findViewById(R.id.time)).setText(comment.time);
|
||||
TextView commentText = (TextView) view.findViewById(R.id.comment);
|
||||
commentText.setMaxLines(3);
|
||||
commentText.setAutoLinkMask(0);
|
||||
|
||||
|
||||
URLImageGetter p = new URLImageGetter(
|
||||
commentText, EhApplication.getConaco(getStageActivity()));
|
||||
commentText.setText(Html.fromHtml(comment.comment, p, null));
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
private class RatingTextViewFactory implements ViewSwitcher.ViewFactory {
|
||||
@Override
|
||||
public View makeView() {
|
||||
@@ -229,6 +345,8 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
|
||||
@Override
|
||||
public void onSuccess(GalleryDetail galleryDetail) {
|
||||
mGalleryDetail = galleryDetail;
|
||||
|
||||
Resources resources = getStageActivity().getResources();
|
||||
mLanguage.setText(galleryDetail.language);
|
||||
mPages.setText(String.format(resources.getString(R.string.page_count),
|
||||
@@ -240,12 +358,30 @@ public class GalleryDetailScene extends Scene implements View.OnClickListener {
|
||||
galleryDetail.favoredTimes));
|
||||
mRating.setRating(galleryDetail.rating);
|
||||
mRatingText.setText(getAllRatingText(galleryDetail.rating, galleryDetail.ratedTimes));
|
||||
fillTags(galleryDetail.tags);
|
||||
|
||||
int commentNum = galleryDetail.comments.size();
|
||||
if (commentNum == 0) {
|
||||
mCommentMore.setText("暂无评论");
|
||||
} else if (commentNum <= 2){
|
||||
mCommentMore.setText("暂无更多评论");
|
||||
} else {
|
||||
mCommentMore.setText("更多评论");
|
||||
}
|
||||
int maxShown = Math.min(2, commentNum);
|
||||
for (int i = 0; i < maxShown; i++) {
|
||||
mComment.addView(createCommentView(galleryDetail.comments.get(i)), i,
|
||||
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
mViewTransition.showView(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
e.printStackTrace();
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.Layout;
|
||||
import android.text.Spannable;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.text.style.URLSpan;
|
||||
import android.text.util.Linkify;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class LinkifyTextView extends TextView {
|
||||
|
||||
private String mUrl;
|
||||
|
||||
public LinkifyTextView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public LinkifyTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public LinkifyTextView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
// Just make urls striking
|
||||
// LinkifyTextView itself should not handle touch url event
|
||||
setAutoLinkMask(Linkify.WEB_URLS);
|
||||
setLinksClickable(false);
|
||||
}
|
||||
|
||||
public String getTouchedUrl() {
|
||||
return mUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call it when you do not need the url any more
|
||||
*/
|
||||
public void clearTouchedUrl() {
|
||||
mUrl = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
public boolean onTouchEvent(@NonNull MotionEvent event) {
|
||||
if (getText() instanceof Spannable) {
|
||||
// Get this code from android.text.method.LinkMovementMethod.
|
||||
// Work fine !
|
||||
int x = (int) event.getX();
|
||||
int y = (int) event.getY();
|
||||
boolean isGetUrl = false;
|
||||
|
||||
x -= getTotalPaddingLeft();
|
||||
y -= getTotalPaddingTop();
|
||||
|
||||
x += getScrollX();
|
||||
y += getScrollY();
|
||||
|
||||
Layout layout = getLayout();
|
||||
int line = layout.getLineForVertical(y);
|
||||
int off = layout.getOffsetForHorizontal(line, x);
|
||||
|
||||
ClickableSpan[] links = ((Spannable)getText()).getSpans(off, off, ClickableSpan.class);
|
||||
|
||||
for (ClickableSpan link : links) {
|
||||
if (link instanceof URLSpan) {
|
||||
mUrl = ((URLSpan)link).getURL();
|
||||
isGetUrl = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isGetUrl) {
|
||||
mUrl = null;
|
||||
}
|
||||
} else {
|
||||
mUrl = null;
|
||||
}
|
||||
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.hippo.miscellaneous;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class StartActivityHelper {
|
||||
|
||||
public static boolean sendEmail(@NonNull Activity from, @NonNull String address,
|
||||
@Nullable String subject, @Nullable String text) {
|
||||
Intent i = new Intent(Intent.ACTION_SENDTO);
|
||||
i.setData(Uri.parse("mailto:" + address));
|
||||
if (subject != null) {
|
||||
i.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||
}
|
||||
if (text != null) {
|
||||
i.putExtra(Intent.EXTRA_TEXT, text);
|
||||
}
|
||||
|
||||
try {
|
||||
from.startActivity(i);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(from, R.string.em_cant_find_activity, Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean share(@NonNull Activity from, String text) {
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_TEXT, text);
|
||||
sendIntent.setType("text/plain");
|
||||
|
||||
try {
|
||||
from.startActivity(sendIntent);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(from, R.string.em_cant_find_activity, Toast.LENGTH_SHORT).show();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.hippo.util;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Html;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hippo.conaco.Conaco;
|
||||
import com.hippo.drawable.UnikeryDrawable;
|
||||
|
||||
public class URLImageGetter implements Html.ImageGetter {
|
||||
|
||||
private TextView mTextView;
|
||||
private Conaco mConaco;
|
||||
|
||||
public URLImageGetter(TextView view, Conaco conaco) {
|
||||
mTextView = view;
|
||||
mConaco = conaco;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getDrawable(String source) {
|
||||
UnikeryDrawable drawable = new UnikeryDrawable(mTextView);
|
||||
mConaco.load(drawable, source, source);
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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.widget;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A ViewGroup that can layout views in line and auto wrap
|
||||
*
|
||||
* @author Hippo
|
||||
*
|
||||
*/
|
||||
public class AutoWrapLayout extends ViewGroup {
|
||||
|
||||
private final static String TAG = "AutoWrapLayout";
|
||||
|
||||
private final List<Rect> rectList = new ArrayList<>();
|
||||
|
||||
private Alignment mAlignment;
|
||||
|
||||
private static final Alignment[] sBaseLineArray = { Alignment.TOP,
|
||||
Alignment.CENTER, Alignment.BOTTOM };
|
||||
|
||||
|
||||
public enum Alignment {
|
||||
TOP(0),
|
||||
CENTER(1),
|
||||
BOTTOM(2);
|
||||
|
||||
Alignment(int ni) {
|
||||
nativeInt = ni;
|
||||
}
|
||||
|
||||
final int nativeInt;
|
||||
}
|
||||
|
||||
public AutoWrapLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
public AutoWrapLayout(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
public AutoWrapLayout(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs,
|
||||
R.styleable.AutoWrapLayout, defStyle, 0);
|
||||
|
||||
int index = a.getInt(R.styleable.AutoWrapLayout_alignment, -1);
|
||||
if (index >= 0) {
|
||||
setAlignment(sBaseLineArray[index]);
|
||||
}
|
||||
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
public void setAlignment(Alignment baseLine) {
|
||||
if (baseLine == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mAlignment != baseLine) {
|
||||
mAlignment = baseLine;
|
||||
|
||||
requestLayout();
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public Alignment getAlignment() {
|
||||
return mAlignment;
|
||||
}
|
||||
|
||||
private void adjustBaseLine(int lineHeight, int startIndex, int endIndex) {
|
||||
if (mAlignment == Alignment.TOP)
|
||||
return;
|
||||
|
||||
for (int index = startIndex; index < endIndex; index++) {
|
||||
final View child = getChildAt(index);
|
||||
final LayoutParams lp =
|
||||
(LayoutParams)child.getLayoutParams();
|
||||
Rect rect = rectList.get(index);
|
||||
int offsetRaw = lineHeight - rect.height() - lp.topMargin - lp.bottomMargin;
|
||||
if (mAlignment == Alignment.CENTER)
|
||||
rect.offset(0, offsetRaw/2);
|
||||
else if (mAlignment == Alignment.BOTTOM)
|
||||
rect.offset(0, offsetRaw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO Take vertical mode
|
||||
/**
|
||||
* each row or line at least show one child
|
||||
*
|
||||
* horizontal only show child can show or partly show in parent
|
||||
*/
|
||||
@SuppressLint("DrawAllocation")
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
|
||||
int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
if (widthMode == MeasureSpec.UNSPECIFIED)
|
||||
maxWidth = Integer.MAX_VALUE;
|
||||
if (heightMode == MeasureSpec.UNSPECIFIED)
|
||||
maxHeight = Integer.MAX_VALUE;
|
||||
|
||||
int paddingLeft = getPaddingLeft();
|
||||
int paddingTop = getPaddingTop();
|
||||
int paddingRight = getPaddingRight();
|
||||
int paddingBottom = getPaddingBottom();
|
||||
|
||||
int maxRightBound = maxWidth - paddingRight;
|
||||
int maxBottomBound = maxHeight - paddingBottom;
|
||||
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
int rightBound = paddingLeft;
|
||||
int maxRightNoPadding = rightBound;
|
||||
int bottomBound;
|
||||
int lastMaxBottom = paddingTop;
|
||||
int maxBottom = lastMaxBottom;
|
||||
int childWidth;
|
||||
int childHeight;
|
||||
|
||||
int lineStartIndex = 0;
|
||||
int lineEndIndex = 0; // endIndex + 1
|
||||
|
||||
rectList.clear();
|
||||
int childCount = getChildCount();
|
||||
for (int index = 0; index < childCount; index++) {
|
||||
final View child = getChildAt(index);
|
||||
child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
|
||||
if (child.getVisibility() == View.GONE)
|
||||
continue;
|
||||
final LayoutParams lp =
|
||||
(LayoutParams)child.getLayoutParams();
|
||||
childWidth = child.getMeasuredWidth();
|
||||
childHeight = child.getMeasuredHeight();
|
||||
|
||||
left = rightBound + lp.leftMargin;
|
||||
right = left + childWidth;
|
||||
rightBound = right + lp.rightMargin;
|
||||
if (rightBound > maxRightBound) { // Go to next row
|
||||
lineEndIndex = index;
|
||||
// Adjust child position base on baseline
|
||||
adjustBaseLine(maxBottom - lastMaxBottom, lineStartIndex, lineEndIndex);
|
||||
|
||||
// If child can't show in parent begin this line
|
||||
if (maxBottom >= maxBottomBound)
|
||||
break;
|
||||
|
||||
// If it is first item in line, try to show it all
|
||||
if (lineEndIndex == lineStartIndex) {
|
||||
child.measure(MeasureSpec.makeMeasureSpec(
|
||||
maxWidth - paddingLeft - paddingRight
|
||||
- lp.leftMargin - lp.rightMargin, MeasureSpec.AT_MOST),
|
||||
MeasureSpec.UNSPECIFIED);
|
||||
childWidth = child.getMeasuredWidth();
|
||||
childHeight = child.getMeasuredHeight();
|
||||
}
|
||||
left = paddingLeft + lp.leftMargin;
|
||||
right = left + childWidth;
|
||||
rightBound = right + lp.rightMargin;
|
||||
|
||||
lastMaxBottom = maxBottom;
|
||||
top = lastMaxBottom + lp.topMargin;
|
||||
bottom = top + childHeight;
|
||||
bottomBound = bottom + lp.bottomMargin;
|
||||
|
||||
lineStartIndex = index;
|
||||
} else {
|
||||
top = lastMaxBottom + lp.topMargin;
|
||||
bottom = top + childHeight;
|
||||
bottomBound = bottom + lp.bottomMargin;
|
||||
}
|
||||
// Update max
|
||||
if (rightBound > maxRightNoPadding)
|
||||
maxRightNoPadding = rightBound;
|
||||
if (bottomBound > maxBottom)
|
||||
maxBottom = bottomBound;
|
||||
Rect rect = new Rect();
|
||||
rect.left = left;
|
||||
rect.top = top;
|
||||
rect.right = right;
|
||||
rect.bottom = bottom;
|
||||
rectList.add(rect);
|
||||
}
|
||||
|
||||
// Handle last line baseline
|
||||
adjustBaseLine(maxBottom - lastMaxBottom, lineStartIndex, rectList.size());
|
||||
|
||||
int measuredWidth;
|
||||
int measuredHeight;
|
||||
|
||||
if (widthMode == MeasureSpec.EXACTLY)
|
||||
measuredWidth = maxWidth;
|
||||
else
|
||||
measuredWidth = maxRightNoPadding + paddingRight;
|
||||
if (heightMode == MeasureSpec.EXACTLY)
|
||||
measuredHeight = maxHeight;
|
||||
else {
|
||||
measuredHeight = maxBottom + paddingBottom;
|
||||
if (heightMode == MeasureSpec.AT_MOST)
|
||||
measuredHeight = measuredHeight > maxHeight ? maxHeight : measuredHeight;
|
||||
}
|
||||
|
||||
setMeasuredDimension(measuredWidth, measuredHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
||||
final int count = rectList.size();
|
||||
for(int i = 0; i < count; i++){
|
||||
final View child = this.getChildAt(i);
|
||||
if (child.getVisibility() == View.GONE)
|
||||
continue;
|
||||
Rect rect = rectList.get(i);
|
||||
child.layout(rect.left, rect.top, rect.right, rect.bottom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LayoutParams generateLayoutParams(AttributeSet attrs) {
|
||||
return new LayoutParams(getContext(), attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutParams generateDefaultLayoutParams() {
|
||||
return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
|
||||
return new LayoutParams(p);
|
||||
}
|
||||
|
||||
public static class LayoutParams extends MarginLayoutParams {
|
||||
public LayoutParams() {
|
||||
this(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
}
|
||||
public LayoutParams(Context c, AttributeSet attrs) {
|
||||
super(c, attrs);
|
||||
}
|
||||
public LayoutParams(int width, int height) {
|
||||
super(width, height);
|
||||
}
|
||||
public LayoutParams(ViewGroup.LayoutParams source) {
|
||||
super(source);
|
||||
}
|
||||
public LayoutParams(MarginLayoutParams source) {
|
||||
super(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user