部分改善详情界面,添加 Ripple 效果

This commit is contained in:
seven332 committed 2014-08-04 22:38:31 +08:00
1 parent ee229b11da
commit e08a9bfdfa
96 files changed
+2585 -2139

No files matched your search

+8 -16
View File
@@ -22,6 +22,7 @@ import java.lang.Thread.UncaughtExceptionHandler;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import android.annotation.SuppressLint;
import android.app.Application;
import com.hippo.ehviewer.cache.ImageCache;
@@ -33,12 +34,14 @@ import com.hippo.ehviewer.util.Download;
import com.hippo.ehviewer.util.Favorite;
import com.hippo.ehviewer.util.ThreadPool;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.widget.SuperToast;
public class AppContext extends Application implements UncaughtExceptionHandler {
@SuppressWarnings("unused")
private static final String TAG = "AppContext";
private final DateFormat mFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
@SuppressLint("SimpleDateFormat")
public static final DateFormat sFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
private Thread.UncaughtExceptionHandler mDefaultHandler;
@@ -52,15 +55,16 @@ public class AppContext extends Application implements UncaughtExceptionHandler
// Init everything
mNetworkThreadPool = new ThreadPool(2, 4);
Config.init(this);
Ui.init(this);
Crash.init(this);
mEhClient = new EhClient(this);
EhClient.createInstance(this);
Download.init(this);
Favorite.init(this);
Data.createInstance(this);
SuperToast.setContext(this);
mData = new Data(this);
// Do catch error prepare
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
@@ -75,22 +79,10 @@ public class AppContext extends Application implements UncaughtExceptionHandler
}
}
public EhClient getEhClient() {
return mEhClient;
}
public ThreadPool getNetworkThreadPool() {
return mNetworkThreadPool;
}
public Data getData() {
return mData;
}
public DateFormat getDateFormat() {
return mFormatter;
}
/**
* {@inheritDoc}
*/
@@ -28,7 +28,7 @@ import com.hippo.ehviewer.ehclient.DetailParser;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.network.HttpHelper;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
/**
* Download a gallery
@@ -72,7 +72,7 @@ public class GallerysDownloader implements Runnable {
mGalleryInfo = galleryInfo;
mPageIndex = startIndex;
mDownloadDir = new File(Config.getDownloadPath(),
Util.rightFileName(mGalleryInfo.gid + '-' + mGalleryInfo.title));
Utils.rightFileName(mGalleryInfo.gid + '-' + mGalleryInfo.title));
mDownloadDir.mkdirs();
// TODO What if these is a file with the same name
+3 -3
View File
@@ -22,7 +22,7 @@ import java.net.URLEncoder;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
public class ListUrls {
@@ -219,7 +219,7 @@ public class ListUrls {
for (int i = 0; i < tag.length; i++)
tag[i] = URLEncoder.encode(tag[i], "UTF-8");
} catch (UnsupportedEncodingException e) {}
url.append(Util.join(tag, '+'));
url.append(Utils.join(tag, '+'));
// Add page
url.append("/").append(page);
@@ -263,7 +263,7 @@ public class ListUrls {
for (int i = 0; i < tag.length; i++)
tag[i] = URLEncoder.encode(tag[i], "UTF-8");
} catch (UnsupportedEncodingException e) {}
url.append(Util.join(tag, '+')).append("&");
url.append(Utils.join(tag, '+')).append("&");
}
// Add page
+2 -2
View File
@@ -38,7 +38,7 @@ import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Future;
import com.hippo.ehviewer.util.FutureListener;
import com.hippo.ehviewer.util.ThreadPool;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.util.ThreadPool.Job;
import com.hippo.ehviewer.util.ThreadPool.JobContext;
@@ -75,7 +75,7 @@ public class UpdateHelper {
}
public void autoCheckUpdate() {
if (Config.getUpdateDate() < Util.getDate())
if (Config.getUpdateDate() < Utils.getDate())
checkUpdate();
}
+5 -5
View File
@@ -40,7 +40,7 @@ import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
/**
* This class holds the memory and disk bitmap caches.
@@ -121,7 +121,7 @@ public final class ImageCache {
* @param cacheParams The cache parameters to initialize the cache
*/
private void init(final Context context) {
Util.execute(false, new AsyncTask<Void, Void, Void>() {
Utils.execute(false, new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... unused) {
@@ -410,7 +410,7 @@ public final class ImageCache {
* cache first
*/
public void flush() {
Util.execute(false, new AsyncTask<Void, Void, Void>() {
Utils.execute(false, new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... unused) {
@@ -432,7 +432,7 @@ public final class ImageCache {
* Clears the disk and memory caches
*/
public void clearCaches() {
Util.execute(false, new AsyncTask<Void, Void, Void>() {
Utils.execute(false, new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... unused) {
@@ -458,7 +458,7 @@ public final class ImageCache {
* thread.
*/
public void close() {
Util.execute(false, new AsyncTask<Void, Void, Void>() {
Utils.execute(false, new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... unused) {
@@ -0,0 +1,44 @@
/*
* 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.data;
public class ApiGalleryDetail extends ApiGalleryInfo {
public int previewSum;
public int previewPerPage;
public PreviewList[] previewLists;
public ApiGalleryDetail() {}
public ApiGalleryDetail(ApiGalleryInfo apiGalleryInfo) {
gid = apiGalleryInfo.gid;
token = apiGalleryInfo.token;
title = apiGalleryInfo.title;
posted = apiGalleryInfo.posted;
category = apiGalleryInfo.category;
thumb = apiGalleryInfo.thumb;
uploader = apiGalleryInfo.uploader;
rating = apiGalleryInfo.rating;
simpleLanguage = apiGalleryInfo.simpleLanguage;
archiver_key = apiGalleryInfo.archiver_key;
title_jpn = apiGalleryInfo.title_jpn;
filecount = apiGalleryInfo.filecount;
filesize = apiGalleryInfo.filesize;
expunged = apiGalleryInfo.expunged;
torrentcount = apiGalleryInfo.torrentcount;
apiTags = apiGalleryInfo.apiTags;
}
}
@@ -17,13 +17,13 @@
package com.hippo.ehviewer.data;
public class ApiGetGalleryInfo extends GalleryInfo{
public class ApiGalleryInfo extends GalleryInfo{
public String archiver_key;
public String title_jpn;
public String filecount;
public long filesize;
public boolean expunged;
public String torrentcount;
public String[] tags;
public String[] apiTags;
}
+10
View File
@@ -83,6 +83,16 @@ public class Data {
private final DBHelper mDBHelper;
private final SQLiteDatabase mDatabase;
private static Data sInstance;
public static void createInstance(Context context) {
sInstance = new Data(context);
}
public static Data getInstance() {
return sInstance;
}
public Data(Context context) {
mContext = context;
mDBHelper = new DBHelper(mContext);
@@ -51,5 +51,6 @@ public class GalleryDetail extends GalleryInfo {
thumb = galleryInfo.thumb;
uploader = galleryInfo.uploader;
rating = galleryInfo.rating;
simpleLanguage = galleryInfo.simpleLanguage;
}
}
@@ -0,0 +1,36 @@
/*
* 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.data;
public class LofiGalleryDetail extends LofiGalleryInfo {
public int previewSum;
public int previewPerPage;
public PreviewList[] previewLists;
public LofiGalleryDetail(LofiGalleryInfo lofiGalleryInfo) {
gid = lofiGalleryInfo.gid;
token = lofiGalleryInfo.token;
title = lofiGalleryInfo.title;
posted = lofiGalleryInfo.posted;
category = lofiGalleryInfo.category;
thumb = lofiGalleryInfo.thumb;
uploader = lofiGalleryInfo.uploader;
rating = lofiGalleryInfo.rating;
simpleLanguage = lofiGalleryInfo.simpleLanguage;
lofiTags = lofiGalleryInfo.lofiTags;
}
}
@@ -0,0 +1,60 @@
/*
* 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.drawable;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
public class OvalDrawable extends Drawable {
private final Paint mPaint;
public OvalDrawable(int color) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaint.setColor(color);
}
@Override
public void draw(Canvas canvas) {
canvas.drawOval(new RectF(this.getBounds()), mPaint);
}
@Override
public void setAlpha(int alpha) {
mPaint.setColor(mPaint.getColor() & 0x00ffffff | (alpha << 24));
invalidateSelf();
}
@Override
public void setColorFilter(ColorFilter cf) {
// Not support
}
@Override
public int getOpacity() {
return PixelFormat.OPAQUE;
}
public void setColor(int color) {
mPaint.setColor(color);
invalidateSelf();
}
}
@@ -28,7 +28,7 @@ import com.hippo.ehviewer.data.Comment;
import com.hippo.ehviewer.data.LargePreviewList;
import com.hippo.ehviewer.data.NormalPreviewList;
import com.hippo.ehviewer.data.PreviewList;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
public class DetailParser {
@@ -141,9 +141,9 @@ public class DetailParser {
if (m.find()) {
re |= DETAIL;
thumb = Util.htmlUnsescape(m.group(1));
title = Util.htmlUnsescape(m.group(2));
title_jpn = Util.htmlUnsescape(m.group(3));
thumb = Utils.htmlUnsescape(m.group(1));
title = Utils.htmlUnsescape(m.group(2));
title_jpn = Utils.htmlUnsescape(m.group(3));
category = EhClient.getType(m.group(4));
uploader = m.group(5);
posted = m.group(6);
+25 -15
View File
@@ -56,7 +56,7 @@ import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.util.ThreadPool;
import com.hippo.ehviewer.util.ThreadPool.Job;
import com.hippo.ehviewer.util.ThreadPool.JobContext;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
public class EhClient {
@@ -92,6 +92,23 @@ public class EhClient {
private final Handler mHandler;
private final EhInfo mInfo;
private static EhClient sInstance;
public static void createInstance(AppContext appContext) {
sInstance = new EhClient(appContext);
}
public static EhClient getInstance() {
return sInstance;
}
public EhClient(AppContext appContext) {
mAppContext = appContext;
mThreadPool = mAppContext.getNetworkThreadPool();
mHandler = AppHandler.getInstance();
mInfo = EhInfo.getInstance(appContext);
}
public static String getUrlHeader() {
return getUrlHeader(Config.getMode());
}
@@ -227,13 +244,6 @@ public class EhClient {
public void onFailure(String eMsg);
}
public EhClient(AppContext appContext) {
mAppContext = appContext;
mThreadPool = mAppContext.getNetworkThreadPool();
mHandler = AppHandler.getInstance();
mInfo = EhInfo.getInstance(appContext);
}
/**
* True if Login
* @return
@@ -351,7 +361,7 @@ public class EhClient {
listener.onGetAvatar(GET_AVATAR_ERROR);
return;
}
String profileUrl = Util.htmlUnsescape(m.group(1));
String profileUrl = Utils.htmlUnsescape(m.group(1));
// Get avatar url
body = hp.get(profileUrl);
if (body == null) {
@@ -775,7 +785,7 @@ public class EhClient {
strs[1] = "last";
else
strs[1] = m.group(2);
strs[2] = Util.htmlUnsescape(m.group(3));
strs[2] = Utils.htmlUnsescape(m.group(3));
} else
eMsg = mAppContext.getString(R.string.em_parser_error);
} else
@@ -965,7 +975,7 @@ public class EhClient {
}
//Create folder
File folder = new File(Config.getDownloadPath() + File.separatorChar + Util.rightFileName(curDownloadInfo.title)); // TODO For title contain invailed char
File folder = new File(Config.getDownloadPath() + File.separatorChar + Utils.rightFileName(curDownloadInfo.title)); // TODO For title contain invailed char
if (!folder.mkdirs() && !folder.isDirectory()) {
listener.onDownloadMangaOver(curDownloadInfo.gid, false);
curDownloadInfo.status = DownloadInfo.FAILED;
@@ -1006,7 +1016,7 @@ public class EhClient {
Log.d(TAG, folder.getPath());
curControlor = imageDownloader.resetData(folder.getPath(),
String.format("%05d", curDownloadInfo.lastStartIndex + 1) + "." + Util.getExtension(imageUrlStr),
String.format("%05d", curDownloadInfo.lastStartIndex + 1) + "." + Utils.getExtension(imageUrlStr),
imageUrlStr);
imageDownloader.run();
@@ -1129,7 +1139,7 @@ public class EhClient {
if (m.find()) {
prePage = m.group(1);
nextPage = m.group(2);
imageUrlStr = Util.htmlUnsescape(m.group(3));
imageUrlStr = Utils.htmlUnsescape(m.group(3));
return true;
}
return false;
@@ -1522,8 +1532,8 @@ public class EhClient {
gi.count = -1;
gi.gid = j.getInt("gid");
gi.token = j.getString("token");
gi.title = Util.htmlUnsescape(j.getString("title"));
gi.posted = mAppContext.getDateFormat().format(Long.parseLong(j.getString("posted")) * 1000);
gi.title = Utils.htmlUnsescape(j.getString("title"));
gi.posted = AppContext.sFormatter.format(Long.parseLong(j.getString("posted")) * 1000);
gi.thumb = j.getString("thumb");
gi.category = getType(j.getString("category"));
gi.uploader = j.getString("uploader");
+3 -3
View File
@@ -32,7 +32,7 @@ import android.graphics.BitmapFactory;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
/**
*
@@ -89,7 +89,7 @@ public class EhInfo {
} catch (FileNotFoundException e) {
return null;
} finally {
Util.closeStreamQuietly(is);
Utils.closeStreamQuietly(is);
}
}
@@ -230,7 +230,7 @@ public class EhInfo {
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
Util.closeStreamQuietly(os);
Utils.closeStreamQuietly(os);
}
}
@@ -22,7 +22,7 @@ import java.util.regex.Pattern;
import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.data.LofiGalleryInfo;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
public class ListParser {
@@ -73,8 +73,8 @@ public class ListParser {
} else {
continue;
}
lgi.thumb = Util.htmlUnsescape(m.group(2));
lgi.title = Util.htmlUnsescape(m.group(3));
lgi.thumb = Utils.htmlUnsescape(m.group(2));
lgi.title = Utils.htmlUnsescape(m.group(3));
if (getPostedAndUploader(m.group(4), pau)) {
lgi.posted = pau[0];
lgi.uploader = pau[1];
@@ -147,12 +147,12 @@ public class ListParser {
gi.category = EhClient.getType(m.group(1));
gi.posted = m.group(2);
if (m.group(3) == null) {
gi.thumb = Util.htmlUnsescape("http://"
gi.thumb = Utils.htmlUnsescape("http://"
+ m.group(5).replace('~', '/'));
gi.title = Util.htmlUnsescape(m.group(6));
gi.title = Utils.htmlUnsescape(m.group(6));
} else {
gi.thumb = Util.htmlUnsescape(m.group(3));
gi.title = Util.htmlUnsescape(m.group(4));
gi.thumb = Utils.htmlUnsescape(m.group(3));
gi.title = Utils.htmlUnsescape(m.group(4));
}
Pattern pattern = Pattern
@@ -27,7 +27,7 @@ import com.hippo.ehviewer.util.FutureListener;
import com.hippo.ehviewer.util.ThreadPool;
import com.hippo.ehviewer.util.ThreadPool.Job;
import com.hippo.ehviewer.util.ThreadPool.JobContext;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -209,7 +209,7 @@ public class ImageSet {
e.printStackTrace();
} finally {
if (fis != null)
Util.closeStreamQuietly(fis);
Utils.closeStreamQuietly(fis);
}
return res;
}
@@ -231,9 +231,9 @@ public class ImageSet {
public boolean getFileForName(String name, ImageData imageData) {
String[] list = mFolder.list();
for (String item : list) {
if(name.equals(Util.getName(item))) {
if(name.equals(Utils.getName(item))) {
imageData.fileName = item;
if (Util.getExtension(item).toLowerCase().equals(GIF_EXTENSION))
if (Utils.getExtension(item).toLowerCase().equals(GIF_EXTENSION))
imageData.type = TYPE_MOVIE;
else
imageData.type = TYPE_BITMAP;
@@ -1,26 +0,0 @@
/*
* 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.network;
public class Constant {
public static final int HTTP_TEMP_REDIRECT = 307;
public static String defaultUserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36";
public static String userAgent = System.getProperty("http.agent", defaultUserAgent);
public static final int DEFAULT_TIMEOUT = 10 * 1000;
public static final int MAX_REDIRECTS = 5;
public static final int BUFFER_SIZE = 4096;
}
+76 -75
View File
@@ -32,24 +32,25 @@ import org.apache.http.conn.ConnectTimeoutException;
import android.content.Context;
import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.exception.FileException;
import com.hippo.ehviewer.exception.NoSdCardException;
import com.hippo.ehviewer.exception.StopRequestException;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Constants;
import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.util.Utils;
// TODO 添加检查次磁盘空间
/**
* Thread unsafe
*
*
* @author Hippo
*
*/
public class Downloader implements Runnable {
private static final String TAG = "Downloader";
public static final int NONE = 0x0;
public static final int READY = 0x1;
public static final int CONNECTING = 0x2;
@@ -57,28 +58,28 @@ public class Downloader implements Runnable {
public static final int FAILED = 0x4;
public static final int COMPLETED = 0x5;
public static final int STOPED = 0x6;
private static final int MAX_RETRY = 3;
private Context mContext;
private final Context mContext;
private File mFile;
private File mFolder;
private String mPath;
private String mFileName;
private URL mUrl;
private Controlor mContorlor;
private final Controlor mContorlor;
private int mTotalSize;
// If support Content-Range, start from it
private int mDownloadSize = 0;
private int mRedirectionCount = 0;
private int status = NONE;
private OnDownloadListener mListener;
private Exception mException;
public interface OnDownloadListener {
public void onDownloadStartConnect();
public void onDownloadStartDownload(int totalSize);
@@ -89,81 +90,81 @@ public class Downloader implements Runnable {
*/
public void onDownloadOver(int status, String eMsg);
}
public class Controlor {
private boolean mStop = false;
public synchronized void stop() {
mStop = true;
mStop = true;
}
public synchronized void reset() {
mStop = false;
mStop = false;
}
public synchronized boolean isStop() {
return mStop;
return mStop;
}
}
public Controlor resetData(String path, String fileName, String urlStr) throws MalformedURLException {
mPath = path;
mFileName = fileName;
mUrl = new URL(urlStr);
mException = null;
mDownloadSize = 0;
mRedirectionCount = 0;
status = READY;
mContorlor.reset();
return mContorlor;
}
public void setOnDownloadListener(OnDownloadListener listener) {
mListener = listener;
}
public Downloader(Context context) {
mContext = context;
mContorlor = new Controlor();
}
public String getEMsg() {
if (mException == null)
return mContext.getString(R.string.em_unknown_error);
else if (mException instanceof MalformedURLException)
return mContext.getString(R.string.em_url_format_error);
else if (mException instanceof ConnectTimeoutException ||
mException instanceof SocketTimeoutException)
return mContext.getString(R.string.em_timeout);
else if (mException instanceof UnknownHostException)
return mContext.getString(R.string.em_unknown_host);
else if (mException instanceof SocketException)
return "SocketException : " + mException.getMessage();
else if (mException instanceof NoSdCardException)
return mContext.getString(R.string.em_no_sdcard);
else if (mException instanceof FileException)
return ((FileException)mException).getMessage();
else
return mException.getMessage();
}
@Override
public void run() {
int retryTimes = 0;
if (true) {
boolean checkFolder = false;
try {
initFolder();
checkFolder = true;
@@ -171,7 +172,7 @@ public class Downloader implements Runnable {
mException = e;
e.printStackTrace();
}
while(checkFolder) {
try {
if (mContorlor.isStop())
@@ -193,50 +194,50 @@ public class Downloader implements Runnable {
}
} else
mException = new NoSdCardException();
if (mContorlor.isStop())
status = STOPED;
if (status != COMPLETED && mFile != null)
mFile.delete();
if (mListener != null)
mListener.onDownloadOver(status, getEMsg());
}
public int getStatus() {
return status;
}
private void initFolder() throws Exception {
mFolder = new File(mPath);
if (!mFolder.exists()) {
if (!mFolder.mkdirs())
throw new FileException(FileException.MKDIR_ERROR);
} else if (!mFolder.isDirectory()){
throw new FileException(FileException.NOT_DIR);
}
if (!mFolder.canWrite())
throw new FileException(FileException.CANNOT_WRITE);
}
private void executeDownload() throws Exception {
while (mRedirectionCount++ < Constant.MAX_REDIRECTS) {
while (mRedirectionCount++ < Constants.MAX_REDIRECTS) {
HttpURLConnection conn = null;
try {
Log.d(TAG, "Get file " + mUrl.toString());
status = CONNECTING;
if (mListener != null)
mListener.onDownloadStartConnect();
conn = (HttpURLConnection)mUrl.openConnection();
conn.setInstanceFollowRedirects(false);
conn.addRequestProperty("Range", "bytes=" + mDownloadSize + "-");
conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constant.DEFAULT_TIMEOUT);
conn.setConnectTimeout(Constants.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constants.DEFAULT_TIMEOUT);
conn.connect();
final int responseCode = conn.getResponseCode();
switch (responseCode) {
@@ -252,7 +253,7 @@ public class Downloader implements Runnable {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
case Constant.HTTP_TEMP_REDIRECT:
case Constants.HTTP_TEMP_REDIRECT:
final String location = conn.getHeaderField("Location");
mUrl = new URL(mUrl, location);
continue;
@@ -269,16 +270,16 @@ public class Downloader implements Runnable {
}
//throw new RedirectionException();
}
/**
* Get Response Headers Info
*
*
* @param conn
*/
private void processResponseHeaders(HttpURLConnection conn) {
mTotalSize = conn.getContentLength();
//
//
String range;
if ((range = conn.getHeaderField("Content-Range")) != null) { // Support Content-Range
boolean newNum = true;
@@ -311,17 +312,17 @@ public class Downloader implements Runnable {
mDownloadSize = 0;
}
}
/**
* Transfer data from the given connection to the destination file.
*/
private void transferData(HttpURLConnection conn) throws Exception {
InputStream in = null;
RandomAccessFile raf = null;
if (mContorlor.isStop())
throw new StopRequestException();
try {
try {
in = conn.getInputStream();
@@ -342,7 +343,7 @@ public class Downloader implements Runnable {
transferData(in, raf);
} finally {
if (in != null)
Util.closeStreamQuietly(in);
Utils.closeStreamQuietly(in);
if (raf != null)
try {
raf.close();
@@ -351,8 +352,8 @@ public class Downloader implements Runnable {
}
}
}
/**
* Transfer as much data as possible from the HTTP response to the
* destination file.
@@ -360,48 +361,48 @@ public class Downloader implements Runnable {
@SuppressWarnings("unused")
private void transferData(InputStream in, OutputStream out)
throws Exception {
final byte data[] = new byte[Constant.BUFFER_SIZE];
final byte data[] = new byte[Constants.BUFFER_SIZE];
while (true) {
if (mContorlor.isStop())
throw new StopRequestException();
int bytesRead = readFromResponse(data, in);
if (bytesRead == -1) { // success, end of stream already reached
return;
}
writeDataToDestination(data, bytesRead, out);
mDownloadSize += bytesRead;
if (mListener != null)
mListener.onDownloadStatusUpdate(mDownloadSize, mTotalSize);
}
}
/**
* Transfer as much data as possible from the HTTP response to the
* destination file.
*/
private void transferData(InputStream in, RandomAccessFile raf)
throws Exception {
final byte data[] = new byte[Constant.BUFFER_SIZE];
final byte data[] = new byte[Constants.BUFFER_SIZE];
while (true) {
if (mContorlor.isStop())
throw new StopRequestException();
int bytesRead = readFromResponse(data, in);
if (bytesRead == -1) { // success, end of stream already reached
return;
}
writeDataToDestination(data, bytesRead, raf);
mDownloadSize += bytesRead;
if (mListener != null)
mListener.onDownloadStatusUpdate(mDownloadSize, mTotalSize);
}
}
/**
* Read some data from the HTTP response stream, handling I/O errors.
* @param data buffer to use to read data
@@ -417,8 +418,8 @@ public class Downloader implements Runnable {
throw e;
}
}
/**
* Write a data buffer to the destination file.
* @param data buffer containing the data to write
@@ -435,7 +436,7 @@ public class Downloader implements Runnable {
throw e;
}
}
/**
* Write a data buffer to the destination file.
* @param data buffer containing the data to write
+10 -10
View File
@@ -54,7 +54,7 @@ import com.hippo.ehviewer.exception.StopRequestException;
import com.hippo.ehviewer.util.Constants;
import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
/**
* It is not thread safe
@@ -191,12 +191,12 @@ public class HttpHelper {
url = rh.getUrl();
Log.d(TAG, "Requst " + url.toString());
boolean isCookiable = isUrlCookiable(url);
while (redirectionCount++ < Constant.MAX_REDIRECTS) {
while (redirectionCount++ < Constants.MAX_REDIRECTS) {
conn = (HttpURLConnection) url.openConnection();
conn.setInstanceFollowRedirects(false);
conn.setRequestProperty("User-Agent", Constant.userAgent);
conn.setConnectTimeout(Constant.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constant.DEFAULT_TIMEOUT);
conn.setRequestProperty("User-Agent", Constants.userAgent);
conn.setConnectTimeout(Constants.DEFAULT_TIMEOUT);
conn.setReadTimeout(Constants.DEFAULT_TIMEOUT);
// Set cookie if necessary
if (isCookiable)
EhInfo.getInstance(mContext).setCookie(conn, mPreviewMode);
@@ -232,7 +232,7 @@ public class HttpHelper {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
case Constant.HTTP_TEMP_REDIRECT:
case Constants.HTTP_TEMP_REDIRECT:
final String location = conn.getHeaderField("Location");
Log.d(TAG, "New location " + location);
mLastUrl = location;
@@ -361,7 +361,7 @@ public class HttpHelper {
else
baos = new ByteArrayOutputStream();
Util.copy(is, baos, Constant.BUFFER_SIZE);
Utils.copy(is, baos, Constants.BUFFER_SIZE);
// Get charset
String charset = null;
@@ -379,8 +379,8 @@ public class HttpHelper {
} catch (Exception e) {
throw e;
} finally {
Util.closeStreamQuietly(is);
Util.closeStreamQuietly(baos);
Utils.closeStreamQuietly(is);
Utils.closeStreamQuietly(baos);
}
return body;
}
@@ -772,7 +772,7 @@ public class HttpHelper {
private void transferData(InputStream in, OutputStream out)
throws Exception {
final byte data[] = new byte[Constant.BUFFER_SIZE];
final byte data[] = new byte[Constants.BUFFER_SIZE];
mReceivedSize = 0;
while (true) {
@@ -36,7 +36,7 @@ import android.widget.LinearLayout;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.ColorPickerView;
import com.hippo.ehviewer.widget.DialogBuilder;
@@ -208,7 +208,7 @@ public class ColorPreference extends Preference implements Preference.OnPreferen
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
new SuperToast(context, R.string.restart_to_take_effect).show();
new SuperToast(R.string.restart_to_take_effect).show();
int color = getColor() | 0xff000000;
Config.setThemeColor(color);
@@ -251,28 +251,28 @@ public class ColorPreference extends Preference implements Preference.OnPreferen
public void onClick(final View v) {
switch (v.getId()) {
case R.id.color_scheme_dialog_preset_one:
mColorPicker.setColor(getColor(android.R.color.holo_blue_light));
mColorPicker.setColor(getColor(R.color.theme_red));
break;
case R.id.color_scheme_dialog_preset_two:
mColorPicker.setColor(getColor(android.R.color.holo_green_light));
mColorPicker.setColor(getColor(R.color.theme_orange));
break;
case R.id.color_scheme_dialog_preset_three:
mColorPicker.setColor(getColor(android.R.color.holo_orange_dark));
mColorPicker.setColor(getColor(R.color.theme_lime));
break;
case R.id.color_scheme_dialog_preset_four:
mColorPicker.setColor(getColor(android.R.color.holo_orange_light));
mColorPicker.setColor(getColor(R.color.theme_green));
break;
case R.id.color_scheme_dialog_preset_five:
mColorPicker.setColor(getColor(android.R.color.holo_purple));
mColorPicker.setColor(getColor(R.color.theme_teal));
break;
case R.id.color_scheme_dialog_preset_six:
mColorPicker.setColor(getColor(android.R.color.holo_red_light));
mColorPicker.setColor(getColor(R.color.theme_blue));
break;
case R.id.color_scheme_dialog_preset_seven:
mColorPicker.setColor(getColor(android.R.color.darker_gray));
mColorPicker.setColor(getColor(R.color.theme_purple));
break;
case R.id.color_scheme_dialog_preset_eight:
mColorPicker.setColor(getColor(android.R.color.black));
mColorPicker.setColor(getColor(R.color.theme_brown));
break;
case R.id.color_scheme_dialog_old_color:
mColorPicker.setColor(mCurrentColor);
@@ -290,7 +290,7 @@ public class ColorPreference extends Preference implements Preference.OnPreferen
public AlertDialog create() {
AlertDialog dialog = super.create();
dialog.getWindow().setFormat(PixelFormat.RGBA_8888);
Util.removeHardwareAccelerationSupport(mColorPicker);
Utils.removeHardwareAccelerationSupport(mColorPicker);
return dialog;
}
}
@@ -114,7 +114,7 @@ public class NumberOfColumnsPreference extends Preference
throw new Exception();
}
} catch (Exception e) {
new SuperToast(mContext, R.string.invalid_input, SuperToast.ERROR).show();
new SuperToast(R.string.invalid_input, SuperToast.ERROR).show();
}
}
}).create().show();
@@ -16,17 +16,6 @@
package com.hippo.ehviewer.service;
import java.util.HashMap;
import java.util.Map;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.ehclient.EhClient.DownloadMangaManager;
import com.hippo.ehviewer.ui.DownloadActivity;
import com.hippo.ehviewer.ui.DownloadInfo;
import com.hippo.ehviewer.util.Download;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -36,6 +25,13 @@ import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.ehclient.EhClient.DownloadMangaManager;
import com.hippo.ehviewer.ui.DownloadActivity;
import com.hippo.ehviewer.ui.DownloadInfo;
import com.hippo.ehviewer.util.Download;
import com.hippo.ehviewer.util.Log;
public class DownloadService extends Service {
@@ -45,27 +41,27 @@ public class DownloadService extends Service {
public static final String KEY_GID = "gid";
public static final String KEY_INDEX = "index";
public static final String KEY_STATE = "state";
private AppContext mAppContext;
private ServiceBinder mBinder = null;
private NotificationManager mNotifyManager;
private DownloadMangaManager downloadMangaManager;
@Override
public void onCreate() {
@Override
public void onCreate() {
super.onCreate();
mAppContext = (AppContext)getApplication();
mBinder = new ServiceBinder();
mNotifyManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
downloadMangaManager = mAppContext.getEhClient().new DownloadMangaManager();
downloadMangaManager = EhClient.getInstance().new DownloadMangaManager();
downloadMangaManager.setDownloadService(this);
downloadMangaManager.setOnDownloadMangaListener(new EhClient.OnDownloadMangaListener() {
@Override
@@ -77,13 +73,13 @@ public class DownloadService extends Service {
.setProgress(0, 0, true).setOngoing(true).setAutoCancel(false);
mNotifyManager.notify(DOWNLOAD_NOTIFY_ID, builder.getNotification());
}
@Override
public void onDownloadMangaAllOver() {
mNotifyManager.cancel(DOWNLOAD_NOTIFY_ID);
stopSelf();
}
@Override
public void onDownloadMangaStart(String id) {
DownloadInfo di = Download.get(id);
@@ -99,7 +95,7 @@ public class DownloadService extends Service {
mNotifyManager.notify(DOWNLOAD_NOTIFY_ID, builder.getNotification());
}
}
@Override
public void onDownloadMangaStart(String id, int pageSum, int startIndex) {
DownloadInfo di = Download.get(id);
@@ -117,13 +113,13 @@ public class DownloadService extends Service {
mNotifyManager.cancel(Integer.parseInt(id));
}
}
@Override
public void onDownloadMangaStop(String id) {
// TODO Auto-generated method stub
}
@Override
public void onDownloadMangaOver(String id, boolean ok) {
String mesg = null;
@@ -140,7 +136,7 @@ public class DownloadService extends Service {
builder.setContentText(null).setProgress(0, 0, false).setOngoing(false);
mNotifyManager.notify(Integer.parseInt(id), builder.getNotification());
}
@Override
public void onDownloadPage(String id, int pageSum, int index) {
DownloadInfo di = Download.get(id);
@@ -162,45 +158,45 @@ public class DownloadService extends Service {
public void onDownloadPageProgress(String id, int pageSum,
int index, float totalSize, float downloadSize) {
// TODO Auto-generated method stub
}
});
}
private void setNotification(Notification.Builder builder) {
builder.setSmallIcon(R.drawable.ic_launcher);
Intent intent = new Intent(DownloadService.this,DownloadActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(DownloadService.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
Intent intent = new Intent(DownloadService.this,DownloadActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(DownloadService.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
}
@Override
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service onStartCommand");
return START_NOT_STICKY;
}
@Override
return START_NOT_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "Service onBind");
return mBinder;
}
@Override
public void onDestroy() {
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Service onDestroy");
mNotifyManager.cancel(DOWNLOAD_NOTIFY_ID);
mBinder = null;
mNotifyManager = null;
}
public void add(String gid, String thumb, String detailUrlStr, String title) {
DownloadInfo di = Download.get(gid);
if (di == null) {
@@ -216,7 +212,7 @@ public class DownloadService extends Service {
}
add(di);
}
public void add(String gid, String thumb, String detailUrlStr,
String pageUrlStr, int pageSum, int lastStartIndex, String title) {
DownloadInfo di = Download.get(gid);
@@ -236,7 +232,7 @@ public class DownloadService extends Service {
}
add(di);
}
public void add(DownloadInfo di) {
if (di.status == DownloadInfo.DOWNLOADING
|| di.status == DownloadInfo.WAITING)
@@ -244,16 +240,16 @@ public class DownloadService extends Service {
di.status = DownloadInfo.WAITING;
downloadMangaManager.add(di);
}
public void cancel(String id) {
downloadMangaManager.cancel(id);
}
public void notifyUpdate(){
Intent it = new Intent(ACTION_UPDATE);
sendBroadcast(it);
}
public void notifyUpdate(String gid, int index, int state){
Intent it = new Intent(ACTION_UPDATE);
it.putExtra(KEY_GID, gid);
@@ -261,7 +257,7 @@ public class DownloadService extends Service {
it.putExtra(KEY_STATE, state);
sendBroadcast(it);
}
public class ServiceBinder extends Binder{
public DownloadService getService(){
return DownloadService.this;
@@ -17,35 +17,54 @@
package com.hippo.ehviewer.ui;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import com.google.analytics.tracking.android.EasyTracker;
import com.hippo.ehviewer.cache.ImageCache;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Ui;
public abstract class AbstractActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Ui.adjustOrientation(this);
Ui.updateTranslucent(this);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Ui.updateTranslucent(this);
}
@Override
protected void onResume() {
super.onResume();
Ui.adjustOrientation(this);
Ui.updateTranslucent(this);
}
@Override
public void onStart() {
protected void onStart() {
super.onStart();
if (Config.getAllowAnalyics())
EasyTracker.getInstance(this).activityStart(this);
Ui.adjustOrientation(this);
}
@Override
public void onStop() {
protected void onStop() {
super.onStop();
if (Config.getAllowAnalyics())
EasyTracker.getInstance(this).activityStop(this);
ImageCache.getInstance(this).flush();
}
}
@@ -1,70 +0,0 @@
/*
* 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.ui;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import com.google.analytics.tracking.android.EasyTracker;
import com.hippo.ehviewer.cache.ImageCache;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Ui;
public abstract class AbstractFragmentActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Ui.adjustOrientation(this);
Ui.updateTranslucent(this);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Ui.updateTranslucent(this);
}
@Override
protected void onResume() {
super.onResume();
Ui.adjustOrientation(this);
Ui.updateTranslucent(this);
}
@Override
public void onStart() {
super.onStart();
if (Config.getAllowAnalyics())
EasyTracker.getInstance(this).activityStart(this);
}
@Override
public void onStop() {
super.onStop();
if (Config.getAllowAnalyics())
EasyTracker.getInstance(this).activityStop(this);
ImageCache.getInstance(this).flush();
}
}
@@ -35,7 +35,6 @@ import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.ehclient.ListParser;
import com.hippo.ehviewer.widget.FswView;
import com.hippo.ehviewer.widget.OnFitSystemWindowsListener;
import com.hippo.ehviewer.widget.PullViewGroup;
import com.hippo.ehviewer.widget.RefreshTextView;
import com.hippo.ehviewer.widget.SuperToast;
@@ -253,19 +252,19 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
setContentView(getLayoutRes());
mAppContext = (AppContext)getApplication();
mClient = mAppContext.getEhClient();
mClient = EhClient.getInstance();
mGiList = new ArrayList<GalleryInfo>();
mMainView = (RelativeLayout)findViewById(R.id.main);
mPullViewGroup = (PullViewGroup)findViewById(R.id.list);
mPullViewGroup = (PullViewGroup)findViewById(R.id.gallery_list);
mPullViewGroup.setAgainstToChildPadding(true);
mContentView = mPullViewGroup.getContentView();
mRefreshTextView = (RefreshTextView)findViewById(R.id.refresh_text);
FswView alignment = (FswView)findViewById(R.id.alignment);
alignment.addOnFitSystemWindowsListener(
new OnFitSystemWindowsListener() {
new FswView.OnFitSystemWindowsListener() {
@Override
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
@@ -502,7 +501,7 @@ public abstract class AbstractGalleryActivity extends AbstractSlidingActivity
default:
mRefreshTextView.setRefreshing(false);
mRefreshTextView.setVisibility(View.GONE);
new SuperToast(AbstractGalleryActivity.this, eMsg, SuperToast.ERROR).show();
new SuperToast(eMsg, SuperToast.ERROR).show();
}
mPullViewGroup.setAnyRefreshComplete(false);
}
@@ -1,223 +0,0 @@
/*
* 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.ui;
import java.util.List;
import android.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.hippo.ehviewer.ListUrls;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.Comment;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.FswView;
import com.hippo.ehviewer.widget.LinkifyTextView;
import com.hippo.ehviewer.widget.OnFitSystemWindowsListener;
import com.hippo.ehviewer.widget.SuperToast;
public class CommentsSectionFragment extends Fragment
implements AdapterView.OnItemLongClickListener, AdapterView.OnItemClickListener {
@SuppressWarnings("unused")
private static final String TAG = "CommentsSectionFragment";
private GalleryDetailActivity mActivity;
private View mRootView;
private ListView mList;
private View mWaitView;
private View mRefreshButton;
private List<Comment> mComments;
private final BaseAdapter adapter = new CommentsAdapter();
private AlertDialog mLongClickDialog;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mActivity = (GalleryDetailActivity)getActivity();
mRootView = inflater.inflate(
R.layout.comments, container, false);
mList = (ListView)mRootView.findViewById(R.id.commtens_list);
mWaitView = mRootView.findViewById(R.id.commtens_wait);
mRefreshButton = mRootView.findViewById(R.id.commtens_refresh);
//mRefreshButton.setOnClickListener(this);
FswView align = (FswView)mActivity.findViewById(R.id.alignment);
int paddingLeft = align.getPaddingLeft();
int paddingTop = align.getPaddingTop();
int paddingRight = align.getPaddingRight();
int paddingBottom = align.getPaddingBottom();
if (paddingTop != 0 || paddingBottom != 0) {
mList.setPadding(paddingLeft, paddingTop,
paddingRight, paddingBottom);
}
align.addOnFitSystemWindowsListener(new OnFitSystemWindowsListener() {
@Override
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
mList.setPadding(paddingLeft, paddingTop,
paddingRight, paddingBottom);
}
});
mList.setAdapter(adapter);
mList.setOnItemClickListener(this);
mList.setOnItemLongClickListener(this);
mComments = mActivity.getComments();
if (mComments != null) {
adapter.notifyDataSetChanged();
mWaitView.setVisibility(View.GONE);
}
return mRootView;
}
public void setComments(List<Comment> comments) {
mComments = comments;
adapter.notifyDataSetChanged();
if (mWaitView != null)
mWaitView.setVisibility(View.GONE);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// Handler url here
LinkifyTextView comment = ((LinkifyTextView)view.findViewById(R.id.comment));
String url = comment.getTouchedUrl();
if (url != null) {
comment.clearTouchedUrl();
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view,
int position, long id) {
final Comment c = (Comment)parent.getItemAtPosition(position);
mLongClickDialog = new DialogBuilder(mActivity)
.setTitle(R.string.what_to_do).setItems(R.array.comment_long_click,
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
mLongClickDialog.dismiss();
switch (position) {
case 0:
ClipboardManager cm = (ClipboardManager)mActivity
.getSystemService(Context.CLIPBOARD_SERVICE);
cm.setPrimaryClip(ClipData.newPlainText(null, c.comment));
new SuperToast(mActivity).setMessage(R.string.copyed).show();
break;
case 1:
mActivity.finish();
Intent intent = new Intent(mActivity, GalleryListActivity.class);
intent.setAction(GalleryListActivity.ACTION_GALLERY_LIST);
intent.putExtra(GalleryListActivity.KEY_MODE, ListUrls.MODE_UPLOADER);
intent.putExtra(GalleryListActivity.KEY_UPLOADER, c.user);
startActivity(intent);
break;
}
}
}).setNegativeButton(android.R.string.cancel,
new View.OnClickListener() {
@Override
public void onClick(View v) {
mLongClickDialog.dismiss();
}
}).create();
mLongClickDialog.show();
return true;
}
private class CommentsAdapter extends BaseAdapter {
@Override
public int getCount() {
if (mComments == null)
return 0;
else
return mComments.size();
}
@Override
public Object getItem(int position) {
return mComments.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
boolean isUserSame = true;
boolean isTimeSame = true;
if (convertView == null) {
convertView = LayoutInflater.from(mActivity)
.inflate(R.layout.comments_item, null);
}
Comment c = mComments.get(position);
TextView user = (TextView)convertView.findViewById(R.id.user);
if (!c.user.equals(user.getText())) {
isUserSame = false;
user.setText(c.user);
}
TextView time = (TextView)convertView.findViewById(R.id.time);
if (!c.time.equals(time.getText())) {
isTimeSame = false;
time.setText(c.time);
}
// No one can post one comment at same this time
if (!isUserSame || !isTimeSame) {
TextView comment = ((TextView)convertView.findViewById(R.id.comment));
comment.setText(Html.fromHtml(c.comment));
}
return convertView;
}
}
}
@@ -1,862 +0,0 @@
/*
* 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.ui;
import java.util.AbstractMap.SimpleEntry;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Path;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.StateListDrawable;
import android.graphics.drawable.shapes.PathShape;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.ScrollView;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.ViewSwitcher;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.ImageLoader;
import com.hippo.ehviewer.ListUrls;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.Comment;
import com.hippo.ehviewer.data.Data;
import com.hippo.ehviewer.data.GalleryDetail;
import com.hippo.ehviewer.data.PreviewList;
import com.hippo.ehviewer.ehclient.DetailParser;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Theme;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.AutoWrapLayout;
import com.hippo.ehviewer.widget.ButtonsDialogBuilder;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.FswView;
import com.hippo.ehviewer.widget.LoadImageView;
import com.hippo.ehviewer.widget.OnFitSystemWindowsListener;
import com.hippo.ehviewer.widget.ProgressiveRatingBar;
import com.hippo.ehviewer.widget.SimpleGridLayout;
import com.hippo.ehviewer.widget.SuperToast;
public class DetailSectionFragment extends Fragment
implements View.OnClickListener, PreviewList.PreviewHolder,
View.OnLayoutChangeListener, ViewSwitcher.ViewFactory {
private static final String TAG = DetailSectionFragment.class.getSimpleName();
private AppContext mAppContext;
private GalleryDetailActivity mActivity;
private EhClient mClient;
private Data mData;
private GalleryDetail mGalleryDetail;
private String mUrl;
private View mRootView;
private ScrollView mScrollView;
private ViewGroup mHeaderView;
private LoadImageView mThumb;
private TextView mTitle;
private TextView mUploader;
private TextView mCategory;
private Button mReadButton;
private Button mRateButton;
private View mColorfulBar;
private ProgressBar mWaitPb;
private Button mRefreshButton;
private ViewGroup mNormalView;
private ViewGroup mOffensiveView;
private ViewGroup mPiningView;
private ViewGroup mPreviewListMain;
private SimpleGridLayout mPreviewListLayout;
private ProgressBar mWaitPreviewList;
private Button mPreviewRefreshButton;
private View mBottomPanel;
private TextView mPreviewNumText;
private View mCancelButton;
private View mOnceButton;
private View mEveryButton;
private View mBackButton;
private View mFrontButton;
private View mKnownButton;
private View mDivider;
private AlertDialog mGoToDialog;
private AlertDialog mTagDialog;
private int mCurPage;
private boolean mShowPreview = false;
private boolean isSetViewFactory = false;
private ShapeDrawable getArrowShapeDrawable(int color, boolean isToLeft) {
Path path = new Path();
if (isToLeft) {
path.moveTo(50, 0);
path.lineTo(50, 100);
path.lineTo(0, 50);
path.close();
} else {
path.moveTo(0, 0);
path.lineTo(0, 100);
path.lineTo(50, 50);
path.close();
}
ShapeDrawable d = new ShapeDrawable(new PathShape(path, 50, 100));
d.getPaint().setColor(color);
return d;
}
private StateListDrawable getArrowClickDrawable(int color, boolean isToLeft) {
StateListDrawable sld = new StateListDrawable();
ShapeDrawable normal = getArrowShapeDrawable(color, isToLeft);
ShapeDrawable grey = getArrowShapeDrawable(Theme.GREY_COLOR, isToLeft);
ShapeDrawable dark = getArrowShapeDrawable(Theme.getDarkerColor(color), isToLeft);
sld.addState(new int[]{-android.R.attr.state_enabled}, grey);
sld.addState(new int[]{android.R.attr.state_enabled, android.R.attr.state_selected}, dark);
sld.addState(new int[]{android.R.attr.state_enabled, android.R.attr.state_focused}, dark);
sld.addState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}, dark);
sld.addState(new int[]{}, normal);
return sld;
}
@Override
public int getCurPreviewPage() {
return mCurPage;
}
@Override
public void onGetPreviewImageFailure() {
mWaitPreviewList.setVisibility(View.GONE);
mPreviewRefreshButton.setVisibility(View.VISIBLE);
}
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (mShowPreview) {
mShowPreview = false;
mScrollView.smoothScrollTo(0,
mNormalView.getTop() + mDivider.getTop());
}
}
@SuppressLint("InflateParams")
@Override
public View makeView() {
LayoutInflater inflater = LayoutInflater.from(mActivity);
return inflater.inflate(R.layout.detail_avg_text, null);
}
public void handleDetail(GalleryDetail gd) {
mGalleryDetail = gd;
mUrl = mClient.getDetailUrl(
mGalleryDetail.gid, mGalleryDetail.token);
mThumb.setImageDrawable(null);
if (mGalleryDetail.thumb != null) {
mThumb.setLoadInfo(mGalleryDetail.thumb, String.valueOf(mGalleryDetail.gid));
ImageLoader.getInstance(mActivity).add(mGalleryDetail.thumb, String.valueOf(mGalleryDetail.gid),
new LoadImageView.SimpleImageGetListener(mThumb).setTransitabled(false));
mTitle.setText(mGalleryDetail.title);
mUploader.setText(mGalleryDetail.uploader);
mCategory.setText(Ui.getCategoryText(mGalleryDetail.category));
mCategory.setBackgroundColor(Ui.getCategoryColor(mGalleryDetail.category));
// Disable them for temp
mReadButton.setEnabled(false);
mRateButton.setEnabled(false);
} else {
mHeaderView.setVisibility(View.GONE);
mColorfulBar.setVisibility(View.GONE);
mThumb.setLoadInfo(null, null);
}
if (mGalleryDetail.size == null) {
mRefreshButton.setVisibility(View.GONE);
mWaitPb.setVisibility(View.VISIBLE);
mNormalView.setVisibility(View.GONE);
mOffensiveView.setVisibility(View.GONE);
mPiningView.setVisibility(View.GONE);
mClient.getGDetail(mUrl, mGalleryDetail, new GDetailGetListener());
} else {
mRefreshButton.setVisibility(View.GONE);
mWaitPb.setVisibility(View.GONE);
mNormalView.setVisibility(View.VISIBLE);
mOffensiveView.setVisibility(View.GONE);
mPiningView.setVisibility(View.GONE);
layout(mGalleryDetail);
}
/*
ImageLoader.getInstance(mActivity).add(mGalleryDetail.thumb, String.valueOf(mGalleryDetail.gid),
new ImageLoader.OnGetImageListener() {
@Override
public void onGetImage(String key, Bitmap bmp) {
mClient.getGListFromImageSearch(bmp, EhClient.IMAGE_SEARCH_USE_SIMILARITY_SCAN,
null, new EhClient.OnGetGListListener() {
@Override
public void onSuccess(Object checkFlag, List<GalleryInfo> giList,
int maxPage) {
Log.d(TAG, "giList.size() = " + giList.size());
}
@Override
public void onFailure(Object checkFlag, String eMsg) {
Log.d(TAG, eMsg);
}
});
}
});*/
}
@SuppressWarnings("deprecation")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mActivity = (GalleryDetailActivity)getActivity();
mAppContext = (AppContext)mActivity.getApplication();
mClient = mAppContext.getEhClient();
mData = mAppContext.getData();
mRootView = inflater.inflate(
R.layout.detail, container, false);
mScrollView = (ScrollView)mRootView.findViewById(R.id.manga_detail_scrollview);
mHeaderView = (ViewGroup)mRootView.findViewById(R.id.detail_header);
mThumb = (LoadImageView)mHeaderView.findViewById(R.id.detail_cover);
mTitle = (TextView)mHeaderView.findViewById(R.id.detail_title);
mUploader = (TextView)mHeaderView.findViewById(R.id.detail_uploader);
mCategory = (TextView)mHeaderView.findViewById(R.id.detail_category);
mReadButton = (Button)mHeaderView.findViewById(R.id.detail_read);
mRateButton = (Button)mHeaderView.findViewById(R.id.detail_do_rate);
mColorfulBar = mRootView.findViewById(R.id.colorful_bar);
mWaitPb = (ProgressBar)mRootView.findViewById(R.id.detail_wait);
mRefreshButton = (Button)mRootView.findViewById(R.id.detail_refresh);
mNormalView = (ViewGroup)mRootView.findViewById(R.id.manga_detail_normal);
mOffensiveView = (ViewGroup)mRootView.findViewById(R.id.manga_detail_offensive);
mPiningView = (ViewGroup)mRootView.findViewById(R.id.manga_detail_pining);
mPreviewListMain = (ViewGroup)mRootView.findViewById(R.id.page_list);
mPreviewListLayout = (SimpleGridLayout)mRootView.findViewById(R.id.preview_list_layout);
mWaitPreviewList = (ProgressBar)mRootView.findViewById(R.id.paper_list_wait);
mPreviewRefreshButton = (Button)mRootView.findViewById(R.id.preview_button_refresh);
mBottomPanel = mRootView.findViewById(R.id.bottom_panel);
mPreviewNumText = (TextView)mBottomPanel.findViewById(R.id.preview_num);
mCancelButton = mOffensiveView.findViewById(R.id.detail_button_cancel);
mOnceButton = mOffensiveView.findViewById(R.id.detail_button_once);
mEveryButton = mOffensiveView.findViewById(R.id.detail_button_every);
mKnownButton = mPiningView.findViewById(R.id.detail_button_known);
mBackButton = mPreviewListMain.findViewById(R.id.back);
mFrontButton = mPreviewListMain.findViewById(R.id.front);
mDivider = mNormalView.findViewById(R.id.divider);
boolean isRandomColor = Config.getRandomThemeColor();
int color = Config.getThemeColor();
// Set random color
if (isRandomColor)
color = Theme.getRandomDarkColor();
mReadButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mRateButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
if (isRandomColor)
color = Theme.getRandomDarkColor();
mColorfulBar.setBackgroundColor(color);
if (isRandomColor)
color = Theme.getRandomDarkColor();
mRefreshButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mCancelButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mOnceButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mEveryButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mKnownButton.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
if (isRandomColor)
color = Theme.getRandomDarkColor();
mPreviewNumText.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
mBackButton.setBackgroundDrawable(getArrowClickDrawable(color, true));
mFrontButton.setBackgroundDrawable(getArrowClickDrawable(color, false));
mUploader.setOnClickListener(this);
mRefreshButton.setOnClickListener(this);
FswView align = (FswView)mActivity.findViewById(R.id.alignment);
int paddingLeft = align.getPaddingLeft();
int paddingTop = align.getPaddingTop();
int paddingRight = align.getPaddingRight();
int paddingBottom = align.getPaddingBottom();
if (paddingTop != 0 || paddingBottom != 0) {
mScrollView.setPadding(paddingLeft, paddingTop,
paddingRight, paddingBottom);
}
align.addOnFitSystemWindowsListener(new OnFitSystemWindowsListener() {
@Override
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
mScrollView.setPadding(paddingLeft, paddingTop,
paddingRight, paddingBottom);
}
});
mScrollView.addOnLayoutChangeListener(this);
mPreviewListLayout.setColumnCountPortrait(
Config.getPreviewColumnsPortrait());
mPreviewListLayout.setColumnCountLandscape(
Config.getPreviewColumnsLandscape());
// Load first detail
mActivity.loadDetail();
return mRootView;
}
private void refreshPageList() {
mPreviewListLayout.removeAllViews();
mPreviewNumText.setText(String.format("%d / %d",
mCurPage+1, mGalleryDetail.previewSum));
PreviewList pageList = mGalleryDetail.previewLists[mCurPage];
if (pageList == null) {
// Update layout
mWaitPreviewList.setVisibility(View.VISIBLE);
mPreviewRefreshButton.setVisibility(View.GONE);
mUrl = mClient.getDetailUrl(
mGalleryDetail.gid, mGalleryDetail.token, mCurPage);
mClient.getPreviewList(mUrl, mCurPage,
new EhClient.OnGetPreviewListListener() {
@Override
public void onSuccess(Object checkFlag, PreviewList pageList) {
if (mActivity.isFinishing())
return;
mWaitPreviewList.setVisibility(View.GONE);
mPreviewRefreshButton.setVisibility(View.GONE);
int page = (Integer)checkFlag;
mGalleryDetail.previewLists[page] = pageList;
mGalleryDetail.previewLists[page].setData(DetailSectionFragment.this, mActivity, mGalleryDetail, page);
mGalleryDetail.previewLists[page].addPreview(mPreviewListLayout);
mShowPreview = true;
}
@Override
public void onFailure(Object checkFlag, String eMsg) {
if (mActivity.isFinishing())
return;
int page = (Integer)checkFlag;
if (page == mCurPage) {
new SuperToast(mActivity).setIcon(R.drawable.ic_warning)
.setMessage(eMsg)
.show();
mWaitPreviewList.setVisibility(View.GONE);
mPreviewRefreshButton.setVisibility(View.VISIBLE);
}
}
});
} else {
// Update layout
mWaitPreviewList.setVisibility(View.GONE);
mPreviewRefreshButton.setVisibility(View.GONE);
mGalleryDetail.previewLists[mCurPage].addPreview(mPreviewListLayout);
mShowPreview = true;
}
}
private AlertDialog createGoToDialog() {
return new DialogBuilder(mActivity).setTitle(R.string.jump)
.setAdapter(new BaseAdapter() {
@Override
public int getCount() {
return mGalleryDetail.previewSum;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@SuppressLint({ "ViewHolder", "InflateParams" })
@Override
public View getView(int position, View convertView,
ViewGroup parent) {
LayoutInflater inflater = mActivity.getLayoutInflater();
View view = inflater.inflate(R.layout.list_item_text, null);
TextView tv = (TextView)view.findViewById(android.R.id.text1);
tv.setText(String.format(getString(R.string.some_page), position + 1));
return tv;
}
}, new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
mGoToDialog.dismiss();
if (position != mCurPage) {
mCurPage = position;
refreshPageList();
}
}
}).setNegativeButton(android.R.string.cancel, new View.OnClickListener() {
@Override
public void onClick(View paramView) {
mGoToDialog.dismiss();
}
}).create();
}
@SuppressWarnings("deprecation")
private void addTags() {
LinearLayout tagsLayout = (LinearLayout)mRootView.findViewById(R.id.tags_layout);
LinkedHashMap<String, LinkedList<SimpleEntry<String, Integer>>> tagGroups =
mGalleryDetail.tags;
tagsLayout.removeAllViews();
int x = Ui.dp2pix(4);
int y = Ui.dp2pix(4);
Resources resources = getResources();
// color
boolean isRandomColor = Config.getRandomThemeColor();
int color = Config.getThemeColor();
// Get tag view resources
int tagTextSize = resources.getDimensionPixelOffset(R.dimen.button_small_size);
ColorStateList tagTextColor = resources.getColorStateList(R.color.blue_bn_text);
int tagPaddingX = resources.getDimensionPixelOffset(R.dimen.button_tag_padding_x);
int tagPaddingY = resources.getDimensionPixelOffset(R.dimen.button_tag_padding_y);
for (Entry<String, LinkedList<SimpleEntry<String, Integer>>> tagGroup : tagGroups.entrySet()) {
LinearLayout tagGroupLayout = new LinearLayout(mActivity);
tagGroupLayout.setOrientation(LinearLayout.HORIZONTAL);
AutoWrapLayout tagLayout = new AutoWrapLayout(mActivity);
// Group name
final String groupName = tagGroup.getKey();
TextView groupNameView = new TextView(new ContextThemeWrapper(mActivity, R.style.TextTag));
groupNameView.setText(groupName);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.setMargins(x, y, x, y);
tagGroupLayout.addView(groupNameView, lp);
// tags
// get random color
if (isRandomColor)
color = Theme.getRandomDarkColor();
for (SimpleEntry<String, Integer> tag : tagGroup.getValue()) {
final String tagText = tag.getKey();
Button tagView = new Button(mActivity);
tagView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tagTextSize);
tagView.setText(tagText);
tagView.setTextColor(tagTextColor);
tagView.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
tagView.setPadding(tagPaddingX, tagPaddingY, tagPaddingX, tagPaddingY);
tagView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
AlertButton voteUp = new AlertButton(mActivity);
voteUp.setText(getString(R.string.vote_up));
voteUp.setOnClickListener(new SimpleVote(groupName, tagText, true));
AlertButton voteDown = new AlertButton(mActivity);
voteDown.setText(getString(R.string.vote_down));
voteDown.setOnClickListener(new SimpleVote(groupName, tagText, false));
AlertButton showTagged = new AlertButton(mActivity);
showTagged.setText(getString(R.string.show_tagged));
showTagged.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mTagDialog.dismiss();
mActivity.finish();
Intent intent = new Intent(mActivity,GalleryListActivity.class);
intent.setAction(GalleryListActivity.ACTION_GALLERY_LIST);
intent.putExtra(GalleryListActivity.KEY_MODE,
ListUrls.MODE_TAG);
intent.putExtra(GalleryListActivity.KEY_TAG, groupName + ":" + tagText);
startActivity(intent);
}
});
mTagDialog = new ButtonsDialogBuilder(mActivity).setTitle(tagText)
.addButton(voteUp).addButton(voteDown).addButton(showTagged)
.create();
mTagDialog.show();
}
});
AutoWrapLayout.LayoutParams alp = new AutoWrapLayout.LayoutParams();
alp.setMargins(x, y, x, y);
tagLayout.addView(tagView, alp);
}
tagGroupLayout.addView(tagLayout);
tagsLayout.addView(tagGroupLayout);
}
// Add tag
if (isRandomColor)
color = Theme.getRandomDarkColor();
Button addtagView = new Button(mActivity);
addtagView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tagTextSize);
addtagView.setText("+");
addtagView.setTextColor(tagTextColor);
addtagView.setBackgroundDrawable(Theme.getClickDrawable(mActivity, color));
addtagView.setPadding(tagPaddingX, tagPaddingY, tagPaddingX, tagPaddingY);
addtagView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO
new SuperToast(mActivity)
.setMessage(R.string.unfinished)
.show();
}
});
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.RIGHT;
lp.setMargins(x, y, x, y);
tagsLayout.addView(addtagView, lp);
}
private void layout(GalleryDetail md) {
if (mActivity.isFinishing())
return;
// Delete progress bar
mWaitPb.setVisibility(View.GONE);
// Check offensive or not
if (md.firstPage.equals("offensive")) {
mOffensiveView.setVisibility(View.VISIBLE);
mCancelButton.setOnClickListener(this);
mOnceButton.setOnClickListener(this);
mEveryButton.setOnClickListener(this);
}
// Check pining or not
else if (md.firstPage.equals("pining")) {
mPiningView.setVisibility(View.VISIBLE);
mKnownButton.setOnClickListener(this);
}
else {
// Set unset info
if (mThumb.getUrl() == null) {
mHeaderView.setVisibility(View.VISIBLE);
mColorfulBar.setVisibility(View.VISIBLE);
mThumb.setLoadInfo(mGalleryDetail.thumb, String.valueOf(mGalleryDetail.gid));
ImageLoader.getInstance(mActivity).add(mGalleryDetail.thumb, String.valueOf(mGalleryDetail.gid),
new LoadImageView.SimpleImageGetListener(mThumb).setTransitabled(false));
mTitle.setText(mGalleryDetail.title);
mUploader.setText(mGalleryDetail.uploader);
mCategory.setText(Ui.getCategoryText(mGalleryDetail.category));
mCategory.setBackgroundColor(Ui.getCategoryColor(mGalleryDetail.category));
}
// Enable button
mReadButton.setEnabled(true);
mReadButton.setOnClickListener(this);
mRateButton.setEnabled(true);
mRateButton.setOnClickListener(this);
RatingBar rate = (RatingBar)mRootView.findViewById(R.id.detail_rate);
rate.setRating(mGalleryDetail.rating);
TextSwitcher averagePeople = (TextSwitcher)mRootView.findViewById(R.id.detail_average_people);
if (!isSetViewFactory) {
averagePeople.setFactory(this);
isSetViewFactory = true;
}
averagePeople.setCurrentText(String.format("%.2f (%d)",
mGalleryDetail.rating, mGalleryDetail.people));
TextView posted = (TextView)mRootView.findViewById(R.id.detail_posted);
posted.setText(mGalleryDetail.posted);
TextView language = (TextView)mRootView.findViewById(R.id.detail_language);
language.setText(String.format(getString(R.string.detail_language), mGalleryDetail.language));
TextView pagesSize = (TextView)mRootView.findViewById(R.id.detail_pages_size);
pagesSize.setText(String.format(getString(R.string.detail_pages_size),
mGalleryDetail.pages, mGalleryDetail.size));
addTags();
mNormalView.setVisibility(View.VISIBLE);
// paper list
if (mGalleryDetail.previewLists[0] != null) {
mPreviewListMain.setVisibility(View.VISIBLE);
// preview num
mBottomPanel.setVisibility(View.VISIBLE);
mPreviewNumText.setText(String.format("%d / %d",
1, mGalleryDetail.previewSum));
mPreviewRefreshButton.setOnClickListener(this);
// Init go to dialog or disable it
if (mGalleryDetail.previewSum > 1) {
mGoToDialog = createGoToDialog();
mPreviewNumText.setOnClickListener(this);
mBackButton.setOnClickListener(this);
mFrontButton.setOnClickListener(this);
} else {
mPreviewNumText.setClickable(false);
mBackButton.setClickable(false);
mFrontButton.setClickable(false);
}
mCurPage = 0;
mPreviewListLayout.removeAllViews();
mGalleryDetail.previewLists[0].setData(this, mActivity, mGalleryDetail, 0);
mGalleryDetail.previewLists[0].addPreview(mPreviewListLayout);
} else {
new SuperToast(mActivity, R.string.detail_preview_error, SuperToast.WARNING);
}
// Set comments
mActivity.setComments(mGalleryDetail.comments);
}
}
@Override
public void onClick(View v) {
if (v == mUploader) {
mActivity.finish();
Intent intent = new Intent(mActivity, GalleryListActivity.class);
intent.setAction(GalleryListActivity.ACTION_GALLERY_LIST);
intent.putExtra(GalleryListActivity.KEY_MODE, ListUrls.MODE_UPLOADER);
intent.putExtra(GalleryListActivity.KEY_UPLOADER, mUploader.getText());
startActivity(intent);
} else if (v == mRateButton) {
rate(mGalleryDetail.rating);
} else if (v == mReadButton) {
mData.addRead(mGalleryDetail);
Intent intent = new Intent(mActivity,
GalleryActivity.class);
intent.putExtra("url", mGalleryDetail.firstPage);
intent.putExtra("gid", mGalleryDetail.gid);
intent.putExtra("title", mGalleryDetail.title);
intent.putExtra("firstPage", 0);
intent.putExtra("pageSum", mGalleryDetail.pages);
startActivity(intent);
} else if (v == mRefreshButton) {
GDetailGetListener listener = new GDetailGetListener();
mClient.getGDetail(mUrl, mGalleryDetail, listener);
// Delete refresh button
mRefreshButton.setVisibility(View.GONE);
// Add progressBar
mWaitPb.setVisibility(View.VISIBLE);
} else if (v == mCancelButton
| v == mKnownButton) {
mActivity.finish();
} else if (v == mOnceButton) {
// TODO create a class uri
GDetailGetListener listener = new GDetailGetListener();
mClient.getGDetail(mUrl + "&nw=session", mGalleryDetail, listener);
// Delete offensiveView
mOffensiveView.setVisibility(View.GONE);
// Add progressBar
mWaitPb.setVisibility(View.VISIBLE);
} else if (v == mEveryButton) {
GDetailGetListener listener = new GDetailGetListener();
mClient.getGDetail(mUrl + "&nw=always", mGalleryDetail, listener);
// Delete offensiveView
mOffensiveView.setVisibility(View.GONE);
// Add progressBar
mWaitPb.setVisibility(View.VISIBLE);
} else if (v == mBackButton) {
if (mCurPage <= 0)
return;
mCurPage--;
refreshPageList();
} else if (v == mFrontButton) {
if (mCurPage >= mGalleryDetail.previewSum - 1)
return;
mCurPage++;
refreshPageList();
} else if (v == mPreviewRefreshButton) {
refreshPageList();
} else if (v == mPreviewNumText) {
mGoToDialog.show();
}
}
private int getSendableRating(float ratingFloat) {
float dr = ratingFloat*2;
return (int)(dr + 0.5);
}
@SuppressLint("InflateParams")
public void rate(float defaultRating) {
View view = mActivity.getLayoutInflater().inflate(R.layout.rate, null);
final TextView tv = (TextView)view.findViewById(R.id.rate_text);
final ProgressiveRatingBar rb = (ProgressiveRatingBar)view.findViewById(R.id.rate);
rb.setOnDrawListener(new ProgressiveRatingBar.OnDrawListener() {
@Override
public void onDraw(float rating) {
int textId = getResources().getIdentifier(mAppContext.getPackageName()
+ ":string/rating" + getSendableRating(rating), null, null);
if (textId == 0)
textId = R.string.rating0;
tv.setText(textId);
}
});
rb.setRating(defaultRating);
new DialogBuilder(mActivity).setTitle(R.string.rate)
.setView(view, true)
.setPositiveButton(android.R.string.ok, new OnClickListener() {
@Override
public void onClick(View v) {
int rating = getSendableRating(rb.getRating());
if (rating <= 0 || rating > 10)
new SuperToast(mActivity)
.setIcon(R.drawable.ic_warning)
.setMessage(R.string.invalid_rating)
.show();
else {
((AlertButton)v).dialog.dismiss();
mClient.rate(mGalleryDetail.gid, mGalleryDetail.token,
rating, new EhClient.OnRateListener() {
@Override
public void onSuccess(float ratingAvg,
int ratingCnt) {
mGalleryDetail.rating = ratingAvg;
mGalleryDetail.people = ratingCnt;
if (!mActivity.isFinishing()) {
//Reset start
RatingBar rate = (RatingBar)mRootView.findViewById(R.id.detail_rate);
rate.setRating(mGalleryDetail.rating);
TextSwitcher averagePeople = (TextSwitcher)
mRootView.findViewById(R.id.detail_average_people);
averagePeople.setText(String.format("%.2f (%d)",
mGalleryDetail.rating, mGalleryDetail.people));
}
new SuperToast(mActivity).setMessage(R.string.rate_succeeded).show();
}
@Override
public void onFailure(String eMsg) {
new SuperToast(mActivity).setIcon(R.drawable.ic_warning)
.setMessage(getString(R.string.rate_failed) + "\n" + eMsg)
.show();
}
});
}
}
}).setNegativeButton(android.R.string.cancel, new OnClickListener(){
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
}
}).create().show();
}
public List<Comment> getComments() {
if (mGalleryDetail == null)
return null;
else
return mGalleryDetail.comments;
}
private class GDetailGetListener
implements EhClient.OnGetGDetailListener {
@Override
public void onSuccess(GalleryDetail md) {
layout(md);
}
@Override
public void onFailure(String eMsg) {
// Delete progress bar
// Show refresh button
mWaitPb.setVisibility(View.GONE);
mRefreshButton.setVisibility(View.VISIBLE);
new SuperToast(mActivity).setIcon(R.drawable.ic_warning).setMessage(eMsg).show();
}
}
private class SimpleVote implements View.OnClickListener {
private final String groupName;
private final String tagText;
private final boolean isUp;
public SimpleVote(String groupName, String tagText, boolean isUp) {
this.groupName = groupName;
this.tagText = tagText;
this.isUp = isUp;
}
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
mClient.vote(mGalleryDetail.gid, mGalleryDetail.token,
groupName, tagText, isUp, new SimpleVoteListener());
}
}
private class SimpleVoteListener implements EhClient.OnVoteListener {
@Override
public void onSuccess(String tagPane) {
new SuperToast(mActivity).setMessage(R.string.vote_succeeded).show();
DetailParser parser = new DetailParser();
if (parser.parser(tagPane, DetailParser.TAG) ==
DetailParser.TAG) {
mGalleryDetail.tags = parser.tags;
addTags();
} else {
new SuperToast(mActivity).setIcon(R.drawable.ic_warning).setMessage(R.string.em_parser_error).show();
}
}
@Override
public void onFailure(String eMsg) {
new SuperToast(mActivity).setIcon(R.drawable.ic_warning).setMessage(getString(R.string.vote_failed) + "\n"+ eMsg).show();
}
}
}
@@ -28,7 +28,7 @@ import com.hippo.ehviewer.service.DownloadServiceConnection;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Download;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.DownloadItemLayout;
@@ -86,9 +86,9 @@ public class DownloadActivity extends AbstractActivity {
mServiceConn.getService().cancel(Download.getKey(longClickItemIndex));
mDlAdapter.notifyDataSetChanged();
// TODO 有人反馈 Download.get(longClickItemIndex).title 为空,看来很有必要在正则抓取时检查是否为空
File dir = new File(Config.getDownloadPath(), Util.rightFileName(Download.get(longClickItemIndex).title));
File dir = new File(Config.getDownloadPath(), Utils.rightFileName(Download.get(longClickItemIndex).title));
try {
Util.deleteContents(dir);
Utils.deleteContents(dir);
} catch (IOException e) {
e.printStackTrace();
}
@@ -67,7 +67,6 @@ import com.hippo.ehviewer.widget.ActionableToastBar.ActionClickedListener;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.FswView;
import com.hippo.ehviewer.widget.LoadImageView;
import com.hippo.ehviewer.widget.OnFitSystemWindowsListener;
import com.hippo.ehviewer.widget.ProgressDialogBulider;
import com.hippo.ehviewer.widget.PullViewGroup;
import com.hippo.ehviewer.widget.RatingView;
@@ -148,9 +147,9 @@ public class FavouriteActivity extends AbstractGalleryActivity
super.onCreate(savedInstanceState);
mAppContext = (AppContext)getApplication();
mData = mAppContext.getData();
mData = Data.getInstance();
mResources =getResources();
mClient = mAppContext.getEhClient();
mClient = EhClient.getInstance();
final ActionBar actionBar = getActionBar();
getActionBar().setDisplayHomeAsUpEnabled(true);
@@ -267,7 +266,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
});
FswView alignment = (FswView)findViewById(R.id.alignment);
alignment.addOnFitSystemWindowsListener(new OnFitSystemWindowsListener() {
alignment.addOnFitSystemWindowsListener(new FswView.OnFitSystemWindowsListener() {
@Override
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
@@ -296,7 +295,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
// Check login
if (!mClient.isLogin()) {
SuperToast superToast = new SuperToast(this, "未检测到登陆状态,仅可使用本地收藏。由于开发者的问题,本地收藏不可靠,请尽快登陆,将本地收藏转移至账户中的收藏。");
SuperToast superToast = new SuperToast("未检测到登陆状态,仅可使用本地收藏。由于开发者的问题,本地收藏不可靠,请尽快登陆,将本地收藏转移至账户中的收藏。"); // TODO
superToast.setDuration(SuperToast.LENGTH_LONG);
superToast.show();
}
@@ -428,7 +427,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
mPdb = null;
mProgressDialog.dismiss();
mProgressDialog = null;
new SuperToast(this, R.string.move_successfully).show();
new SuperToast(R.string.move_successfully).show();
}
}
@@ -439,8 +438,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (mMenuIndex == position) {
new SuperToast(FavouriteActivity.this, R.string.dst_src_same,
SuperToast.WARNING).show();
new SuperToast(R.string.dst_src_same, SuperToast.WARNING).show();
return;
}
@@ -573,7 +571,7 @@ public class FavouriteActivity extends AbstractGalleryActivity
mLastModifyGiList = gis;
mLastModifyPageNum = pageNum;
refresh();
new SuperToast(FavouriteActivity.this, mSuccStr).show();
new SuperToast(mSuccStr).show();
// add to local
if (mToLocal)
+58 -68
View File
@@ -24,6 +24,17 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.ehclient.EhClient;
@@ -32,56 +43,43 @@ import com.hippo.ehviewer.gallery.data.ImageSet;
import com.hippo.ehviewer.gallery.ui.GLRootView;
import com.hippo.ehviewer.network.Downloader;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import com.hippo.ehviewer.util.Log;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.SuperToast;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
public class GalleryActivity extends AbstractActivity {
private String TAG = "MangaActivity";
private final String TAG = "MangaActivity";
private AppContext mAppContext;
private EhClient mEhClient;
private RelativeLayout mainView;
private int gid;
private String title;
private int retryTimes = 0;
private static final int maxRetry = 3;
private boolean stopFlag = false;
// [firstPage, lastPage)
// last 是目前已下载的最后一页的 index + 1
private int pageSum;
private int firstPage;
private int lastPage;
private String allPrePageUrl;
private String allNextPageUrl;
private boolean getPrePage = false;
private boolean mStop = false;
private File mFolder;
private ImageSet mImageSet;
// two element, first is web url, second is image url
private List<String[]> imagesUrl;
// TODO use downloader to download image
// TODO combine it with MangaDownloadActivity
private class MangaUrlGetListener implements EhClient.OnGetMangaUrlListener {
@@ -93,12 +91,12 @@ public class GalleryActivity extends AbstractActivity {
return;
}
retryTimes = 0;
final int index = (Integer)checkFlag;
final String prePageUrl = arg[0];
final String nextPageUrl = arg[1];
final String imageUrl = arg[2];
String[] urls = imagesUrl.get(index);
if (urls == null) {
imagesUrl.set(index, urls = new String[2]);
@@ -117,9 +115,9 @@ public class GalleryActivity extends AbstractActivity {
if (index != firstPage - 1 && (index == firstPage && allPrePageUrl == null) && index != lastPage) {
Log.e(TAG, "targetPage != firstPage - 1 && (targetPage == firstPage && allPrePageUrl == null) && targetPage != lastPage");
}
final String imageName = String.format("%05d", index + 1) + "." + Util.getExtension(imageUrl);
final String imageName = String.format("%05d", index + 1) + "." + Utils.getExtension(imageUrl);
final Downloader downloader = new Downloader(GalleryActivity.this);
try {
downloader.resetData(mFolder.getPath(),
@@ -129,7 +127,7 @@ public class GalleryActivity extends AbstractActivity {
onFailure(checkFlag, mAppContext.getString(R.string.em_url_format_error));
e.printStackTrace();
}
// TODO threadpool
new Thread() {
@Override
@@ -138,14 +136,14 @@ public class GalleryActivity extends AbstractActivity {
if (testImage(mFolder.getPath(), imageName)) {
onGetImage(index, Downloader.COMPLETED, nextPageUrl);
} else {
downloader.run();
onGetImage(index, downloader.getStatus(), nextPageUrl);
}
}
}.start();
}
// TODO only test bitmap here
private boolean testImage(String path, String name) {
boolean isImage = false;
@@ -168,11 +166,11 @@ public class GalleryActivity extends AbstractActivity {
e.printStackTrace();
} finally {
if (fis != null)
Util.closeStreamQuietly(fis);
Utils.closeStreamQuietly(fis);
}
return isImage;
}
private void onGetImage(int index, int state, String nextPageUrl) {
if (state == Downloader.COMPLETED) {
mImageSet.changeState(index, ImageSet.STATE_LOADED);
@@ -189,7 +187,7 @@ public class GalleryActivity extends AbstractActivity {
mImageSet.changeState(lastPage, ImageSet.STATE_LOADING);
}
}
@Override
public void onFailure(Object checkFlag, String eMsg) {
if (stopFlag) {
@@ -199,11 +197,9 @@ public class GalleryActivity extends AbstractActivity {
retryTimes++;
int targetPage = (Integer)checkFlag;
if (retryTimes < maxRetry) {
new SuperToast(GalleryActivity.this)
.setIcon(R.drawable.ic_warning)
.setMessage(eMsg + " " +
String.format(getString(R.string.em_retry_times), retryTimes))
.show(); // TODO
new SuperToast(eMsg + " " +
String.format(getString(R.string.em_retry_times), retryTimes),
SuperToast.WARNING).show(); // TODO
if (targetPage == firstPage - 1 &&
getPrePage == true) {
mEhClient.getMangaUrl(allPrePageUrl, targetPage, new MangaUrlGetListener());
@@ -217,21 +213,17 @@ public class GalleryActivity extends AbstractActivity {
if (targetPage == firstPage - 1 &&
getPrePage == true) {
getPrePage = false;
new SuperToast(GalleryActivity.this)
.setIcon(R.drawable.ic_warning)
.setMessage(R.string.retry_max_pre).show();
new SuperToast(R.string.retry_max_pre, SuperToast.WARNING).show();
}
else {
new SuperToast(GalleryActivity.this)
.setIcon(R.drawable.ic_warning)
.setMessage(R.string.retry_max_next).show();
new SuperToast(R.string.retry_max_next, SuperToast.WARNING).show();
mStop = true;
}
mImageSet.changeState(targetPage, ImageSet.STATE_FAIL);
}
}
}
@SuppressLint("NewApi")
@Override
public void onWindowFocusChanged(boolean hasFocus) {
@@ -245,21 +237,21 @@ public class GalleryActivity extends AbstractActivity {
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gl_root_group);
mAppContext = (AppContext)getApplication();
mEhClient = mAppContext.getEhClient();
mEhClient = EhClient.getInstance();
getActionBar().hide();
// For API < 16 Fullscreen
if (Build.VERSION.SDK_INT < 19) {
@@ -277,33 +269,31 @@ public class GalleryActivity extends AbstractActivity {
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
Intent intent = getIntent();
firstPage = intent.getIntExtra("firstPage", 0);
lastPage = firstPage;
gid = intent.getIntExtra("gid", 0);
title = intent.getStringExtra("title");
mFolder = new File(Config.getDownloadPath(), Util.rightFileName(title));
mFolder = new File(Config.getDownloadPath(), Utils.rightFileName(title));
if (mFolder.isFile())
mFolder.delete();
mFolder.mkdirs();
pageSum = intent.getIntExtra("pageSum", 0);
mImageSet = new ImageSet(this, gid, mFolder, pageSum, firstPage, lastPage, null);
GalleryView isv = new GalleryView(getApplicationContext(), mImageSet, firstPage);
isv.setOnEdgeListener(new GalleryView.OnEdgeListener() {
@Override
public void onLastPageEdge() {
new SuperToast(GalleryActivity.this)
.setMessage(R.string.last_page).show();
new SuperToast(R.string.last_page).show();
}
@Override
public void onFirstPageEdge() {
new SuperToast(GalleryActivity.this)
.setMessage(R.string.first_page).show();
new SuperToast(R.string.first_page).show();
}
});
isv.setOnTapTextListener(new GalleryView.OnTapTextListener() {
@Override
public void onTapText(int index) {
@@ -318,7 +308,7 @@ public class GalleryActivity extends AbstractActivity {
@Override
public void onTapDoubleText(int index) {
// TODO Auto-generated method stub
}
});
isv.setOnScrollPageListener(new GalleryView.OnScrollPageListener() {
@@ -329,7 +319,7 @@ public class GalleryActivity extends AbstractActivity {
mEhClient.getMangaUrl(allNextPageUrl, lastPage, new MangaUrlGetListener());
mImageSet.changeState(lastPage, ImageSet.STATE_LOADING);
}
if (!getPrePage && allPrePageUrl != null
&& !allPrePageUrl.equals("first")
&& index == firstPage - 1) {
@@ -341,24 +331,24 @@ public class GalleryActivity extends AbstractActivity {
});
GLRootView glrv= (GLRootView)findViewById(R.id.gl_root_view);
glrv.setContentPane(isv);
String url = intent.getStringExtra("url");
allNextPageUrl = url;
allPrePageUrl = null;
if (firstPage == 0)
allPrePageUrl = "first";
if (firstPage == pageSum - 1)
allNextPageUrl = "last";
imagesUrl = new ArrayList<String[]>(Collections.nCopies(pageSum, (String[])null));
imagesUrl.set(lastPage, new String[]{url, null});
// Get image and next page
mEhClient.getMangaUrl(url, lastPage, new MangaUrlGetListener());
mImageSet.changeState(lastPage, ImageSet.STATE_LOADING);
}
@Override
protected void onDestroy () {
stopFlag = true;
@@ -16,353 +16,573 @@
package com.hippo.ehviewer.ui;
import java.util.List;
import java.util.Stack;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.widget.ScrollView;
import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.ViewSwitcher;
import com.hippo.ehviewer.Analytics;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.ImageLoader;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.Comment;
import com.hippo.ehviewer.data.ApiGalleryDetail;
import com.hippo.ehviewer.data.GalleryDetail;
import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.data.LofiGalleryDetail;
import com.hippo.ehviewer.data.LofiGalleryInfo;
import com.hippo.ehviewer.drawable.OvalDrawable;
import com.hippo.ehviewer.ehclient.DetailUrlParser;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.service.DownloadService;
import com.hippo.ehviewer.service.DownloadServiceConnection;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Constants;
import com.hippo.ehviewer.util.Favorite;
import com.hippo.ehviewer.util.Theme;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.FswView;
import com.hippo.ehviewer.widget.LoadImageView;
import com.hippo.ehviewer.widget.ProgressiveRatingBar;
import com.hippo.ehviewer.widget.RefreshTextView;
import com.hippo.ehviewer.widget.SuperButton;
import com.hippo.ehviewer.widget.SuperToast;
import com.hippo.ehviewer.windowsanimate.WindowsAnimate;
public class GalleryDetailActivity extends AbstractFragmentActivity
implements ActionBar.TabListener {
public class GalleryDetailActivity extends AbstractActivity
implements View.OnClickListener, FswView.OnFitSystemWindowsListener,
View.OnTouchListener , ViewSwitcher.ViewFactory,
ProgressiveRatingBar.OnUserRateListener {
@SuppressWarnings("unused")
private static final String TAG = "MangaDetailActivity";
private static final String TAG = GalleryDetailActivity.class.getSimpleName();
public static final String KEY_G_INFO = "gallery_info";
private ViewPager mViewPager;
private Stack<GalleryDetail> mGdList;
private GalleryDetail mGalleryDetail;
private Resources mResources;
private EhClient mClient;
private WindowsAnimate mWindowsAnimate;
private GalleryInfo mGalleryInfo;
private DetailSectionFragment mDetailFragment;
private CommentsSectionFragment mCommentsFragment;
private int mRunningAnimateNum = 0;
private boolean isCheckmark = false;
private boolean isSetDrawable = false;
private int mTabIndex;
private RefreshTextView mRefreshText;
private LoadImageView mThumb;
private TextView mTitle;
private TextView mUploader;
private SuperButton mDownloadButton;
private SuperButton mReadButton;
private TextView mCategory;
private TextView mMoreOfUploader;
private TextView mSimilar;
private final DownloadServiceConnection mServiceConn = new DownloadServiceConnection();
private TextSwitcher mRatingText;
private ProgressiveRatingBar mRating;
private TextView mFavorite;
private TextView mRate;
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
private ScrollView mDetailScroll;
private ScrollView mMoreDetailScroll;
private View mDetailHeader;
private View mDetailButtons;
private TextView mWarning;
private View mDetailActions;
private View mDividerAM;
private View mDetailMore;
private View mDividerMR;
private View mDetailRate;
private OvalDrawable mCategoryDrawable;
private Drawable mRateDrawable;
private Drawable mCheckmarkDrawable;
private GalleryInfo handleIntent(Intent intent) {
GalleryInfo gi = null;
if (intent.getAction() == "android.intent.action.VIEW") {
// Start from url
DetailUrlParser parser = new DetailUrlParser();
if (parser.parser(intent.getData().getPath())) {
if (Config.getMode() == EhClient.MODE_LOFI) {
// We can't get info from lofi detail, we need get info from api
gi = new ApiGalleryDetail();
gi.gid = parser.gid;
gi.token = parser.token;
} else {
gi = new GalleryDetail();
gi.gid = parser.gid;
gi.token = parser.token;
}
} else {
// If can not parser url, just keep it null
}
} else {
gi = (GalleryInfo)(intent.getParcelableExtra(KEY_G_INFO));
if (gi != null) {
if (gi instanceof LofiGalleryInfo)
gi = new LofiGalleryDetail((LofiGalleryInfo)gi);
else
gi = new GalleryDetail(gi);
}
}
return gi;
}
/*
@Override
protected void onNewIntent(Intent intent) {
if (mGalleryInfo != null)
mGiStack.push(mGalleryInfo);
setIntent(intent);
mGalleryInfo = handleIntent(intent);
if (mGalleryInfo == null) {
// TODO need a toast ?
if (mGiStack.isEmpty())
finish();
else
mGalleryInfo = mGiStack.pop();
} else {
doPreLayout();
}
}*/
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConn);
}
private GalleryDetail handleIntent(Intent intent) {
GalleryDetail gi = null;
if (intent.getAction() == "android.intent.action.VIEW") {
DetailUrlParser parser = new DetailUrlParser();
if (parser.parser(intent.getData().getPath())) {
gi = new GalleryDetail();
gi.gid = parser.gid;
gi.token = parser.token;
} else {
// TODO
}
} else {
gi = new GalleryDetail((GalleryInfo)
(intent.getParcelableExtra(KEY_G_INFO)));
}
// Analytics
if (gi != null)
Analytics.openGallery(this, gi.gid, gi.token);
return gi;
mWindowsAnimate.free();
}
@Override
protected void onNewIntent(Intent intent) {
mGdList.push(mGalleryDetail);
setIntent(intent);
mGalleryDetail = handleIntent(intent);
loadDetail();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGalleryInfo = handleIntent(getIntent());
if (mGalleryInfo == null)
// If no GalleryInfo pass, just finish
finish();
setContentView(R.layout.gallery_detail);
setTitle(String.valueOf(mGalleryInfo.gid));
mClient = EhClient.getInstance();
mWindowsAnimate = new WindowsAnimate();
mWindowsAnimate.init(this);
mResources = getResources();
final ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
// Get view
mDetailScroll = (ScrollView)findViewById(R.id.detail_scroll);
mMoreDetailScroll = (ScrollView)findViewById(R.id.more_detail_scroll);
mRefreshText = (RefreshTextView)findViewById(R.id.refresh_text);
mDetailHeader = findViewById(R.id.detail_header);
mDetailButtons = findViewById(R.id.detail_buttons);
mWarning = (TextView)findViewById(R.id.warning);
mDetailActions = findViewById(R.id.detail_actions);
mDividerAM = findViewById(R.id.detail_divider_a_m);
mDetailMore = findViewById(R.id.detail_more);
mDividerMR = findViewById(R.id.detail_divider_m_r);
mDetailRate = findViewById(R.id.detail_rate);
mThumb = (LoadImageView)findViewById(R.id.thumb);
mTitle = (TextView)findViewById(R.id.title);
mUploader = (TextView)findViewById(R.id.uploader);
mDownloadButton = (SuperButton)findViewById(R.id.download);
mReadButton = (SuperButton)findViewById(R.id.read);
mCategory = (TextView)findViewById(R.id.category);
mMoreOfUploader = (TextView)findViewById(R.id.more_of_uploader);
mSimilar = (TextView)findViewById(R.id.similar);
mRatingText = (TextSwitcher)mDetailRate.findViewById(R.id.rating_text);
mRating = (ProgressiveRatingBar)mDetailRate.findViewById(R.id.rating);
mFavorite = (TextView)findViewById(R.id.favorite);
mRate = (TextView)findViewById(R.id.rate);
// Get temp view
FswView alignment = (FswView)findViewById(R.id.alignment);
// Set Drawable
Rect rect = new Rect(0, 0, Ui.dp2pix(48), Ui.dp2pix(48));
mCategoryDrawable = new OvalDrawable(0);
mCategoryDrawable.setBounds(0, 0, Ui.dp2pix(48), Ui.dp2pix(48));
mCategory.setCompoundDrawables(null, mCategoryDrawable, null, null);
Drawable moreOfUploaderDrawable = mResources.getDrawable(R.drawable.ic_more_of_uploader);
moreOfUploaderDrawable.setBounds(rect);
mMoreOfUploader.setCompoundDrawables(null, moreOfUploaderDrawable, null, null);
Drawable similarDrawable = mResources.getDrawable(R.drawable.ic_similar);
similarDrawable.setBounds(rect);
mSimilar.setCompoundDrawables(null, similarDrawable, null, null);
Drawable favoriteDrawable = mResources.getDrawable(R.drawable.ic_favorite);
favoriteDrawable.setBounds(rect);
mFavorite.setCompoundDrawables(null, favoriteDrawable, null, null);
mRateDrawable = mResources.getDrawable(R.drawable.ic_rate);
mRateDrawable.setBounds(rect);
mCheckmarkDrawable = mResources.getDrawable(R.drawable.ic_checkmark);
mCheckmarkDrawable.setBounds(rect);
mRate.setCompoundDrawables(null, mRateDrawable, null, null);
// Set ripple
mWindowsAnimate.addRippleEffect(mCategory, false);
mWindowsAnimate.addRippleEffect(mMoreOfUploader, false);
mWindowsAnimate.addRippleEffect(mSimilar, false);
mWindowsAnimate.addRippleEffect(mFavorite, false);
// Init
mRatingText.setFactory(this);
// Set random color
int color = Config.getRandomThemeColor() ? Theme.getRandomDarkColor() : Config.getThemeColor();
int actionBarColor = color & 0x00ffffff | 0xdd000000;
Drawable drawable = new ColorDrawable(actionBarColor);
actionBar.setBackgroundDrawable(drawable);
Ui.translucent(this, actionBarColor);
mDownloadButton.setRoundBackground(true, mResources.getColor(R.color.background_light), color);
mDownloadButton.setTextColor(color);
mReadButton.setRoundBackground(true, color, 0);
((TextView)findViewById(R.id.detail_more_text)).setTextColor(color);
// Set listener
mDownloadButton.setOnClickListener(this);
mReadButton.setOnClickListener(this);
mCategory.setOnClickListener(this);
mMoreOfUploader.setOnClickListener(this);
mSimilar.setOnClickListener(this);
mRating.setOnUserRateListener(this);
mFavorite.setOnClickListener(this);
mRate.setOnClickListener(this);
mDetailMore.setOnTouchListener(this);
alignment.addOnFitSystemWindowsListener(this);
doPreLayout();
}
public void loadDetail() {
setTitle(String.valueOf(mGalleryDetail.gid));
mDetailFragment.handleDetail(mGalleryDetail);
getActionBar().setSelectedNavigationItem(0);
private void doPreLayout() {
String detailUrl = mClient.getDetailUrl(
mGalleryInfo.gid, mGalleryInfo.token);
if (mGalleryInfo instanceof GalleryDetail) {
GalleryDetail galleryDetail = (GalleryDetail)mGalleryInfo;
if (galleryDetail.title == null) {
// TODO
// We should get info from detail page
} else {
mDetailScroll.setVisibility(View.VISIBLE);
mDetailHeader.setVisibility(View.VISIBLE);
mThumb.setLoadInfo(galleryDetail.thumb, String.valueOf(galleryDetail.gid));
ImageLoader.getInstance(this).add(galleryDetail.thumb, String.valueOf(galleryDetail.gid),
new LoadImageView.SimpleImageGetListener(mThumb).setTransitabled(false));
mTitle.setText(galleryDetail.title);
mUploader.setText(galleryDetail.uploader);
mClient.getGDetail(detailUrl, galleryDetail, new GDetailGetListener());
}
} else {
}
}
private String getRatingText(float rating) {
if (rating == Float.NaN)
return "(´_ゝ`)";
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 "(´_ゝ`)";
else
return getString(resId);
}
private String getAllRatingText(float rating, int people) {
return new StringBuilder().append("大家觉得").append(" ") // TODO
.append(getRatingText(rating))
.append(" (").append(rating).append(", ").append(people).append(")").toString();
}
/**
* GalleryDetail
* LofiGalleryDetail
* ApiGalleryDetail
*/
private void doLayout() {
if (mDetailHeader.getVisibility() == View.GONE) {
// If not set header in doPreLayout
mDetailHeader.setVisibility(View.VISIBLE);
mThumb.setLoadInfo(mGalleryInfo.thumb, String.valueOf(mGalleryInfo.gid));
ImageLoader.getInstance(this).add(mGalleryInfo.thumb, String.valueOf(mGalleryInfo.gid),
new LoadImageView.SimpleImageGetListener(mThumb).setTransitabled(false));
mTitle.setText(mGalleryInfo.title);
mUploader.setText(mGalleryInfo.uploader);
}
mDetailButtons.setVisibility(View.VISIBLE);
mWarning.setVisibility(View.VISIBLE);
mDetailActions.setVisibility(View.VISIBLE);
mDividerAM.setVisibility(View.VISIBLE);
mDetailMore.setVisibility(View.VISIBLE);
mDividerMR.setVisibility(View.VISIBLE);
mDetailRate.setVisibility(View.VISIBLE);
mCategory.setText(Ui.getCategoryText(mGalleryInfo.category));
mCategoryDrawable.setColor(Ui.getCategoryColor(mGalleryInfo.category));
if (mGalleryInfo instanceof GalleryDetail) {
GalleryDetail galleryDetail = (GalleryDetail)mGalleryInfo;
// TODO set language
((TextView)mDetailMore.findViewById(R.id.language)).setText("语言: " + galleryDetail.language); // TODO
((TextView)mDetailMore.findViewById(R.id.posted)).setText(galleryDetail.posted);
((TextView)mDetailMore.findViewById(R.id.pages)).setText("页面: " + String.valueOf(galleryDetail.pages));
((TextView)mDetailMore.findViewById(R.id.size)).setText("大小: " + galleryDetail.size);
StringBuilder sb = new StringBuilder();
sb.append("gid: ").append(galleryDetail.gid).append("\n\n")
.append("token: ").append(galleryDetail.token).append("\n\n")
.append("title: ").append(galleryDetail.title).append("\n\n")
.append("title_jpn: ").append(galleryDetail.title_jpn).append("\n\n")
.append("thumb: ").append(galleryDetail.thumb).append("\n\n")
.append("category: ").append(Ui.getCategoryText(galleryDetail.category)).append("\n\n")
.append("uploader: ").append(galleryDetail.uploader).append("\n\n")
.append("posted: ").append(galleryDetail.posted).append("\n\n")
.append("pages: ").append(galleryDetail.pages).append("\n\n")
.append("size: ").append(galleryDetail.size).append("\n\n")
.append("resized: ").append(galleryDetail.resized).append("\n\n")
.append("parent: ").append(galleryDetail.parent).append("\n\n")
.append("visible: ").append(galleryDetail.visible).append("\n\n")
.append("language: ").append(galleryDetail.language).append("\n\n")
.append("people: ").append(galleryDetail.people).append("\n\n")
.append("rating: ").append(galleryDetail.rating);
((TextView)mMoreDetailScroll.findViewById(R.id.more_detail)).setText(sb.toString());
mRatingText.setCurrentText(getAllRatingText(galleryDetail.rating, galleryDetail.people));
mRating.setRating(galleryDetail.rating);
mRating.setEnableRate(false);
} else if (mGalleryInfo instanceof GalleryDetail) {
} else if (mGalleryInfo instanceof ApiGalleryDetail) {
}
}
@Override
public void onBackPressed() {
if (!mGdList.isEmpty()) {
mGalleryDetail = mGdList.pop();
loadDetail();
} else {
finish();
if (mRunningAnimateNum != 0 || mWindowsAnimate.isRunningAnimate())
return;
if (mDetailScroll.getVisibility() == View.VISIBLE) {
super.onBackPressed();
} else if (mMoreDetailScroll.getVisibility() == View.VISIBLE) {
mDetailScroll.setVisibility(View.VISIBLE);
ValueAnimator animation = ValueAnimator.ofInt(mMoreDetailScroll.getLeft(), mMoreDetailScroll.getRight());
animation.setDuration(Constants.ANIMATE_TIME);
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int left = (Integer)animation.getAnimatedValue();
mMoreDetailScroll.setLeft(left);
}
});
animation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
@Override
public void onAnimationEnd(Animator animation) {
mMoreDetailScroll.setVisibility(View.GONE);
mRunningAnimateNum--;
}
@Override
public void onAnimationCancel(Animator animation) {}
});
animation.setInterpolator(new AccelerateInterpolator());
animation.start();
mRunningAnimateNum++;
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.viewpager);
public void onClick(View v) {
if (mRunningAnimateNum != 0 || mWindowsAnimate.isRunningAnimate())
return;
mGdList = new Stack<GalleryDetail>();
mGalleryDetail = handleIntent(getIntent());
final ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Set random color
int color = Config.getRandomThemeColor() ? Theme.getRandomDarkColor() : Config.getThemeColor();
color = color & 0x00ffffff | 0xdd000000;
Drawable drawable = new ColorDrawable(color);
actionBar.setBackgroundDrawable(drawable);
Ui.translucent(this, color);
SectionsPagerAdapter adapter =
new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setAdapter(adapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
if (v == mDownloadButton) {
} else if (v == mReadButton) {
//mData.addRead(mGalleryInfo);
if (mGalleryInfo instanceof GalleryDetail) {
GalleryDetail galleryDetail = (GalleryDetail)mGalleryInfo;
Intent intent = new Intent(this,
GalleryActivity.class);
intent.putExtra("url", galleryDetail.firstPage);
intent.putExtra("gid", mGalleryInfo.gid);
intent.putExtra("title", mGalleryInfo.title);
intent.putExtra("firstPage", 0);
intent.putExtra("pageSum", galleryDetail.pages);
startActivity(intent);
} else {
// TODO
}
});
for (int i = 0; i < adapter.getCount(); i++) {
actionBar.addTab(
actionBar.newTab()
.setText(adapter.getPageTitle(i))
.setTabListener(this));
}
// Download service
Intent it = new Intent(GalleryDetailActivity.this, DownloadService.class);
bindService(it, mServiceConn, BIND_AUTO_CREATE);
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
mViewPager.setCurrentItem(tab.getPosition());
mTabIndex = tab.getPosition();
invalidateOptionsMenu();
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.detail, menu);
return true;
}
public List<Comment> getComments() {
if (mDetailFragment == null)
return null;
else
return mDetailFragment.getComments();
}
public void setComments(List<Comment> comments) {
if (mCommentsFragment != null)
mCommentsFragment.setComments(comments);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.action_favourite:
int defaultFavorite = Config.getDefaultFavorite();
switch (defaultFavorite) {
case -2:
Favorite.getAddToFavoriteDialog(this, mGalleryDetail).show();
break;
case -1:
((AppContext)getApplication()).getData().addLocalFavourite(mGalleryDetail);
new SuperToast(this).setMessage(R.string.toast_add_favourite).show();
break;
default:
((AppContext)getApplication()).getEhClient().addToFavorite(mGalleryDetail.gid,
mGalleryDetail.token, defaultFavorite, null, new EhClient.OnAddToFavoriteListener() {
} else if (v == mFavorite) {
Favorite.addToFavorite(this, mGalleryInfo);
} else if (v == mRate) {
if (isCheckmark) {
int rating = (int)(mRating.getRating() * 2 + 0.5);
if (rating <= 0 || rating > 10) {
new SuperToast(R.string.invalid_rating, SuperToast.ERROR).show();
return;
}
mClient.rate(mGalleryInfo.gid, mGalleryInfo.token, rating, new EhClient.OnRateListener() {
@Override
public void onSuccess() {
new SuperToast(GalleryDetailActivity.this).setMessage(R.string.toast_add_favourite).show();
public void onSuccess(float ratingAvg, int ratingCnt) {
mGalleryInfo.rating = ratingAvg;
// TODO mGalleryInfo.people = ratingCnt;
mRatingText.setText(getAllRatingText(mGalleryInfo.rating, ratingCnt));
mRating.setRating(mGalleryInfo.rating);
}
@Override
public void onFailure(String eMsg) {
new SuperToast(GalleryDetailActivity.this).setMessage(R.string.failed_to_add).show();
mRatingText.setText("评分失败"); // TODO
new SuperToast(eMsg, SuperToast.WARNING).show();
}
});
}
return true;
case R.id.action_download:
if (mGalleryDetail.language == null) {
new SuperToast(this).setMessage(R.string.wait).show();
mRatingText.setText("感谢评分"); // TODO
mRating.setEnableRate(false);
} else {
Intent it = new Intent(GalleryDetailActivity.this, DownloadService.class);
startService(it);
mServiceConn.getService().add(String.valueOf(mGalleryDetail.gid), mGalleryDetail.thumb,
EhClient.getDetailUrl(mGalleryDetail.gid, mGalleryDetail.token, 0, Config.getMode()),
mGalleryDetail.title);
new SuperToast(this, R.string.toast_add_download).show();
mRatingText.setText("请理智评分"); // TODO
mRating.setEnableRate(true);
}
return true;
case R.id.action_info:
if (mGalleryDetail.language == null) {
new SuperToast(this, R.string.wait).show();
} else {
new DialogBuilder(this).setTitle(R.string.info)
.setLongMessage(
"gid : " + mGalleryDetail.gid + "\n\n" +
"token : " + mGalleryDetail.token + "\n\n" +
"title : " + mGalleryDetail.title + "\n\n" +
"title_jpn : " + mGalleryDetail.title_jpn + "\n\n" +
"thumb : " + mGalleryDetail.thumb + "\n\n" +
"category : " + EhClient.getType(mGalleryDetail.category) + "\n\n" +
"uploader : " + mGalleryDetail.uploader + "\n\n" +
"posted : " + mGalleryDetail.posted + "\n\n" +
"pages : " + mGalleryDetail.pages + "\n\n" +
"size : " + mGalleryDetail.size + "\n\n" +
"resized : " + mGalleryDetail.resized + "\n\n" +
"parent : " + mGalleryDetail.parent + "\n\n" +
"visible : " + mGalleryDetail.visible + "\n\n" +
"language : " + mGalleryDetail.language + "\n\n" +
"people : " + mGalleryDetail.people + "\n\n" +
"rating : " + mGalleryDetail.rating)
.setMessageSelectable()
.setSimpleNegativeButton().create().show();
}
return true;
case R.id.action_reply:
final EditText et = new EditText(this);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
int x = Ui.dp2pix(8);
lp.leftMargin = x;
lp.rightMargin = x;
lp.topMargin = x;
lp.bottomMargin = x;
new DialogBuilder(this).setView(et, lp)
.setTitle(R.string.comment)
.setPositiveButton(R.string.send, new View.OnClickListener() {
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
String comment = et.getText().toString();
((AppContext)getApplication()).getEhClient()
.comment(EhClient.getDetailUrl(mGalleryDetail.gid, mGalleryDetail.token, 0, Config.getMode()),
comment, new EhClient.OnCommentListener() {
@Override
public void onSuccess(List<Comment> comments) {
setComments(comments);
mGalleryDetail.comments = comments;
}
@Override
public void onFailure(String eMsg) {
new SuperToast(GalleryDetailActivity.this, eMsg)
.setIcon(R.drawable.ic_warning).show();
}
});
// Animate to change
ValueAnimator animation = ValueAnimator.ofFloat(0.0f, 90.0f, 180.0f);
animation.setDuration(Constants.ANIMATE_TIME);
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float rotationY = (Float)animation.getAnimatedValue();
if (rotationY > 90) {
rotationY = 180 - rotationY;
if (!isSetDrawable) {
mRate.setCompoundDrawables(null, isCheckmark ? mRateDrawable : mCheckmarkDrawable, null, null);
mRate.setText(isCheckmark ? R.string.rate : android.R.string.ok);
isSetDrawable = true;
isCheckmark = !isCheckmark;
}
}).setNegativeButton(android.R.string.cancel,
new View.OnClickListener() {
@Override
public void onClick(View v) {
((AlertButton)v).dialog.dismiss();
}
}).create().show();
return true;
default:
return super.onOptionsItemSelected(item);
}
mRate.setRotationY(rotationY);
}
});
animation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
@Override
public void onAnimationEnd(Animator animation) {
mRunningAnimateNum--;
isSetDrawable = false;
}
@Override
public void onAnimationCancel(Animator animation) {}
});
animation.start();
mRunningAnimateNum++;
}
}
@Override
public boolean onPrepareOptionsMenu (Menu menu) {
MenuItem info = menu.findItem(R.id.action_info);
MenuItem reply = menu.findItem(R.id.action_reply);
if (mTabIndex == 1) {
info.setVisible(false);
reply.setVisible(true);
} else {
info.setVisible(true);
reply.setVisible(false);
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
mDetailScroll.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
mMoreDetailScroll.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
}
@Override
@SuppressLint("ClickableViewAccessibility")
public boolean onTouch(View v, MotionEvent event) {
if (v == mDetailMore) {
if (event.getAction() == MotionEvent.ACTION_UP &&
System.nanoTime() / 1000000 - event.getDownTime() < 100) {
mWindowsAnimate.addCircleTransitions(mDetailMore, (int)event.getX(),
(int)event.getY(), mResources.getColor(R.color.background_light),
new WindowsAnimate.OnAnimationEndListener() {
@Override
public void onAnimationEnd() {
mDetailScroll.setVisibility(View.GONE);
mMoreDetailScroll.setVisibility(View.VISIBLE);
mMoreDetailScroll.scrollTo(0, 0);
AlphaAnimation aa = new AlphaAnimation(0.0f,1.0f);
aa.setDuration(Constants.ANIMATE_TIME);
mMoreDetailScroll.startAnimation(aa);
}
});
}
}
return true;
}
private class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
@Override
public void onUserRate(float rating) {
mRatingText.setText(getRatingText(rating));
}
@Override
public View makeView() {
TextView tv = new TextView(this);
tv.setGravity(Gravity.CENTER);
return tv;
}
private class GDetailGetListener
implements EhClient.OnGetGDetailListener {
@Override
public void onSuccess(GalleryDetail md) {
doLayout();
}
@Override
public Fragment getItem(int i) {
if (i == 0) {
return mDetailFragment = new DetailSectionFragment();
}
else if (i == 1) {
return mCommentsFragment = new CommentsSectionFragment();
}
else
return null;
}
@Override
public int getCount() {
return 2;
}
@Override
public CharSequence getPageTitle(int position) {
if (position == 0)
return getString(R.string.detail);
else
return getString(R.string.comment);
}
public void onFailure(String eMsg) {
// TODO
new SuperToast(eMsg, SuperToast.ERROR).show();
}
}
}
@@ -18,41 +18,39 @@ package com.hippo.ehviewer.ui;
import java.io.File;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.gallery.GalleryView;
import com.hippo.ehviewer.gallery.data.DownloadImageSet;
import com.hippo.ehviewer.gallery.ui.GLRootView;
import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Util;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.SuperToast;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
public class GalleryDownloadActivity extends AbstractActivity {
private static final String TAG = "MangaDownloadActivity";
public static final String KEY_TITLE = "title";
public static final String KEY_GID= "gid";
public static final String KEY_SIZE = "size";
public static final String KEY_END_INDEX = "endIndex";
private RelativeLayout mainView;
private DownloadImageSet mDownloadImageSet;
@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gl_root_group);
getActionBar().hide();
// For API < 16 Fullscreen
if (Build.VERSION.SDK_INT < 19) {
@@ -70,34 +68,34 @@ public class GalleryDownloadActivity extends AbstractActivity {
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
Intent intent = getIntent();
String title = intent.getStringExtra(KEY_TITLE);
int gid = intent.getIntExtra(KEY_GID, 0);
int size = intent.getIntExtra(KEY_SIZE, 1);
int endIndex = intent.getIntExtra(KEY_END_INDEX, 0);
GLRootView glrv= (GLRootView)findViewById(R.id.gl_root_view);
File folder = new File(Config.getDownloadPath(), Util.rightFileName(title));
File folder = new File(Config.getDownloadPath(), Utils.rightFileName(title));
folder.mkdirs();
mDownloadImageSet = new DownloadImageSet(this, gid, folder, size, 0, endIndex, null);
GalleryView isv = new GalleryView(getApplicationContext(), mDownloadImageSet, 0);
isv.setOnEdgeListener(new GalleryView.OnEdgeListener() {
@Override
public void onLastPageEdge() {
new SuperToast(GalleryDownloadActivity.this, R.string.last_page).show();
new SuperToast(R.string.last_page).show();
}
@Override
public void onFirstPageEdge() {
new SuperToast(GalleryDownloadActivity.this, R.string.first_page).show();
new SuperToast(R.string.first_page).show();
}
});
glrv.setContentPane(isv);
// Avoid error when use Movie
//glrv.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
@SuppressLint("NewApi")
@Override
public void onWindowFocusChanged(boolean hasFocus) {
@@ -111,7 +109,7 @@ public class GalleryDownloadActivity extends AbstractActivity {
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}
}
@Override
public void onDestroy() {
super.onDestroy();
@@ -83,13 +83,12 @@ import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Favorite;
import com.hippo.ehviewer.util.Theme;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.CategoryTable;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.FswView;
import com.hippo.ehviewer.widget.LoadImageView;
import com.hippo.ehviewer.widget.OnFitSystemWindowsListener;
import com.hippo.ehviewer.widget.PrefixEditText;
import com.hippo.ehviewer.widget.RatingView;
import com.hippo.ehviewer.widget.SuperDialogUtil;
@@ -217,7 +216,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
@Override
public void onFailure(String eMsg) {
setUserPanel();
new SuperToast(GalleryListActivity.this, eMsg).setIcon(R.drawable.ic_warning).show();
new SuperToast(eMsg, SuperToast.ERROR).show();
if (!GalleryListActivity.this.isFinishing())
loginDialog.show();
}
@@ -231,11 +230,11 @@ public class GalleryListActivity extends AbstractGalleryActivity
setUserPanel();
break;
case EhClient.NO_AVATAR:
new SuperToast(GalleryListActivity.this, "无头像").show(); // TODO
new SuperToast("无头像").show(); // TODO
break;
case EhClient.GET_AVATAR_ERROR:
default:
new SuperToast(GalleryListActivity.this, "获取头像失败", SuperToast.ERROR).show(); // TODO
new SuperToast("获取头像失败", SuperToast.ERROR).show(); // TODO
break;
}
}
@@ -500,10 +499,10 @@ public class GalleryListActivity extends AbstractGalleryActivity
String filePath = (String)mSearchImageText.getText();
File file = new File(filePath);
if (!file.exists()) {
new SuperToast(this, "图片不存在", SuperToast.ERROR).show();
new SuperToast("图片不存在", SuperToast.ERROR).show();
} else {
if (!file.canRead()) {
new SuperToast(this, "图片不可读", SuperToast.ERROR).show();
new SuperToast("图片不可读", SuperToast.ERROR).show();
} else {
CheckBox similar = (CheckBox)view.findViewById(R.id.checkboxSimilar);
@@ -532,28 +531,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
switch (position) {
case 0: // Add favourite item
gi = getGalleryInfo(longClickItemIndex);
int defaultFavorite = Config.getDefaultFavorite();
switch (defaultFavorite) {
case -2:
Favorite.getAddToFavoriteDialog(GalleryListActivity.this, gi).show();
break;
case -1:
((AppContext)getApplication()).getData().addLocalFavourite(gi);
new SuperToast(GalleryListActivity.this).setMessage(R.string.toast_add_favourite).show();
break;
default:
((AppContext)getApplication()).getEhClient().addToFavorite(gi.gid,
gi.token, defaultFavorite, null, new EhClient.OnAddToFavoriteListener() {
@Override
public void onSuccess() {
new SuperToast(GalleryListActivity.this).setMessage(R.string.toast_add_favourite).show();
}
@Override
public void onFailure(String eMsg) {
new SuperToast(GalleryListActivity.this).setMessage(R.string.failed_to_add).show();
}
});
}
Favorite.addToFavorite(GalleryListActivity.this, gi);
break;
case 1:
gi = getGalleryInfo(longClickItemIndex);
@@ -561,7 +539,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
startService(it);
mServiceConn.getService().add(String.valueOf(gi.gid), gi.thumb,
mClient.getDetailUrl(gi.gid, gi.token), gi.title);
new SuperToast(GalleryListActivity.this, R.string.toast_add_download).show();
new SuperToast(R.string.toast_add_download).show();
break;
default:
break;
@@ -599,8 +577,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
if (targetPage < 0 || targetPage >= getPageNum())
throw new Exception();
} catch(Exception e) {
new SuperToast(GalleryListActivity.this, R.string.toast_invalid_page,
SuperToast.ERROR).show();
new SuperToast(R.string.toast_invalid_page, SuperToast.ERROR).show();
return;
}
@@ -641,9 +618,9 @@ public class GalleryListActivity extends AbstractGalleryActivity
public void onClick(View v) {
String key = et.getText().toString();
if (key.length() == 0)
new SuperToast(GalleryListActivity.this, R.string.tag_name_empty).setIcon(R.drawable.ic_warning).show();
new SuperToast(R.string.tag_name_empty, SuperToast.WARNING).show();
else if (listMenuTag.contains(key) && !key.equals(oldStr))
new SuperToast(GalleryListActivity.this, R.string.tag_name_empty).setIcon(R.drawable.ic_warning).show();
new SuperToast(R.string.tag_name_empty, SuperToast.WARNING).show();
else {
((AlertButton)v).dialog.dismiss();
if (listener != null) {
@@ -678,11 +655,9 @@ public class GalleryListActivity extends AbstractGalleryActivity
if (searchNormal.getVisibility() == View.GONE) {
searchNormal.setVisibility(View.VISIBLE);
searchTag.setVisibility(View.GONE);
new SuperToast(GalleryListActivity.this, R.string.toast_normal_mode).show();
} else {
searchNormal.setVisibility(View.GONE);
searchTag.setVisibility(View.VISIBLE);
new SuperToast(GalleryListActivity.this, R.string.toast_tag_mode).show();
}
}
}).setPositiveButton(android.R.string.ok, new View.OnClickListener() {
@@ -913,8 +888,8 @@ public class GalleryListActivity extends AbstractGalleryActivity
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mData = mAppContext.getData();
mClient = mAppContext.getEhClient();
mData = Data.getInstance();
mClient = EhClient.getInstance();
mResources =getResources();
handleIntent(getIntent());
@@ -1154,7 +1129,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
});
FswView alignment = (FswView)findViewById(R.id.alignment);
alignment.addOnFitSystemWindowsListener(new OnFitSystemWindowsListener() {
alignment.addOnFitSystemWindowsListener(new FswView.OnFitSystemWindowsListener() {
@Override
public void onfitSystemWindows(int paddingLeft, int paddingTop,
int paddingRight, int paddingBottom) {
@@ -1345,7 +1320,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
public void onBackPressed() {
if (System.currentTimeMillis() - curBackTime > BACK_PRESSED_INTERVAL) {
curBackTime = System.currentTimeMillis();
new SuperToast(GalleryListActivity.this, R.string.exit_tip).show();
new SuperToast(R.string.exit_tip).show();
} else
finish();
}
@@ -1418,7 +1393,7 @@ public class GalleryListActivity extends AbstractGalleryActivity
@Override
public void onSuccess(String version, long size,
final String url, final String fileName, String info) {
String sizeStr = Util.sizeToString(size);
String sizeStr = Utils.sizeToString(size);
AlertDialog dialog = SuperDialogUtil.createUpdateDialog(GalleryListActivity.this,
version, sizeStr, info,
new View.OnClickListener() {
@@ -1540,9 +1515,8 @@ public class GalleryListActivity extends AbstractGalleryActivity
listener.onSuccess(mAdapter, taskStamp, gis, gis.size() == 0 ? 0 : 1);
// Show update time
if (timeStamp != -1 && Config.getShowPopularUpdateTime())
new SuperToast(GalleryListActivity.this,
String.format(getString(R.string.popular_update_time),
mAppContext.getDateFormat().format(timeStamp))).show();
new SuperToast(String.format(getString(R.string.popular_update_time),
AppContext.sFormatter.format(timeStamp))).show();
}
@Override
public void onFailure(String eMsg) {
@@ -61,7 +61,7 @@ import com.hippo.ehviewer.util.Config;
import com.hippo.ehviewer.util.Favorite;
import com.hippo.ehviewer.util.Theme;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
import com.hippo.ehviewer.widget.AlertButton;
import com.hippo.ehviewer.widget.CategoryTable;
import com.hippo.ehviewer.widget.DialogBuilder;
@@ -291,7 +291,7 @@ public class SettingsActivity extends AbstractPreferenceActivity {
Config.screenOriPre2Value(Integer.parseInt((String) newValue)));
} else if (KEY_RANDOM_THEME_COLOR.equals(key)) {
new SuperToast(mActivity, R.string.restart_to_take_effect).show();
new SuperToast(R.string.restart_to_take_effect).show();
mThemeColor.setEnabled(!(Boolean)newValue);
}
@@ -443,7 +443,7 @@ public class SettingsActivity extends AbstractPreferenceActivity {
private static void setExculdeTagGroup(TableLayout tl, int value) {
for (int i = 0; i < EXCULDE_TAG_GROUP_RESID.length; i++) {
CheckBox cb = (CheckBox)tl.findViewById(EXCULDE_TAG_GROUP_RESID[i]);
cb.setChecked(Util.int2boolean(value & EXCULDE_TAG_GROUP_ID[i]));
cb.setChecked(Utils.int2boolean(value & EXCULDE_TAG_GROUP_ID[i]));
}
}
@@ -647,8 +647,7 @@ public class SettingsActivity extends AbstractPreferenceActivity {
@Override
public void onClick(View v) {
if (!fileExplorerView.canWrite())
new SuperToast(mActivity).setIcon(R.drawable.ic_warning)
.setMessage(R.string.cur_dir_not_writable).show();
new SuperToast(R.string.cur_dir_not_writable, SuperToast.WARNING).show();
else {
String downloadPath = fileExplorerView.getCurPath();
@@ -756,14 +755,14 @@ public class SettingsActivity extends AbstractPreferenceActivity {
InputStream is = mActivity.getResources()
.openRawResource(R.raw.change_log);
new DialogBuilder(mActivity).setTitle(R.string.changelog)
.setLongMessage(Util.InputStream2String(is, "utf-8"))
.setLongMessage(Utils.InputStream2String(is, "utf-8"))
.setSimpleNegativeButton().create().show();
} else if (KEY_THANKS.equals(key)) {
InputStream is = mActivity.getResources()
.openRawResource(R.raw.thanks);
final WebView webView = new WebView(mActivity);
webView.loadData(Util.InputStream2String(is, "utf-8"), "text/html; charset=UTF-8", null);
webView.loadData(Utils.InputStream2String(is, "utf-8"), "text/html; charset=UTF-8", null);
new DialogBuilder(mActivity).setTitle(R.string.thanks)
.setView(webView, false).setSimpleNegativeButton()
.create().show();
@@ -787,7 +786,7 @@ public class SettingsActivity extends AbstractPreferenceActivity {
public void onSuccess(String version, long size,
final String url, final String fileName, String info) {
mCheckUpdate.setSummary(R.string.found_update);
String sizeStr = Util.sizeToString(size);
String sizeStr = Utils.sizeToString(size);
AlertDialog dialog = SuperDialogUtil.createUpdateDialog(
mActivity, version, sizeStr, info,
new View.OnClickListener() {
+1 -1
View File
@@ -226,7 +226,7 @@ public class Config {
}
public static void setUpdateDate() {
setUpdateDate(Util.getDate());
setUpdateDate(Utils.getDate());
}
public static void setUpdateDate(int date) {
+12 -1
View File
@@ -16,7 +16,18 @@
package com.hippo.ehviewer.util;
public class Constants {
public final class Constants {
public static final int FALSE = 0;
public static final int TRUE = 1;
public static final int ANIMATE_TIME = 300;
public static final int HTTP_TEMP_REDIRECT = 307;
public static String defaultUserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36";
public static String userAgent = System.getProperty("http.agent", defaultUserAgent);
public static final int DEFAULT_TIMEOUT = 10 * 1000;
public static final int MAX_REDIRECTS = 5;
public static final int BUFFER_SIZE = 4096;
}
+18 -19
View File
@@ -34,35 +34,34 @@ import android.os.Build;
import android.os.Environment;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.util.Log;
public class Crash {
private static final String TAG = "Crash";
private static Context mContext;
private static String externalCrashFilePath = "/EhViewer/crash";
private static String internalCrashFilePath = "/crash";
private static final String NEW_CRAHS = "new_crash";
private static final String LAST_CRASH_POSITION = "last_crash_position";
private static final String LAST_CRASH_NAME = "last_crash_name";
private static boolean mInit = false;
/**
* Init Crash
*
*
* @param context Application context
*/
public static void init(Context context) {
if (mInit)
return;
mInit = true;
mContext = context;
}
/**
* Is init
* @return True if init
@@ -70,16 +69,16 @@ public class Crash {
public static boolean isInit() {
return mInit;
}
/**
* Save throwable infomation to file
*
*
* @param ex The throwable to store
*/
public static void saveCrashInfo2File(Throwable ex) {
StringBuffer sb = new StringBuffer();
collectDeviceInfo(sb);
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
@@ -95,7 +94,7 @@ public class Crash {
sb.append(result);
try {
long timestamp = System.currentTimeMillis();
String time = ((AppContext)mContext).getDateFormat().format(new Date());
String time = AppContext.sFormatter.format(new Date());
String fileName = "crash-" + time + "-" + timestamp + ".log";
String path = null;
boolean position = false;
@@ -125,7 +124,7 @@ public class Crash {
Log.e(TAG, "An error occured while writing crash file...", e);
}
}
private static void collectDeviceInfo(StringBuffer sb) {
try {
PackageManager pm = mContext.getPackageManager();
@@ -167,22 +166,22 @@ public class Crash {
sb.append("SDK=" + Build.VERSION.SDK_INT + "\n");
sb.append("\n");
}
/**
* Check is there last crash
*
*
* @return Return the crash String or null if there is no
*/
public static String getLastCrash() {
SharedPreferences configPre = mContext.getSharedPreferences("config", 0);
if (!configPre.getBoolean(NEW_CRAHS, false))
return null;
boolean position = configPre.getBoolean(LAST_CRASH_POSITION, false);
String lastCrashName;
if ((lastCrashName = configPre.getString(LAST_CRASH_NAME, null)) == null)
return null;
File lastCrashFile;
if (position) {
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
@@ -194,7 +193,7 @@ public class Crash {
}
if (!lastCrashFile.isFile())
return null;
try {
byte[] buffer = new byte[(int) lastCrashFile.length()];
DataInputStream din = new DataInputStream(new FileInputStream(lastCrashFile));
+8 -8
View File
@@ -65,7 +65,7 @@ public class Download {
}
private static void getDownloadInfo() {
String[] allOrder = Util.getStrings(mDownloadInfoPre, LIST_ORDER);
String[] allOrder = Utils.getStrings(mDownloadInfoPre, LIST_ORDER);
if (allOrder == null)
return;
@@ -87,7 +87,7 @@ public class Download {
mDownloadInfos.add(di);
}
if (errorFlag)
Util.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
Utils.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
}
/**
@@ -102,7 +102,7 @@ public class Download {
if (mListOrder.indexOf(key) == -1) {
mListOrder.add(key);
mDownloadInfos.add(di);
Util.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
Utils.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
mDownloadInfoPre.edit().putString(key, encode(di)).apply();
return true;
} else
@@ -127,7 +127,7 @@ public class Download {
String temp1 = mListOrder.get(indexOne);
mListOrder.set(indexOne, mListOrder.get(indexTwo));
mListOrder.set(indexTwo, temp1);
Util.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
Utils.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
DownloadInfo temp2 = mDownloadInfos.get(indexOne);
mDownloadInfos.set(indexOne, mDownloadInfos.get(indexTwo));
@@ -151,7 +151,7 @@ public class Download {
mListOrder.remove(index);
mDownloadInfos.remove(index);
mDownloadInfoPre.edit().remove(key).apply();
Util.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
Utils.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
return true;
} else
return false;
@@ -167,7 +167,7 @@ public class Download {
mDownloadInfos.remove(index);
String key = mListOrder.remove(index);
mDownloadInfoPre.edit().remove(key).apply();
Util.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
Utils.putStrings(mDownloadInfoPre, LIST_ORDER, mListOrder);
return true;
}
@@ -221,11 +221,11 @@ public class Download {
e.printStackTrace();
}
}
return Util.byteArrayToHexString(os.toByteArray());
return Utils.byteArrayToHexString(os.toByteArray());
}
protected static DownloadInfo decode(String strDi) {
byte[] bytes = Util.hexStringToByteArray(strDi);
byte[] bytes = Utils.hexStringToByteArray(strDi);
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
DownloadInfo di = null;
try {
+45 -23
View File
@@ -16,19 +16,9 @@
package com.hippo.ehviewer.util;
import com.hippo.ehviewer.Analytics;
import com.hippo.ehviewer.AppContext;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.ui.GalleryDetailActivity;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.SuperToast;
import android.app.AlertDialog;
import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -36,26 +26,58 @@ import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.data.Data;
import com.hippo.ehviewer.data.GalleryInfo;
import com.hippo.ehviewer.ehclient.EhClient;
import com.hippo.ehviewer.widget.DialogBuilder;
import com.hippo.ehviewer.widget.SuperToast;
public class Favorite {
private static Context mContext;
private static Resources mResources;
private static AlertDialog lastAddToFavoriteDialog;
public static String[] FAVORITE_TITLES;
public static void init(Context context) {
mContext = context;
mResources = mContext.getResources();
FAVORITE_TITLES = new String[EhClient.FAVORITE_SLOT_NUM + 1];
FAVORITE_TITLES[0] = mResources.getString(R.string.local_favorite);
for (int i = 1; i < EhClient.FAVORITE_SLOT_NUM + 1; i++) {
FAVORITE_TITLES[i] = mResources.getString(R.string.favourite) + " "+ (i - 1);
}
}
public static void addToFavorite(final Context context, GalleryInfo gi) {
int defaultFavorite = Config.getDefaultFavorite();
switch (defaultFavorite) {
case -2:
Favorite.getAddToFavoriteDialog(context, gi).show();
break;
case -1:
Data.getInstance().addLocalFavourite(gi);
new SuperToast(R.string.toast_add_favourite).show();
break;
default:
EhClient.getInstance().addToFavorite(gi.gid,
gi.token, defaultFavorite, null, new EhClient.OnAddToFavoriteListener() {
@Override
public void onSuccess() {
new SuperToast(R.string.toast_add_favourite).show();
}
@Override
public void onFailure(String eMsg) {
new SuperToast(R.string.failed_to_add).show();
}
});
}
}
public static AlertDialog getAddToFavoriteDialog(final Context context, final GalleryInfo gi) {
DialogBuilder db = new DialogBuilder(context).setView(R.layout.add_to_favorite, false);
db.setTitle(R.string.where_to_add);
@@ -71,25 +93,25 @@ public class Favorite {
int position, long id) {
lastAddToFavoriteDialog.dismiss();
lastAddToFavoriteDialog = null;
if (cb.isChecked())
Config.setDefaultFavorite(position - 1);
switch (position) {
case 0:
((AppContext)mContext).getData().addLocalFavourite(gi);
new SuperToast(context).setMessage(R.string.toast_add_favourite).show();
Data.getInstance().addLocalFavourite(gi);
new SuperToast(R.string.toast_add_favourite).show();
break;
default:
((AppContext)mContext).getEhClient().addToFavorite(gi.gid,
EhClient.getInstance().addToFavorite(gi.gid,
gi.token, position - 1, null, new EhClient.OnAddToFavoriteListener() {
@Override
public void onSuccess() {
new SuperToast(context).setMessage(R.string.toast_add_favourite).show();
new SuperToast(R.string.toast_add_favourite).show();
}
@Override
public void onFailure(String eMsg) {
new SuperToast(context).setMessage(R.string.failed_to_add).show();
new SuperToast(R.string.failed_to_add).show();
}
});
}
+179
View File
@@ -0,0 +1,179 @@
/*
* 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.util;
import java.util.Random;
public final class MathUtils {
private static final Random sRandom = new Random();
private static final float DEG_TO_RAD = 0.01745329F;
private static final float RAD_TO_DEG = 57.295784F;
public static float abs(float v) {
return v > 0.0F ? v : -v;
}
public static int constrain(int amount, int low, int high) {
return amount > high ? high : amount < low ? low : amount;
}
public static long constrain(long amount, long low, long high) {
return amount > high ? high : amount < low ? low : amount;
}
public static float constrain(float amount, float low, float high) {
return amount > high ? high : amount < low ? low : amount;
}
public static float log(float a) {
return (float) Math.log(a);
}
public static float exp(float a) {
return (float) Math.exp(a);
}
public static float pow(float a, float b) {
return (float) Math.pow(a, b);
}
public static float max(float a, float b) {
return a > b ? a : b;
}
public static float max(int a, int b) {
return a > b ? a : b;
}
public static float max(float a, float b, float c) {
return b > c ? b : a > b ? c : a > c ? a : c;
}
public static float max(int a, int b, int c) {
return a > b ? a > c ? a : c : b > c ? b : c;
}
public static float min(float a, float b) {
return a < b ? a : b;
}
public static float min(int a, int b) {
return a < b ? a : b;
}
public static float min(float a, float b, float c) {
return b < c ? b : a < b ? c : a < c ? a : c;
}
public static float min(int a, int b, int c) {
return a < b ? a < c ? a : c : b < c ? b : c;
}
public static float dist(float x1, float y1, float x2, float y2) {
float x = x2 - x1;
float y = y2 - y1;
return (float) Math.sqrt(x * x + y * y);
}
public static float dist(float x1, float y1, float z1, float x2, float y2,
float z2) {
float x = x2 - x1;
float y = y2 - y1;
float z = z2 - z1;
return (float) Math.sqrt(x * x + y * y + z * z);
}
public static float mag(float a, float b) {
return (float) Math.sqrt(a * a + b * b);
}
public static float mag(float a, float b, float c) {
return (float) Math.sqrt(a * a + b * b + c * c);
}
public static float sq(float v) {
return v * v;
}
public static float radians(float degrees) {
return degrees * 0.01745329F;
}
public static float degrees(float radians) {
return radians * 57.295784F;
}
public static float acos(float value) {
return (float) Math.acos(value);
}
public static float asin(float value) {
return (float) Math.asin(value);
}
public static float atan(float value) {
return (float) Math.atan(value);
}
public static float atan2(float a, float b) {
return (float) Math.atan2(a, b);
}
public static float tan(float angle) {
return (float) Math.tan(angle);
}
public static float lerp(float start, float stop, float amount) {
return start + (stop - start) * amount;
}
public static float norm(float start, float stop, float value) {
return (value - start) / (stop - start);
}
public static float map(float minStart, float minStop, float maxStart,
float maxStop, float value) {
return maxStart + (maxStart - maxStop)
* ((value - minStart) / (minStop - minStart));
}
public static int random(int howbig) {
return (int) (sRandom.nextFloat() * howbig);
}
public static int random(int howsmall, int howbig) {
if (howsmall >= howbig)
return howsmall;
return (int) (sRandom.nextFloat() * (howbig - howsmall) + howsmall);
}
public static float random(float howbig) {
return sRandom.nextFloat() * howbig;
}
public static float random(float howsmall, float howbig) {
if (howsmall >= howbig)
return howsmall;
return sRandom.nextFloat() * (howbig - howsmall) + howsmall;
}
public static void randomSeed(long seed) {
sRandom.setSeed(seed);
}
}
+14 -28
View File
@@ -31,33 +31,19 @@ public final class Theme {
public static final ColorDrawable GREY_DRAWABLE =
new ColorDrawable(0xffaaaaaa);
/**
* Colors from colors_material.xml
*
* material_red_300, material_red_500, material_red_700,
* material_red_A200, material_blue_500, material_blue_700,
* material_blue_A200, material_blue_A400, material_teal_700,
* material_green_500, material_green_700, material_lime_700,
* material_yellow_500, material_yellow_700, material_orange_500,
* material_orange_700, material_orange_A400, material_deep_orange_500,
* material_deep_orange_700, material_deep_orange_A200,
* material_deep_orange_A400, material_grey_600, material_grey_700,
* material_blue_grey_500, material_blue_grey_600,
* material_blue_grey_700, material_blue_grey_800,
* material_brown_500, material_brown_700
/*
* 赤 0xffc53929
* 橙 0xffff9100
* Lime 0xffafb42b;
* 绿 0xff0b8043
* 青 0xff0097a7
* 蓝 0xff3367d6
* 紫 0xff9c27b0
* 棕 0xff795548
*/
private static final int[] DARK_COLOR_TABLE = {
0xffe67c73, 0xffdb4437, 0xffc53929, 0xffff5252,
0xff4285f4, 0xff3367d6, 0xff448aff, 0xff2979ff,
0xff0097a7,
0xff0f9d58, 0xff0b8043,
0xffafb42b,
0xfff4b400, 0xfff09300,
0xffff9800, 0xfff57c00, 0xffff9100,
0xffff5722, 0xffc53929, 0xffff5252, 0xffff1744,
0xff757575, 0xff717171,
0xff607d8b, 0xff546e7a, 0xff455a64, 0xff37474f,
0xff795548, 0xff5d4037
0xffc53929, 0xffff9100, 0xffafb42b, 0xff0b8043,
0xff0097a7, 0xff3367d6, 0xff9c27b0, 0xff795548
};
/**
@@ -74,9 +60,9 @@ public final class Theme {
* @return
*/
public static int getDarkerColor(int color) {
return (((color & 0xff0000) >> 1) & 0xff0000)
| (((color & 0xff00) >> 1) & 0xff00)
| (((color & 0xff) >> 1) & 0xff)
return ((int)((color & 0xff0000) * 0.8) & 0xff0000)
| ((int)((color & 0xff00) * 0.8) & 0xff00)
| ((int)((color & 0xff) * 0.8) & 0xff)
| (color & 0xff000000);
}
+2 -4
View File
@@ -43,15 +43,14 @@ import com.readystatesoftware.systembartint.SystemBarTintManager.SystemBarConfig
public class Ui {
@SuppressWarnings("unused")
private static final String TAG = "Ui";
private static final String TAG = Ui.class.getSimpleName();
private static Context mContext;
private static Resources mResources;
private static final BitmapFactory.Options opt = new BitmapFactory.Options();
private static float mDensity;
public static float mDensity;
public static int HOLO_BLUE_DARK;
public static int LIST_MAIN_BG;
public static int DOUJINSHI_BG_COLOR;
public static int MANGA_BG_COLOR;
@@ -91,7 +90,6 @@ public class Ui {
// init color
HOLO_BLUE_DARK = mResources.getColor(android.R.color.holo_blue_dark);
LIST_MAIN_BG = mResources.getColor(R.color.list_main_bg);
DOUJINSHI_BG_COLOR = mResources.getColor(R.color.doujinshi_bg);
MANGA_BG_COLOR = mResources.getColor(R.color.manga_bg);
@@ -33,8 +33,9 @@ import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Build;
import android.view.View;
import android.view.ViewParent;
public class Util {
public class Utils {
@SuppressWarnings("unused")
private static String TAG = "Util";
@@ -134,12 +135,12 @@ public class Util {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String str = null;
try {
Util.copy(is, baos, 1024);
Utils.copy(is, baos, 1024);
str = baos.toString(charset);
} catch (IOException e) {
e.printStackTrace();
} finally {
Util.closeStreamQuietly(baos);
Utils.closeStreamQuietly(baos);
}
return str;
}
@@ -157,7 +158,7 @@ public class Util {
String str = shaper.getString(key, null);
if (str == null || str.length() == 0)
return null;
return new String(Util.hexStringToByteArray(str)).split("\n");
return new String(Utils.hexStringToByteArray(str)).split("\n");
}
public static void putStrings(SharedPreferences shaper, String key, List<String> strs) {
@@ -314,4 +315,40 @@ public class Util {
public static final boolean int2boolean(int integer) {
return integer == 0 ? false : true;
}
public static void getCenterInWindows(View view, int[] location) {
getLocationInWindow(view, location);
location[0] += view.getWidth() / 2;
location[1] += view.getHeight() / 2;
}
public static void getLocationInWindow(View view, int[] location) {
if (location == null || location.length < 2) {
throw new IllegalArgumentException("location must be an array of two integers");
}
float[] position = new float[2];
position[0] = view.getLeft();
position[1] = view.getTop();
ViewParent viewParent = view.getParent();
while (viewParent instanceof View) {
view = (View)viewParent;
if (view.getId() == android.R.id.content) {
break;
}
position[0] -= view.getScrollX();
position[1] -= view.getScrollY();
position[0] += view.getLeft();
position[1] += view.getTop();
viewParent = view.getParent();
}
location[0] = (int) (position[0] + 0.5f);
location[1] = (int) (position[1] + 0.5f);
}
}
@@ -23,7 +23,7 @@ import android.widget.TableLayout;
import com.hippo.ehviewer.ListUrls;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.util.Util;
import com.hippo.ehviewer.util.Utils;
public class CategoryTable extends TableLayout {
@@ -73,16 +73,16 @@ public class CategoryTable extends TableLayout {
* @param category
*/
public void setCategory(int category) {
mDoujinshi.setChecked(!Util.int2boolean(category & ListUrls.DOUJINSHI));
mManga.setChecked(!Util.int2boolean(category & ListUrls.MANGA));
mArtistCG.setChecked(!Util.int2boolean(category & ListUrls.ARTIST_CG));
mGameCG.setChecked(!Util.int2boolean(category & ListUrls.GAME_CG));
mWestern.setChecked(!Util.int2boolean(category & ListUrls.WESTERN));
mNonH.setChecked(!Util.int2boolean(category & ListUrls.NON_H));
mImageSets.setChecked(!Util.int2boolean(category & ListUrls.IMAGE_SET));
mCosplay.setChecked(!Util.int2boolean(category & ListUrls.COSPLAY));
mAsianPorn.setChecked(!Util.int2boolean(category & ListUrls.ASIAN_PORN));
mMisc.setChecked(!Util.int2boolean(category & ListUrls.MISC));
mDoujinshi.setChecked(!Utils.int2boolean(category & ListUrls.DOUJINSHI));
mManga.setChecked(!Utils.int2boolean(category & ListUrls.MANGA));
mArtistCG.setChecked(!Utils.int2boolean(category & ListUrls.ARTIST_CG));
mGameCG.setChecked(!Utils.int2boolean(category & ListUrls.GAME_CG));
mWestern.setChecked(!Utils.int2boolean(category & ListUrls.WESTERN));
mNonH.setChecked(!Utils.int2boolean(category & ListUrls.NON_H));
mImageSets.setChecked(!Utils.int2boolean(category & ListUrls.IMAGE_SET));
mCosplay.setChecked(!Utils.int2boolean(category & ListUrls.COSPLAY));
mAsianPorn.setChecked(!Utils.int2boolean(category & ListUrls.ASIAN_PORN));
mMisc.setChecked(!Utils.int2boolean(category & ListUrls.MISC));
}
/**
@@ -60,4 +60,9 @@ public class FswView extends View {
paddingRight, paddingBottom);
return re;
}
public interface OnFitSystemWindowsListener {
void onfitSystemWindows(int paddingLeft,
int paddingTop, int paddingRight, int paddingBottom);
}
}
@@ -1,22 +0,0 @@
/*
* 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;
public interface OnFitSystemWindowsListener {
void onfitSystemWindows(int paddingLeft,
int paddingTop, int paddingRight, int paddingBottom);
}
@@ -20,37 +20,58 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RatingBar;
public class ProgressiveRatingBar extends RatingBar {
@SuppressLint("ClickableViewAccessibility")
public class ProgressiveRatingBar extends RatingBar
implements View.OnTouchListener {
private OnDrawListener mListener;
private boolean mEnableRate = true;
private OnUserRateListener mListener;
public ProgressiveRatingBar(Context context) {
super(context);
setOnTouchListener(this);
}
public ProgressiveRatingBar(Context context, AttributeSet attrs) {
super(context, attrs);
setOnTouchListener(this);
}
public ProgressiveRatingBar(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
setOnTouchListener(this);
}
public void setEnableRate(boolean enableRate) {
mEnableRate = enableRate;
}
@SuppressLint("WrongCall")
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mEnableRate)
return false;
else
return true;
}
@Override
@SuppressLint("WrongCall")
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mListener != null)
mListener.onDraw(getRating());
if (isPressed() && mListener != null) {
mListener.onUserRate(getRating());
}
}
public void setOnDrawListener(OnDrawListener l) {
public void setOnUserRateListener(OnUserRateListener l) {
mListener = l;
}
public interface OnDrawListener {
void onDraw(float rating);
public interface OnUserRateListener {
void onUserRate(float rating);
}
}
+12 -11
View File
@@ -16,8 +16,6 @@
package com.hippo.ehviewer.widget;
import com.hippo.ehviewer.R;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -26,6 +24,8 @@ import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import com.hippo.ehviewer.R;
public class RatingView extends View {
private static boolean mInit = false;
private static Bitmap EMPTY_START;
@@ -33,9 +33,9 @@ public class RatingView extends View {
private static Bitmap FULL_START;
private static int mAWidth;
private static int mHeight;
private int mRating;
public RatingView(Context context) {
super(context);
init(context);
@@ -48,11 +48,11 @@ public class RatingView extends View {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
if (mInit)
return;
Resources resources = context.getResources();
FULL_START = BitmapFactory.decodeResource(resources, R.drawable.star_small);
HALF_START = BitmapFactory.decodeResource(resources, R.drawable.star_small_half);
@@ -61,21 +61,21 @@ public class RatingView extends View {
mHeight = FULL_START.getHeight();
mInit = true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mAWidth * 5, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int step = 0;
int fullNum = mRating / 2;
int halfNum = mRating % 2;
int emptyNum = 5 - fullNum - halfNum;
for (int i = 0; i < fullNum; i++, step++)
canvas.drawBitmap(FULL_START, step * mAWidth, 0, null);
for (int i = 0; i < halfNum; i++, step++)
@@ -83,8 +83,9 @@ public class RatingView extends View {
for (int i = 0; i < emptyNum; i++, step++)
canvas.drawBitmap(EMPTY_START, step * mAWidth, 0, null);
}
public void setRating(float rating) {
mRating = Math.min(10, Math.round(rating * 2));
invalidate();
}
}
+4 -10
View File
@@ -24,6 +24,7 @@ import android.widget.Button;
import com.hippo.ehviewer.R;
import com.hippo.ehviewer.cardview.CardViewSalon;
import com.hippo.ehviewer.tile.TileSalon;
import com.hippo.ehviewer.util.Theme;
public class SuperButton extends Button {
@@ -45,13 +46,6 @@ public class SuperButton extends Button {
init(context, attrs, defStyle);
}
public static int getDarkerColor(int color) {
return ((int)((color & 0xff0000) * 0.8) & 0xff0000)
| ((int)((color & 0xff00) * 0.8) & 0xff00)
| ((int)((color & 0xff) * 0.8) & 0xff)
| (color & 0xff000000);
}
public void init(Context context, AttributeSet attrs, int defStyle) {
int backgroundType = BACKGROUND_TYPE_ROUND;
int bgColor = context.getResources().getColor(R.color.background_light);
@@ -92,8 +86,8 @@ public class SuperButton extends Button {
setRoundBackground(withShadow, new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed},
new int[]{}}, new int[]{0xffcccccc, getDarkerColor(bgColor), bgColor},
boundColor == 0 ? null : new int[]{0xffcccccc, getDarkerColor(boundColor), boundColor}); // TODO
new int[]{}}, new int[]{0xffcccccc, Theme.getDarkerColor(bgColor), bgColor},
boundColor == 0 ? null : new int[]{0xffcccccc, Theme.getDarkerColor(boundColor), boundColor}); // TODO
}
private void setTileBackground(int[][] stateSets, int[] bgColors) {
@@ -104,6 +98,6 @@ public class SuperButton extends Button {
setTileBackground(new int[][]{
new int[]{-android.R.attr.state_enabled},
new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed},
new int[]{}}, new int[]{0xffcccccc, getDarkerColor(bgColor), bgColor});
new int[]{}}, new int[]{0xffcccccc, Theme.getDarkerColor(bgColor), bgColor});
}
}
+22 -18
View File
@@ -16,6 +16,7 @@
package com.hippo.ehviewer.widget;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
@@ -36,43 +37,46 @@ public class SuperToast extends Toast {
public static final int WARNING = 1;
public static final int ERROR = 2;
private final Context mContext;
private LinearLayout mMainView;
private ImageView mIcon;
private TextView mMessage;
public SuperToast(Context context) {
super(context);
mContext = context;
private static Context sContext;
public static void setContext(Context context) {
sContext = context;
}
public SuperToast() {
super(sContext);
init();
}
public SuperToast(Context context, int strResId) {
this(context);
public SuperToast(int strResId) {
this();
setMessage(strResId);
}
public SuperToast(Context context, String mesg) {
this(context);
public SuperToast(String mesg) {
this();
setMessage(mesg);
}
public SuperToast(Context context, int strResId, int type) {
this(context, strResId);
public SuperToast(int strResId, int type) {
this(strResId);
setTypeIcon(type);
}
public SuperToast(Context context, String mesg, int type) {
this(context, mesg);
public SuperToast(String mesg, int type) {
this(mesg);
setTypeIcon(type);
}
@SuppressLint("InflateParams")
private void init() {
LayoutInflater inflate = (LayoutInflater)
mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
FrameLayout view = (FrameLayout)inflate.inflate(R.layout.super_toast, null);
FrameLayout view = (FrameLayout)LayoutInflater.from(sContext)
.inflate(R.layout.super_toast, null);
mMainView = (LinearLayout)view.getChildAt(0);
// Set random color
mMainView.setBackgroundColor(Config.getRandomThemeColor() ? Theme.getRandomDarkColor() : Config.getThemeColor());
@@ -102,7 +106,7 @@ public class SuperToast extends Toast {
}
public SuperToast setIcon(int resId) {
return setIcon(mContext.getResources().getDrawable(resId));
return setIcon(sContext.getResources().getDrawable(resId));
}
public SuperToast setIcon(Drawable drawable) {
@@ -112,7 +116,7 @@ public class SuperToast extends Toast {
}
public SuperToast setMessage(int resId) {
return setMessage(mContext.getResources().getString(resId));
return setMessage(sContext.getResources().getString(resId));
}
public SuperToast setMessage(CharSequence text) {
@@ -0,0 +1,52 @@
/*
* 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.windowsanimate;
import java.util.LinkedList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.widget.AbsoluteLayout;
@SuppressWarnings("deprecation")
public class AnimateCanvas extends AbsoluteLayout {
private final List<Ripple> mRippleList = new LinkedList<Ripple>();
public AnimateCanvas(Context context) {
super(context);
setWillNotDraw(false);
}
void addRenderingRipple(Ripple ripple) {
if (!mRippleList.contains(ripple))
mRippleList.add(ripple);
}
void removeRenderingRipple(Ripple ripple) {
mRippleList.remove(ripple);
}
@Override
public void onDraw(Canvas canvas) {
for (Ripple ripple : mRippleList) {
ripple.draw(canvas);
}
}
}
@@ -0,0 +1,407 @@
/*
* 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.windowsanimate;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.annotation.TargetApi;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.view.View;
import android.view.animation.LinearInterpolator;
import com.hippo.ehviewer.util.MathUtils;
import com.hippo.ehviewer.util.Ui;
import com.hippo.ehviewer.util.Utils;
/**
* @author Hippo
*
* Get lots of code from android.graphics.drawable.Ripple
*/
public class Ripple {
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
private static final TimeInterpolator DECEL_INTERPOLATOR = new LogInterpolator();
private static final float GLOBAL_SPEED = 1.0F;
private static final float WAVE_TOUCH_DOWN_ACCELERATION = 1024.0F;
private static final float WAVE_TOUCH_UP_ACCELERATION = 3400.0F;
private static final float WAVE_OPACITY_DECAY_VELOCITY = 3.0F;
private static final float WAVE_OUTER_OPACITY_VELOCITY_MAX = 4.5F;
private static final float WAVE_OUTER_OPACITY_VELOCITY_MIN = 1.5F;
private static final float WAVE_OUTER_SIZE_INFLUENCE_MAX = 200.0F;
private static final float WAVE_OUTER_SIZE_INFLUENCE_MIN = 40.0F;
private static final long RIPPLE_ENTER_DELAY = 80L;
private final WindowsAnimate mWindowsAnimate;
private final View mView;
private final Rect mBounds;
private final boolean mkeepBound;
private float mOuterRadius;
private final int[] mStartPosition = new int[2];
private ObjectAnimator mAnimRadius;
private ObjectAnimator mAnimOpacity;
private ObjectAnimator mAnimOuterOpacity;
private ObjectAnimator mAnimX;
private ObjectAnimator mAnimY;
private float mOuterOpacity = 0.0F;
private float mOpacity = 1.0F;
private float mTweenRadius = 0.0F;
private float mTweenX = 0.0F;
private float mTweenY = 0.0F;
private static Paint mPaint;
static {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(0x20444444);
}
public Ripple(WindowsAnimate windowsAnimate, View view, Rect bounds, boolean keepBound) {
mWindowsAnimate = windowsAnimate;
mView = view;
mBounds = new Rect(bounds);
mkeepBound = keepBound;
float halfWidth = mBounds.width() / 2.0F;
float halfHeight = mBounds.height() / 2.0F;
mOuterRadius = ((float) Math.sqrt(halfWidth * halfWidth
+ halfHeight * halfHeight));
}
public void onBoundsChanged(Rect bounds) {
mBounds.set(bounds);
float halfWidth = mBounds.width() / 2.0F;
float halfHeight = mBounds.height() / 2.0F;
mOuterRadius = ((float) Math.sqrt(halfWidth * halfWidth
+ halfHeight * halfHeight));
}
public void setOpacity(float a) {
mOpacity = a;
invalidateSelf();
}
public float getOpacity() {
return mOpacity;
}
public void setOuterOpacity(float a) {
mOuterOpacity = a;
invalidateSelf();
}
public float getOuterOpacity() {
return mOuterOpacity;
}
public void setRadiusGravity(float r) {
mTweenRadius = r;
invalidateSelf();
}
public float getRadiusGravity() {
return mTweenRadius;
}
public void setXGravity(float x) {
mTweenX = x;
invalidateSelf();
}
public float getXGravity() {
return mTweenX;
}
public void setYGravity(float y) {
mTweenY = y;
invalidateSelf();
}
public float getYGravity() {
return mTweenY;
}
// TODO make mkeepBound work, ripple only show int view's area, just use clipPath
public void draw(Canvas c) {
Utils.getCenterInWindows(mView, mStartPosition);
c.translate(mStartPosition[0], mStartPosition[1]);
drawSoftware(c, mPaint);
c.translate(-mStartPosition[0], -mStartPosition[1]);
}
private void drawSoftware(Canvas c, Paint p) {
int paintAlpha = p.getAlpha();
int outerAlpha = (int) (paintAlpha * mOuterOpacity + 0.5F);
if ((outerAlpha > 0) && (mOuterRadius > 0.0F)) {
p.setAlpha(outerAlpha);
p.setStyle(Paint.Style.FILL);
c.drawCircle(0.0F, 0.0F, mOuterRadius, p);
}
int alpha = (int) (paintAlpha * mOpacity + 0.5F);
float radius = MathUtils.lerp(0.0F, mOuterRadius,
mTweenRadius);
if ((alpha > 0) && (radius > 0.0F)) {
p.setAlpha(alpha);
p.setStyle(Paint.Style.FILL);
c.drawCircle(0.0F, 0.0F, radius, p);
}
p.setAlpha(paintAlpha);
}
// TODO Can't enter before exit end
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public void enter() {
addSelf();
mOuterOpacity = 0.0F;
mOpacity = 1.0F;
mTweenRadius = 0.0F;
mTweenX = 0.0F;
mTweenY = 0.0F;
int radiusDuration = (int) (1000.0D * Math.sqrt(mOuterRadius
/ WAVE_TOUCH_DOWN_ACCELERATION * Ui.mDensity) + 0.5D);
long outerDuration = 666L;
ObjectAnimator radius = ObjectAnimator.ofFloat(this, "radiusGravity",
new float[] { 1.0F });
radius.setDuration(radiusDuration);
radius.setInterpolator(LINEAR_INTERPOLATOR);
radius.setStartDelay(RIPPLE_ENTER_DELAY);
ObjectAnimator cX = ObjectAnimator.ofFloat(this, "xGravity",
new float[] { 1.0F });
cX.setDuration(radiusDuration);
cX.setInterpolator(LINEAR_INTERPOLATOR);
cX.setStartDelay(RIPPLE_ENTER_DELAY);
ObjectAnimator cY = ObjectAnimator.ofFloat(this, "yGravity",
new float[] { 1.0F });
cY.setDuration(radiusDuration);
cY.setInterpolator(LINEAR_INTERPOLATOR);
cY.setStartDelay(RIPPLE_ENTER_DELAY);
ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerOpacity",
new float[] { 0.0F, 1.0F });
outer.setDuration(outerDuration);
outer.setInterpolator(LINEAR_INTERPOLATOR);
if (Build.VERSION.SDK_INT >= 18) {
radius.setAutoCancel(true);
cX.setAutoCancel(true);
cY.setAutoCancel(true);
outer.setAutoCancel(true);
}
mAnimRadius = radius;
mAnimOuterOpacity = outer;
mAnimX = cX;
mAnimY = cY;
radius.start();
outer.start();
cX.start();
cY.start();
}
public void exit() {
cancelSoftwareAnimations();
float radius = MathUtils.lerp(0.0F, mOuterRadius,
mTweenRadius);
float remaining;
if ((mAnimRadius != null) && (mAnimRadius.isRunning())) {
remaining = mOuterRadius - radius;
} else {
remaining = mOuterRadius;
}
int radiusDuration = (int) (1000.0D * Math.sqrt(remaining / 4424.0F
* Ui.mDensity) + 0.5D);
int opacityDuration = (int) (1000.0F * mOpacity / 3.0F + 0.5F);
float outerSizeInfluence = MathUtils.constrain(
(mOuterRadius - 40.0F * Ui.mDensity)
/ (200.0F * Ui.mDensity), 0.0F, 1.0F);
float outerOpacityVelocity = MathUtils.lerp(1.5F, 4.5F,
outerSizeInfluence);
int outerInflection = Math.max(0, (int) (1000.0F
* (mOpacity - mOuterOpacity)
/ (3.0F + outerOpacityVelocity) + 0.5F));
int inflectionOpacity = (int) (255.0F * (mOuterOpacity + outerInflection
* outerOpacityVelocity * outerSizeInfluence / 1000.0F) + 0.5F);
exitSoftware(radiusDuration, opacityDuration, outerInflection,
inflectionOpacity);
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private void exitSoftware(int radiusDuration, int opacityDuration,
int outerInflection, int inflectionOpacity) {
ObjectAnimator radiusAnim = ObjectAnimator.ofFloat(this,
"radiusGravity", new float[] { 1.0F });
radiusAnim.setDuration(radiusDuration);
radiusAnim.setInterpolator(DECEL_INTERPOLATOR);
ObjectAnimator xAnim = ObjectAnimator.ofFloat(this, "xGravity",
new float[] { 1.0F });
xAnim.setDuration(radiusDuration);
xAnim.setInterpolator(DECEL_INTERPOLATOR);
ObjectAnimator yAnim = ObjectAnimator.ofFloat(this, "yGravity",
new float[] { 1.0F });
yAnim.setDuration(radiusDuration);
yAnim.setInterpolator(DECEL_INTERPOLATOR);
ObjectAnimator opacityAnim = ObjectAnimator.ofFloat(this, "opacity",
new float[] { 0.0F });
opacityAnim.setDuration(opacityDuration);
opacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
ObjectAnimator outerOpacityAnim;
if (outerInflection > 0) {
outerOpacityAnim = ObjectAnimator.ofFloat(this,
"outerOpacity", new float[] { inflectionOpacity / 255.0F });
outerOpacityAnim.setDuration(outerInflection);
outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
final int outerDuration = opacityDuration - outerInflection;
if (outerDuration > 0) {
outerOpacityAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
ObjectAnimator outerFadeOutAnim = ObjectAnimator
.ofFloat(Ripple.this, "outerOpacity",
new float[] { 0.0F });
if (Build.VERSION.SDK_INT >= 18)
outerFadeOutAnim.setAutoCancel(true);
outerFadeOutAnim.setDuration(outerDuration);
outerFadeOutAnim
.setInterpolator(Ripple.LINEAR_INTERPOLATOR);
outerFadeOutAnim
.addListener(Ripple.this.mAnimationListener);
Ripple.this.mAnimOuterOpacity = outerFadeOutAnim;
outerFadeOutAnim.start();
}
@Override
public void onAnimationCancel(Animator animation) {
animation.removeListener(this);
}
});
} else {
outerOpacityAnim.addListener(mAnimationListener);
}
} else {
outerOpacityAnim = ObjectAnimator.ofFloat(this, "outerOpacity",
new float[] { 0.0F });
outerOpacityAnim.setDuration(opacityDuration);
outerOpacityAnim.addListener(mAnimationListener);
}
if (Build.VERSION.SDK_INT >= 18) {
radiusAnim.setAutoCancel(true);
xAnim.setAutoCancel(true);
yAnim.setAutoCancel(true);
opacityAnim.setAutoCancel(true);
outerOpacityAnim.setAutoCancel(true);
}
mAnimRadius = radiusAnim;
mAnimOpacity = opacityAnim;
mAnimOuterOpacity = outerOpacityAnim;
mAnimX = opacityAnim;
mAnimY = opacityAnim;
radiusAnim.start();
opacityAnim.start();
outerOpacityAnim.start();
xAnim.start();
yAnim.start();
}
public void cancel() {
cancelSoftwareAnimations();
}
private void cancelSoftwareAnimations() {
if (mAnimRadius != null) {
mAnimRadius.cancel();
}
if (mAnimOpacity != null) {
mAnimOpacity.cancel();
}
if (mAnimOuterOpacity != null) {
mAnimOuterOpacity.cancel();
}
if (mAnimX != null) {
mAnimX.cancel();
}
if (mAnimY != null) {
mAnimY.cancel();
}
}
private void addSelf() {
mWindowsAnimate.addRenderingRipple(this);
}
private void removeSelf() {
mWindowsAnimate.removeRenderingRipple(this);
}
private void invalidateSelf() {
mWindowsAnimate.updateCanvas();
}
private final AnimatorListenerAdapter mAnimationListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Ripple.this.removeSelf();
}
};
private static class LogInterpolator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
return 1.0F - (float) Math.pow(400.0D, -input * 1.4D);
}
}
}
@@ -0,0 +1,103 @@
/*
* 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.windowsanimate;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
/**
* @author Hippo
*
* Get lots of code from android.graphics.drawable.RippleDrawable
*/
public class RippleHelpDrawable extends Drawable {
private final Ripple mRipple;
private boolean mActive = false;
@SuppressWarnings("deprecation")
public RippleHelpDrawable(WindowsAnimate windowsAnimate, View view, boolean keepBound) {
mRipple = new Ripple(windowsAnimate, view, getBounds(), keepBound);
view.setBackgroundDrawable(this);
}
@Override
public boolean isStateful() {
return true;
}
@Override
protected boolean onStateChange(int[] stateSet) {
boolean active = false;
boolean enabled = false;
int N = stateSet.length;
for (int i = 0; i < N; i++) {
if (stateSet[i] == android.R.attr.state_enabled) {
enabled = true;
}
if ((stateSet[i] == android.R.attr.state_focused) ||
(stateSet[i] == android.R.attr.state_pressed)) {
active = true;
}
}
setActive((active) && (enabled));
return false;
}
private void setActive(boolean active) {
if (mActive != active) {
mActive = active;
if (active) {
mRipple.enter();
} else {
mRipple.exit();
}
}
}
@Override
protected void onBoundsChange(Rect bounds) {
mRipple.onBoundsChanged(bounds);
}
@Override
public void draw(Canvas canvas) {
// None
}
@Override
public void setAlpha(int alpha) {
// None
}
@Override
public void setColorFilter(ColorFilter cf) {
// None
}
@Override
public int getOpacity() {
return PixelFormat.TRANSPARENT;
}
}
@@ -0,0 +1,153 @@
/*
* 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.windowsanimate;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.widget.AbsoluteLayout;
import com.hippo.ehviewer.drawable.OvalDrawable;
import com.hippo.ehviewer.util.Utils;
@SuppressWarnings("deprecation")
public final class WindowsAnimate {
private Context mContext;
private ViewGroup mContentViewGroup;
private AnimateCanvas mAnimateCanvas;
private int mRunningAnimateNum = 0;
public boolean init(Activity activity) {
mContentViewGroup = (ViewGroup)activity.getWindow().getDecorView()
.findViewById(android.R.id.content);
if (mContentViewGroup == null)
return false;
mContext = activity.getApplicationContext();
mAnimateCanvas = new AnimateCanvas(mContext);
mContentViewGroup.addView(mAnimateCanvas, new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return true;
}
public void free() {
if (mContentViewGroup != null) {
mContentViewGroup.removeView(mAnimateCanvas);
mContentViewGroup = null;
}
}
public boolean isRunningAnimate() {
return mRunningAnimateNum != 0;
}
public void addRippleEffect(View view, boolean keepBound) {
new RippleHelpDrawable(this, view, keepBound);
}
public void removeRippleEffect(View view) {
// TODO
}
public void updateCanvas() {
mAnimateCanvas.invalidate();
}
void addRenderingRipple(Ripple ripple) {
mAnimateCanvas.addRenderingRipple(ripple);
}
void removeRenderingRipple(Ripple ripple) {
mAnimateCanvas.removeRenderingRipple(ripple);
}
public void addCircleTransitions(View view, int color, OnAnimationEndListener listener) {
if (mContentViewGroup == null)
throw new RuntimeException("Call init(Activity) first, or call it after call free()");
int[] loaction = new int[2];
Utils.getCenterInWindows(view, loaction);
addCircleTransitions(loaction[0], loaction[1], color, listener);
}
public void addCircleTransitions(View view, int x, int y, int color, OnAnimationEndListener listener) {
if (mContentViewGroup == null)
throw new RuntimeException("Call init(Activity) first, or call it after call free()");
int[] loaction = new int[2];
Utils.getLocationInWindow(view, loaction);
addCircleTransitions(loaction[0] + x, loaction[1] + y, color, listener);
}
public void addCircleTransitions(final int x, final int y, int color, final OnAnimationEndListener listener) {
if (mContentViewGroup == null)
throw new RuntimeException("Call init(Activity) first, or call it after call free()");
int maxWidth = mAnimateCanvas.getWidth();
int maxHeight = mAnimateCanvas.getHeight();
final double maxLength = Math.sqrt(maxWidth * maxWidth + maxHeight * maxHeight);
final View animateView = new View(mContext);
animateView.setClickable(true);
animateView.setBackgroundDrawable(new OvalDrawable(color));
final AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams(0, 0, x, y);
mAnimateCanvas.addView(animateView, lp);
ValueAnimator animation = ValueAnimator.ofFloat(0.0f, 1.0f);
animation.setDuration(500);
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float scale = (Float)animation.getAnimatedValue();
lp.x = (int)(x - maxLength * scale);
lp.y = (int)(y - maxLength * scale);
lp.width = (int)(2 * maxLength * scale);
lp.height = (int)(2 * maxLength * scale);
animateView.requestLayout();
}
});
animation.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {}
@Override
public void onAnimationRepeat(Animator animation) {}
@Override
public void onAnimationEnd(Animator animation) {
if (mAnimateCanvas != null)
mAnimateCanvas.removeView(animateView);
if (listener != null)
listener.onAnimationEnd();
mRunningAnimateNum--;
}
@Override
public void onAnimationCancel(Animator animation) {}
});
animation.setInterpolator(new AccelerateInterpolator());
animation.start();
mRunningAnimateNum++;
}
public interface OnAnimationEndListener {
public void onAnimationEnd();
}
}