diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..c6cbe562a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000000..c45be16cc8 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +MonkeyBook \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000000..96cc43efa6 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000000..e7bedf3377 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000000..97626ba454 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000000..444164129a --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000..7158618b85 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.8 + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000..814aec0dce --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000000..7f68460d8b --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000000..98a9bfd53a --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,111 @@ +apply plugin: 'com.android.application' +apply plugin: 'org.greenrobot.greendao' + +android { + compileSdkVersion 25 + buildToolsVersion '25.0.0' + + defaultConfig { + applicationId "com.monke.monkeybook" + minSdkVersion 17 + targetSdkVersion 25 + versionCode 6 + versionName "1.2.1" + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "debug"] + } + + productFlavors{ + baidu { + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"] + } + pyger{ + manifestPlaceholders = [UMENG_CHANNEL_VALUE: "pyger"] + } + } + + signingConfigs { + config { + keyAlias 'monkeybook' + keyPassword 'zqh19931118' + storeFile file('D:/WorkSpace/Android/PersonalKey/Monke_keystore.jks') + storePassword 'zqh19931118' + } + } + lintOptions { + abortOnError false + } + buildTypes { + release { + buildConfigField "boolean", "IS_RELEASE", "true" + minifyEnabled true + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + applicationVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.apk')) { + //这里修改apk文件名 + def fileName = APP_NAME +"_"+"${variant.productFlavors[0].name}"+ "_v" + defaultConfig.versionName + "(" + defaultConfig.versionCode + ").apk" + output.outputFile = new File(outputFile.parent, fileName) + } + } + } + } + debug { + buildConfigField "boolean", "IS_RELEASE", "false" + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' +// signingConfig signingConfigs.config + } + } +} + +repositories{ + flatDir{ + dirs 'libs' + } +} + + +dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + testCompile 'junit:junit:4.12' + compile(name: 'autoupdatesdk-release', ext: 'aar') + compile 'com.android.support:appcompat-v7:25.1.0' + compile 'com.android.support:design:25.1.0' + compile 'com.android.support:cardview-v7:25.1.0' + compile 'com.android.support:support-compat:25.1.0' + compile project(':basemvplib') + //GreenDao + compile 'org.greenrobot:greendao:3.0.1' + compile 'org.greenrobot:greendao-generator:3.0.0' + //JSOUP + compile 'org.jsoup:jsoup:1.10.2' + //沉浸式状态栏 + compile 'com.zhangmonke:ImmerseLayout:1.1.1' + //ProgressBar + compile 'com.zhangmonke:MProgressBar:1.0.1' + //Glide + compile 'com.github.bumptech.glide:glide:3.7.0' + //AutofitTextView + compile 'me.grantland:autofittextview:0.2.1' + //删除粒子效果 + compile 'tyrantgit:explosionfield:1.0.1' + //View简易动画 + compile 'com.daimajia.easing:library:2.0@aar' + compile 'com.daimajia.androidanimations:library:2.2@aar' + //CircleImageView + compile 'de.hdodenhof:circleimageview:2.1.0' + //SwitchButton + compile 'com.kyleduo.switchbutton:library:1.4.4' + compile 'com.victor:lib:1.0.4' + compile files('libs/commons-codec-1.10-sources.jar') + compile files('libs/juniversalchardet-1.0.3.jar') + compile files('libs/umeng-analytics-v6.1.1.jar') + compile files('libs/utdid4all-1.0.4.jar') +} + +greendao { + schemaVersion 1 + daoPackage 'com.monke.monkeybook.dao' + targetGenDir 'src/main/java' +} diff --git a/app/libs/autoupdatesdk-release.aar b/app/libs/autoupdatesdk-release.aar new file mode 100644 index 0000000000..e6ae996d2f Binary files /dev/null and b/app/libs/autoupdatesdk-release.aar differ diff --git a/app/libs/commons-codec-1.10-sources.jar b/app/libs/commons-codec-1.10-sources.jar new file mode 100644 index 0000000000..d7971c6bfe Binary files /dev/null and b/app/libs/commons-codec-1.10-sources.jar differ diff --git a/app/libs/juniversalchardet-1.0.3.jar b/app/libs/juniversalchardet-1.0.3.jar new file mode 100644 index 0000000000..1af703fec5 Binary files /dev/null and b/app/libs/juniversalchardet-1.0.3.jar differ diff --git a/app/libs/umeng-analytics-v6.1.1.jar b/app/libs/umeng-analytics-v6.1.1.jar new file mode 100644 index 0000000000..76e618c23d Binary files /dev/null and b/app/libs/umeng-analytics-v6.1.1.jar differ diff --git a/app/libs/utdid4all-1.0.4.jar b/app/libs/utdid4all-1.0.4.jar new file mode 100644 index 0000000000..34815c3497 Binary files /dev/null and b/app/libs/utdid4all-1.0.4.jar differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000000..d9aaa87b4c --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,206 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in D:\CodeTool\Android\Android_SDK/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} +# +# 对于一些基本指令的添加 +# +############################################# +# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改 +-optimizationpasses 5 + +# 混合时不使用大小写混合,混合后的类名为小写 +-dontusemixedcaseclassnames + +# 指定不去忽略非公共库的类 +-dontskipnonpubliclibraryclasses + +# 这句话能够使我们的项目混淆后产生映射文件 +# 包含有类名->混淆后类名的映射关系 +-verbose + +# 指定不去忽略非公共库的类成员 +-dontskipnonpubliclibraryclassmembers + +# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。 +-dontpreverify + +# 保留Annotation不混淆 +-keepattributes *Annotation*,InnerClasses + +# 避免混淆泛型 +-keepattributes Signature + +# 抛出异常时保留代码行号 +-keepattributes SourceFile,LineNumberTable + +# 指定混淆是采用的算法,后面的参数是一个过滤器 +# 这个过滤器是谷歌推荐的算法,一般不做更改 +-optimizations !code/simplification/cast,!field/*,!class/merging/* + + +############################################# +# +# Android开发中一些需要保留的公共部分 +# +############################################# + +# 保留我们使用的四大组件,自定义的Application等等这些类不被混淆 +# 因为这些子类都有可能被外部调用 +-keep public class * extends android.app.Activity +-keep public class * extends android.app.Appliction +-keep public class * extends android.app.Service +-keep public class * extends android.content.BroadcastReceiver +-keep public class * extends android.content.ContentProvider +-keep public class * extends android.app.backup.BackupAgentHelper +-keep public class * extends android.preference.Preference +-keep public class * extends android.view.View +-keep public class com.android.vending.licensing.ILicensingService + + +# 保留support下的所有类及其内部类 +-keep class android.support.** {*;} + +# 保留继承的 +-keep public class * extends android.support.v4.** +-keep public class * extends android.support.v7.** +-keep public class * extends android.support.annotation.** + +# 保留R下面的资源 +-keep class **.R$* {*;} + +# 保留本地native方法不被混淆 +-keepclasseswithmembernames class * { + native ; +} + +# 保留在Activity中的方法参数是view的方法, +# 这样以来我们在layout中写的onClick就不会被影响 +-keepclassmembers class * extends android.app.Activity{ + public void *(android.view.View); +} + +# 保留枚举类不被混淆 +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +# 保留我们自定义控件(继承自View)不被混淆 +-keep public class * extends android.view.View{ + *** get*(); + void set*(***); + public (android.content.Context); + public (android.content.Context, android.util.AttributeSet); + public (android.content.Context, android.util.AttributeSet, int); +} + +# 保留Parcelable序列化类不被混淆 +-keep class * implements android.os.Parcelable { + public static final android.os.Parcelable$Creator *; +} + +# 保留Serializable序列化的类不被混淆 +-keepclassmembers class * implements java.io.Serializable { + static final long serialVersionUID; + private static final java.io.ObjectStreamField[] serialPersistentFields; + !static !transient ; + !private ; + !private ; + private void writeObject(java.io.ObjectOutputStream); + private void readObject(java.io.ObjectInputStream); + java.lang.Object writeReplace(); + java.lang.Object readResolve(); +} + +# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆 +-keepclassmembers class * { + void *(**On*Event); + void *(**On*Listener); +} + +# webView处理,项目中没有使用到webView忽略即可 +-keepclassmembers class fqcn.of.javascript.interface.for.webview { + public *; +} +-keepclassmembers class * extends android.webkit.webViewClient { + public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); + public boolean *(android.webkit.WebView, java.lang.String); +} +-keepclassmembers class * extends android.webkit.webViewClient { + public void *(android.webkit.webView, jav.lang.String); +} + +# 移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用 +# 记得proguard-android.txt中一定不要加-dontoptimize才起作用 +# 另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制 +#-assumenosideeffects class android.util.Log { +# public static int v(...); +# public static int i(...); +# public static int w(...); +# public static int d(...); +# public static int e(...); +#} + +### greenDAO 3 +-keep class org.greenrobot.greendao.**{ *; } +-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao { +public static java.lang.String TABLENAME; +} +-keep class **$Properties +-dontwarn org.greenrobot.greendao.database.** +-dontwarn rx.** + +-dontwarn okio.** +-dontwarn retrofit2.** +-dontwarn javax.annotation.** +-keep class retrofit2.**{*;} +-keep class okhttp3.**{*;} +-keep class okio.**{*;} +-keep class com.hwangjr.rxbus.**{*;} +-dontwarn org.apache.log4j.lf5.viewer.** +-dontnote org.apache.log4j.lf5.viewer.** +-dontwarn freemarker.** +-dontnote org.python.core.** +-dontwarn com.hwangjr.rxbus.** + +-keep class com.monke.monkeybook.widget.**{*;} +-keep class com.monke.monkeybook.bean.**{*;} +-keep class android.support.**{*;} +-keep class me.grantland.widget.**{*;} +-keep class de.hdodenhof.circleimageview.**{*;} +-keep class retrofit2.**{*;} +-keep class tyrant.explosionfield.**{*;} +-keep class tyrantgit.explosionfield.**{*;} +-keep class freemarker.**{*;} +##JSOUP +-keep class org.jsoup.**{ *; } +-keep class com.monke.mprogressbar.**{ *; } + +##友盟统计 +-keepclassmembers class * { + public (org.json.JSONObject); +} +-keep public class com.monke.monkeybook.R$*{ + public static final int *; +} +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +##百度自动更新 +-keep class com.baidu.**{*;} diff --git a/app/src/androidTest/java/com/monke/monkeybook/ApplicationTest.java b/app/src/androidTest/java/com/monke/monkeybook/ApplicationTest.java new file mode 100644 index 0000000000..5fa3869c7d --- /dev/null +++ b/app/src/androidTest/java/com/monke/monkeybook/ApplicationTest.java @@ -0,0 +1,13 @@ +package com.monke.monkeybook; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..530fef4372 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/BitIntentDataManager.java b/app/src/main/java/com/monke/monkeybook/BitIntentDataManager.java new file mode 100644 index 0000000000..9db86da2dc --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/BitIntentDataManager.java @@ -0,0 +1,34 @@ +package com.monke.monkeybook; + +import java.util.HashMap; +import java.util.Map; + +public class BitIntentDataManager { + public static Map bigData; + + private static BitIntentDataManager instance = null; + + public static BitIntentDataManager getInstance(){ + if(instance == null){ + synchronized (BitIntentDataManager.class){ + if(instance == null){ + instance = new BitIntentDataManager(); + } + } + } + return instance; + } + + private BitIntentDataManager(){ + bigData = new HashMap<>(); + } + public Object getData(String key){ + return bigData.get(key); + } + public void putData(String key,Object data){ + bigData.put(key,data); + } + public void cleanData(String key){ + bigData.remove(key); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/ErrorAnalyContentManager.java b/app/src/main/java/com/monke/monkeybook/ErrorAnalyContentManager.java new file mode 100644 index 0000000000..e99adda161 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/ErrorAnalyContentManager.java @@ -0,0 +1,124 @@ +package com.monke.monkeybook; + +import com.monke.monkeybook.base.observer.SimpleObserver; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +public class ErrorAnalyContentManager { + private ErrorAnalyContentManager(){ + + } + private static ErrorAnalyContentManager instance; + + public static ErrorAnalyContentManager getInstance(){ + if(instance == null){ + synchronized (ErrorAnalyContentManager.class){ + if(instance == null){ + instance = new ErrorAnalyContentManager(); + } + } + } + return instance; + } + + public void writeNewErrorUrl(final String url){ + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + String filePath = MApplication.getInstance().getExternalFilesDir("").getPath(); + File dir = new File(filePath); + if(!dir.exists()){ + dir.mkdirs(); + } + + File file2 = new File(filePath,"ErrorAnalyUrlsDetail.txt"); + if(!file2.exists()) { + file2.createNewFile(); + } + FileOutputStream fileOutputStream2 = new FileOutputStream(file2,true); + fileOutputStream2.write((url+" \r\n").getBytes()); + fileOutputStream2.flush(); + fileOutputStream2.close(); + /////////////////////////////////////////////////////////////////////// + File file1 = new File(filePath,"ErrorAnalyUrls.txt"); + if(!file1.exists()) { + file1.createNewFile(); + } + FileInputStream inputStream = new FileInputStream(file1); + byte[] bytes = new byte[1024]; + ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); + while (inputStream.read(bytes) != -1) { + arrayOutputStream.write(bytes, 0, bytes.length); + } + inputStream.close(); + arrayOutputStream.close(); + String content = new String(arrayOutputStream.toByteArray()); + if(!content.contains(url.substring(0,url.indexOf('/',8)))){ + FileOutputStream fileOutputStream1 = new FileOutputStream(file1,true); + fileOutputStream1.write((url.substring(0,url.indexOf('/',8))+" \r\n").getBytes()); + fileOutputStream1.flush(); + fileOutputStream1.close(); + } + e.onNext(true); + e.onComplete(); + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(Boolean value) { + + } + + @Override + public void onError(Throwable e) { + + } + }); + } + + public void writeMayByNetError(final String url){ + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + String filePath = MApplication.getInstance().getExternalFilesDir("").getPath(); + File dir = new File(filePath); + if(!dir.exists()){ + dir.mkdirs(); + } + + File file = new File(filePath,"ErrorNetUrl.txt"); + if(!file.exists()) { + file.createNewFile(); + } + FileOutputStream fileOutputStream2 = new FileOutputStream(file,true); + fileOutputStream2.write((url+" \r\n").getBytes()); + fileOutputStream2.flush(); + fileOutputStream2.close(); + e.onNext(true); + e.onComplete(); + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(Boolean value) { + + } + + @Override + public void onError(Throwable e) { + + } + }); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/MApplication.java b/app/src/main/java/com/monke/monkeybook/MApplication.java new file mode 100644 index 0000000000..01c891111f --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/MApplication.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook; + +import android.app.Application; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.widget.Toast; + +import com.monke.monkeybook.service.DownloadService; +import com.umeng.analytics.MobclickAgent; + +public class MApplication extends Application { + + private static MApplication instance; + + @Override + public void onCreate() { + super.onCreate(); + if (BuildConfig.IS_RELEASE) { + String channel = "debug"; + try { + ApplicationInfo appInfo = getPackageManager() + .getApplicationInfo(getPackageName(), + PackageManager.GET_META_DATA); + channel = appInfo.metaData.getString("UMENG_CHANNEL_VALUE"); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + MobclickAgent.startWithConfigure(new MobclickAgent.UMAnalyticsConfig(this, getString(R.string.umeng_key), channel, MobclickAgent.EScenarioType.E_UM_NORMAL, true)); + } + instance = this; + startService(new Intent(this, DownloadService.class)); + } + + public static MApplication getInstance() { + return instance; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/ReadBookControl.java b/app/src/main/java/com/monke/monkeybook/ReadBookControl.java new file mode 100644 index 0000000000..c7f4412e1d --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/ReadBookControl.java @@ -0,0 +1,176 @@ +package com.monke.monkeybook; + +import android.content.SharedPreferences; +import android.graphics.Color; +import com.monke.monkeybook.utils.DensityUtil; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ReadBookControl { + public static final int DEFAULT_TEXT = 2; + public static final int DEFAULT_BG = 1; + + private static List> textKind; + private static List> textDrawable; + + private int textSize; + private int textExtra; + private int textColor; + private int textBackground; + + private int textKindIndex = DEFAULT_TEXT; + private int textDrawableIndex = DEFAULT_BG; + + private Boolean canClickTurn = true; + private Boolean canKeyTurn = true; + + private SharedPreferences preference; + + private static ReadBookControl readBookControl; + + public static ReadBookControl getInstance(){ + if(readBookControl == null){ + synchronized (ReadBookControl.class){ + if(readBookControl == null){ + readBookControl = new ReadBookControl(); + } + } + } + return readBookControl; + } + private ReadBookControl(){ + if(null == textKind){ + textKind = new ArrayList<>(); + Map temp1 = new HashMap<>(); + temp1.put("textSize", 14); + temp1.put("textExtra", DensityUtil.dp2px(MApplication.getInstance(),6.5f)); + textKind.add(temp1); + + Map temp2 = new HashMap<>(); + temp2.put("textSize", 16); + temp2.put("textExtra", DensityUtil.dp2px(MApplication.getInstance(),8)); + textKind.add(temp2); + + Map temp3 = new HashMap<>(); + temp3.put("textSize", 17); + temp3.put("textExtra", DensityUtil.dp2px(MApplication.getInstance(),9)); + textKind.add(temp3); + + Map temp4 = new HashMap<>(); + temp4.put("textSize", 20); + temp4.put("textExtra", DensityUtil.dp2px(MApplication.getInstance(),11)); + textKind.add(temp4); + + Map temp5 = new HashMap<>(); + temp5.put("textSize", 22); + temp5.put("textExtra", DensityUtil.dp2px(MApplication.getInstance(),13)); + textKind.add(temp5); + } + if(null == textDrawable){ + textDrawable = new ArrayList<>(); + Map temp1 = new HashMap<>(); + temp1.put("textColor",Color.parseColor("#3E3D3B")); + temp1.put("textBackground",R.drawable.shape_bg_readbook_white); + textDrawable.add(temp1); + + Map temp2 = new HashMap<>(); + temp2.put("textColor",Color.parseColor("#5E432E")); + temp2.put("textBackground",R.drawable.bg_readbook_yellow); + textDrawable.add(temp2); + + Map temp3 = new HashMap<>(); + temp3.put("textColor",Color.parseColor("#22482C")); + temp3.put("textBackground",R.drawable.bg_readbook_green); + textDrawable.add(temp3); + + Map temp4 = new HashMap<>(); + temp4.put("textColor",Color.parseColor("#808080")); + temp4.put("textBackground",R.drawable.bg_readbook_black); + textDrawable.add(temp4); + } + preference = MApplication.getInstance().getSharedPreferences("CONFIG", 0); + this.textKindIndex = preference.getInt("textKindIndex",DEFAULT_TEXT); + this.textSize = textKind.get(textKindIndex).get("textSize"); + this.textExtra = textKind.get(textKindIndex).get("textExtra"); + this.textDrawableIndex = preference.getInt("textDrawableIndex",DEFAULT_BG); + this.textColor = textDrawable.get(textDrawableIndex).get("textColor"); + this.textBackground = textDrawable.get(textDrawableIndex).get("textBackground"); + + this.canClickTurn = preference.getBoolean("canClickTurn",true); + this.canKeyTurn = preference.getBoolean("canClickTurn",true); + } + + public int getTextSize() { + return textSize; + } + + public int getTextExtra() { + return textExtra; + } + + public int getTextColor() { + return textColor; + } + + public int getTextBackground() { + return textBackground; + } + + public int getTextKindIndex() { + return textKindIndex; + } + + public void setTextKindIndex(int textKindIndex) { + this.textKindIndex = textKindIndex; + SharedPreferences.Editor editor = preference.edit(); + editor.putInt("textKindIndex",textKindIndex); + editor.commit(); + this.textSize = textKind.get(textKindIndex).get("textSize"); + this.textExtra = textKind.get(textKindIndex).get("textExtra"); + } + + public int getTextDrawableIndex() { + return textDrawableIndex; + } + + public void setTextDrawableIndex(int textDrawableIndex) { + this.textDrawableIndex = textDrawableIndex; + SharedPreferences.Editor editor = preference.edit(); + editor.putInt("textDrawableIndex",textDrawableIndex); + editor.commit(); + this.textColor = textDrawable.get(textDrawableIndex).get("textColor"); + this.textBackground = textDrawable.get(textDrawableIndex).get("textBackground"); + } + + public static List> getTextKind() { + return textKind; + } + + public static List> getTextDrawable() { + return textDrawable; + } + + public Boolean getCanKeyTurn() { + return canKeyTurn; + } + + public void setCanKeyTurn(Boolean canKeyTurn) { + this.canKeyTurn = canKeyTurn; + SharedPreferences.Editor editor = preference.edit(); + editor.putBoolean("canKeyTurn",canKeyTurn); + editor.commit(); + } + + public Boolean getCanClickTurn() { + return canClickTurn; + } + + public void setCanClickTurn(Boolean canClickTurn) { + this.canClickTurn = canClickTurn; + SharedPreferences.Editor editor = preference.edit(); + editor.putBoolean("canClickTurn",canClickTurn); + editor.commit(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/base/MBaseActivity.java b/app/src/main/java/com/monke/monkeybook/base/MBaseActivity.java new file mode 100644 index 0000000000..c5d0afb855 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/base/MBaseActivity.java @@ -0,0 +1,19 @@ +package com.monke.monkeybook.base; + +import com.monke.basemvplib.IPresenter; +import com.monke.basemvplib.impl.BaseActivity; +import com.umeng.analytics.MobclickAgent; + +public abstract class MBaseActivity extends BaseActivity{ + @Override + protected void onResume() { + super.onResume(); + MobclickAgent.onResume(this); + } + + @Override + protected void onPause() { + super.onPause(); + MobclickAgent.onPause(this); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/base/observer/SimpleObserClass.java b/app/src/main/java/com/monke/monkeybook/base/observer/SimpleObserClass.java new file mode 100644 index 0000000000..d59fbde476 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/base/observer/SimpleObserClass.java @@ -0,0 +1,37 @@ +package com.monke.monkeybook.base.observer; + +import com.monke.monkeybook.utils.NetworkUtil; + +public class SimpleObserClass { + private int code; + private T t; + + public SimpleObserClass(T t){ + this(t,NetworkUtil.SUCCESS); + } + + public SimpleObserClass(T t,int code){ + this.t = t; + this.code = code; + } + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public Boolean success(){ + return code == NetworkUtil.SUCCESS; + } + + public T getT() { + return t; + } + + public void setT(T t) { + this.t = t; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/base/observer/SimpleObserver.java b/app/src/main/java/com/monke/monkeybook/base/observer/SimpleObserver.java new file mode 100644 index 0000000000..fc0629dc7d --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/base/observer/SimpleObserver.java @@ -0,0 +1,17 @@ +package com.monke.monkeybook.base.observer; + +import io.reactivex.Observer; +import io.reactivex.disposables.Disposable; + +public abstract class SimpleObserver implements Observer { + + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onComplete() { + + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/BookContentBean.java b/app/src/main/java/com/monke/monkeybook/bean/BookContentBean.java new file mode 100644 index 0000000000..fe88769292 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/BookContentBean.java @@ -0,0 +1,143 @@ +package com.monke.monkeybook.bean; + +import android.os.Parcel; +import android.os.Parcelable; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Transient; +import org.greenrobot.greendao.annotation.Generated; + +import java.util.ArrayList; +import java.util.List; + +/** + * 书本缓存内容 + */ +@Entity +public class BookContentBean implements Parcelable{ + @Id + private String durChapterUrl; //对应BookInfoBean noteUrl; + + private int durChapterIndex; //当前章节 (包括番外) + + private String durCapterContent; //当前章节内容 + + private String tag; //来源 某个网站/本地 + + @Transient + private Boolean isRight = true; + + @Transient + private List lineContent = new ArrayList<>(); + + @Transient + private float lineSize; + + public BookContentBean(){ + + } + + public float getLineSize() { + return lineSize; + } + + public void setLineSize(float lineSize) { + this.lineSize = lineSize; + } + + protected BookContentBean(Parcel in) { + durChapterUrl = in.readString(); + durChapterIndex = in.readInt(); + durCapterContent = in.readString(); + tag = in.readString(); + lineContent = in.createStringArrayList(); + isRight = in.readByte()!=0; + } + + @Generated(hash = 1355824386) + public BookContentBean(String durChapterUrl, int durChapterIndex, + String durCapterContent, String tag) { + this.durChapterUrl = durChapterUrl; + this.durChapterIndex = durChapterIndex; + this.durCapterContent = durCapterContent; + this.tag = tag; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(durChapterUrl); + dest.writeInt(durChapterIndex); + dest.writeString(durCapterContent); + dest.writeString(tag); + dest.writeStringList(lineContent); + dest.writeByte((byte) (isRight ? 1 : 0)); + } + + @Override + public int describeContents() { + return 0; + } + + @Transient + public static final Creator CREATOR = new Creator() { + @Override + public BookContentBean createFromParcel(Parcel in) { + return new BookContentBean(in); + } + + @Override + public BookContentBean[] newArray(int size) { + return new BookContentBean[size]; + } + }; + + public String getDurChapterUrl() { + return durChapterUrl; + } + + public void setDurChapterUrl(String durChapterUrl) { + this.durChapterUrl = durChapterUrl; + } + + public int getDurChapterIndex() { + return durChapterIndex; + } + + public void setDurChapterIndex(int durChapterIndex) { + this.durChapterIndex = durChapterIndex; + } + + public String getDurCapterContent() { + return durCapterContent; + } + + public void setDurCapterContent(String durCapterContent) { + this.durCapterContent = durCapterContent; + if(durCapterContent==null || durCapterContent.length()==0) + this.isRight = false; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public List getLineContent() { + return lineContent; + } + + public void setLineContent(List lineContent) { + this.lineContent = lineContent; + } + + public Boolean getRight() { + return isRight; + } + + public void setRight(Boolean right) { + isRight = right; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/BookInfoBean.java b/app/src/main/java/com/monke/monkeybook/bean/BookInfoBean.java new file mode 100644 index 0000000000..c8f5aa96a7 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/BookInfoBean.java @@ -0,0 +1,212 @@ +package com.monke.monkeybook.bean; + +import android.os.Parcel; +import android.os.Parcelable; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Transient; +import org.greenrobot.greendao.annotation.Generated; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * 书本信息 + */ +@Entity +public class BookInfoBean implements Parcelable,Cloneable{ + + @Transient + public static final long REFRESH_DUR = 10*60*1000; + + private String name; //小说名 + + private String tag; + + @Id + private String noteUrl; //如果是来源网站 则小说根地址 /如果是本地 则是小说本地MD5 + + private String chapterUrl; //章节目录地址 + + @Transient + private List chapterlist = new ArrayList<>(); //章节列表 + + private long finalRefreshData; //章节最后更新时间 + + private String coverUrl; //小说封面 + + private String author;//作者 + + private String introduce; //简介 + + private String origin; //来源 + + public BookInfoBean(){ + + } + + protected BookInfoBean(Parcel in) { + name = in.readString(); + tag = in.readString(); + noteUrl = in.readString(); + chapterUrl = in.readString(); + chapterlist = in.createTypedArrayList(ChapterListBean.CREATOR); + finalRefreshData = in.readLong(); + coverUrl = in.readString(); + author = in.readString(); + introduce = in.readString(); + origin = in.readString(); + } + + @Generated(hash = 1627552162) + public BookInfoBean(String name, String tag, String noteUrl, String chapterUrl, + long finalRefreshData, String coverUrl, String author, String introduce, + String origin) { + this.name = name; + this.tag = tag; + this.noteUrl = noteUrl; + this.chapterUrl = chapterUrl; + this.finalRefreshData = finalRefreshData; + this.coverUrl = coverUrl; + this.author = author; + this.introduce = introduce; + this.origin = origin; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(name); + dest.writeString(tag); + dest.writeString(noteUrl); + dest.writeString(chapterUrl); + dest.writeTypedList(chapterlist); + dest.writeLong(finalRefreshData); + dest.writeString(coverUrl); + dest.writeString(author); + dest.writeString(introduce); + dest.writeString(origin); + } + + @Override + public int describeContents() { + return 0; + } + + @Transient + public static final Creator CREATOR = new Creator() { + @Override + public BookInfoBean createFromParcel(Parcel in) { + return new BookInfoBean(in); + } + + @Override + public BookInfoBean[] newArray(int size) { + return new BookInfoBean[size]; + } + }; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getNoteUrl() { + return noteUrl; + } + + public void setNoteUrl(String noteUrl) { + this.noteUrl = noteUrl; + } + + public String getChapterUrl() { + return chapterUrl; + } + + public void setChapterUrl(String chapterUrl) { + this.chapterUrl = chapterUrl; + } + + public List getChapterlist() { + return chapterlist; + } + + public void setChapterlist(List chapterlist) { + this.chapterlist = chapterlist; + } + public void addChapterlist(List chapterlist){ + this.chapterlist.addAll(chapterlist); + } + + public long getFinalRefreshData() { + return finalRefreshData; + } + + public void setFinalRefreshData(long finalRefreshData) { + this.finalRefreshData = finalRefreshData; + } + + public String getCoverUrl() { + return coverUrl; + } + + public void setCoverUrl(String coverUrl) { + this.coverUrl = coverUrl; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getIntroduce() { + return introduce; + } + + public void setIntroduce(String introduce) { + this.introduce = introduce; + } + + public String getOrigin() { + return this.origin; + } + + public void setOrigin(String origin) { + this.origin = origin; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + BookInfoBean bookInfoBean = (BookInfoBean) super.clone(); + bookInfoBean.name = new String(name); + bookInfoBean.tag = new String(tag); + bookInfoBean.noteUrl = new String(noteUrl); + bookInfoBean.chapterUrl = new String(chapterUrl); + bookInfoBean.coverUrl = new String(coverUrl); + bookInfoBean.author = new String(author); + bookInfoBean.introduce = new String(introduce); + bookInfoBean.origin = new String(origin); + if(chapterlist!=null){ + List newList = new ArrayList<>(); + Iterator iterator = chapterlist.iterator(); + while(iterator.hasNext()){ + newList.add((ChapterListBean) iterator.next().clone()); + } + bookInfoBean.setChapterlist(newList); + } + return bookInfoBean; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/bean/BookShelfBean.java b/app/src/main/java/com/monke/monkeybook/bean/BookShelfBean.java new file mode 100644 index 0000000000..a547dc2c0f --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/BookShelfBean.java @@ -0,0 +1,144 @@ +package com.monke.monkeybook.bean; + + +import android.os.Parcel; +import android.os.Parcelable; +import com.monke.monkeybook.widget.contentswitchview.BookContentView; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Generated; +import org.greenrobot.greendao.annotation.Transient; + +/** + * 书架item Bean + */ + +@Entity +public class BookShelfBean implements Parcelable,Cloneable{ + @Transient + public static final long REFRESH_TIME = 5*60*1000; //更新时间间隔 至少 + @Transient + public static final String LOCAL_TAG = "loc_book"; + + @Id + private String noteUrl; //对应BookInfoBean noteUrl; + + private int durChapter; //当前章节 (包括番外) + + private int durChapterPage = BookContentView.DURPAGEINDEXBEGIN; // 当前章节位置 用页码 + + private long finalDate; //最后阅读时间 + + private String tag; + + @Transient + private BookInfoBean bookInfoBean = new BookInfoBean(); + + public BookShelfBean(){ + + } + + protected BookShelfBean(Parcel in) { + noteUrl = in.readString(); + durChapter = in.readInt(); + durChapterPage = in.readInt(); + finalDate = in.readLong(); + tag = in.readString(); + bookInfoBean = in.readParcelable(BookInfoBean.class.getClassLoader()); + } + + @Generated(hash = 2028192361) + public BookShelfBean(String noteUrl, int durChapter, int durChapterPage, long finalDate, + String tag) { + this.noteUrl = noteUrl; + this.durChapter = durChapter; + this.durChapterPage = durChapterPage; + this.finalDate = finalDate; + this.tag = tag; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(noteUrl); + dest.writeInt(durChapter); + dest.writeInt(durChapterPage); + dest.writeLong(finalDate); + dest.writeString(tag); + dest.writeParcelable(bookInfoBean, flags); + } + + @Override + public int describeContents() { + return 0; + } + + @Transient + public static final Creator CREATOR = new Creator() { + @Override + public BookShelfBean createFromParcel(Parcel in) { + return new BookShelfBean(in); + } + + @Override + public BookShelfBean[] newArray(int size) { + return new BookShelfBean[size]; + } + }; + + public String getNoteUrl() { + return noteUrl; + } + + public void setNoteUrl(String noteUrl) { + this.noteUrl = noteUrl; + } + + public int getDurChapter() { + return durChapter; + } + + public void setDurChapter(int durChapter) { + this.durChapter = durChapter; + } + + public int getDurChapterPage() { + return durChapterPage; + } + + public void setDurChapterPage(int durChapterPage) { + this.durChapterPage = durChapterPage; + } + + public long getFinalDate() { + return finalDate; + } + + public void setFinalDate(long finalDate) { + this.finalDate = finalDate; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public BookInfoBean getBookInfoBean() { + return bookInfoBean; + } + + public void setBookInfoBean(BookInfoBean bookInfoBean) { + this.bookInfoBean = bookInfoBean; + } + + @Override + public Object clone() throws CloneNotSupportedException { + BookShelfBean bookShelfBean = (BookShelfBean) super.clone(); + bookShelfBean.noteUrl = new String(noteUrl); + bookShelfBean.tag = new String(tag); + bookShelfBean.bookInfoBean = (BookInfoBean) bookInfoBean.clone(); + return bookShelfBean; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/bean/ChapterListBean.java b/app/src/main/java/com/monke/monkeybook/bean/ChapterListBean.java new file mode 100644 index 0000000000..12331f17c5 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/ChapterListBean.java @@ -0,0 +1,148 @@ +package com.monke.monkeybook.bean; + +import android.os.Parcel; +import android.os.Parcelable; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Transient; +import org.greenrobot.greendao.annotation.Generated; + +@Entity +public class ChapterListBean implements Parcelable,Cloneable{ + + private String noteUrl; //对应BookInfoBean noteUrl; + + private int durChapterIndex; //当前章节数 + @Id + private String durChapterUrl; //当前章节对应的文章地址 + + private String durChapterName; //当前章节名称 + + private String tag; + + private Boolean hasCache = false; + @Transient + private BookContentBean bookContentBean = new BookContentBean(); + + protected ChapterListBean(Parcel in) { + noteUrl = in.readString(); + durChapterIndex = in.readInt(); + durChapterUrl = in.readString(); + durChapterName = in.readString(); + tag = in.readString(); + bookContentBean = in.readParcelable(BookContentBean.class.getClassLoader()); + hasCache = in.readByte() != 0; + } + + @Generated(hash = 1225922702) + public ChapterListBean(String noteUrl, int durChapterIndex, String durChapterUrl, + String durChapterName, String tag, Boolean hasCache) { + this.noteUrl = noteUrl; + this.durChapterIndex = durChapterIndex; + this.durChapterUrl = durChapterUrl; + this.durChapterName = durChapterName; + this.tag = tag; + this.hasCache = hasCache; + } + + @Generated(hash = 1096893365) + public ChapterListBean() { + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(noteUrl); + dest.writeInt(durChapterIndex); + dest.writeString(durChapterUrl); + dest.writeString(durChapterName); + dest.writeString(tag); + dest.writeParcelable(bookContentBean, flags); + dest.writeByte((byte)(hasCache?1:0)); + } + + @Override + public int describeContents() { + return 0; + } + + public BookContentBean getBookContentBean() { + return bookContentBean; + } + + public void setBookContentBean(BookContentBean bookContentBean) { + this.bookContentBean = bookContentBean; + } + + public Boolean getHasCache() { + return this.hasCache; + } + + public void setHasCache(Boolean hasCache) { + this.hasCache = hasCache; + } + + public String getTag() { + return this.tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getDurChapterName() { + return this.durChapterName; + } + + public void setDurChapterName(String durChapterName) { + this.durChapterName = durChapterName; + } + + public String getDurChapterUrl() { + return this.durChapterUrl; + } + + public void setDurChapterUrl(String durChapterUrl) { + this.durChapterUrl = durChapterUrl; + } + + public int getDurChapterIndex() { + return this.durChapterIndex; + } + + public void setDurChapterIndex(int durChapterIndex) { + this.durChapterIndex = durChapterIndex; + } + + public String getNoteUrl() { + return this.noteUrl; + } + + public void setNoteUrl(String noteUrl) { + this.noteUrl = noteUrl; + } + + @Transient + public static final Creator CREATOR = new Creator() { + @Override + public ChapterListBean createFromParcel(Parcel in) { + return new ChapterListBean(in); + } + + @Override + public ChapterListBean[] newArray(int size) { + return new ChapterListBean[size]; + } + }; + + @Override + protected Object clone() throws CloneNotSupportedException { + ChapterListBean chapterListBean = (ChapterListBean) super.clone(); + chapterListBean.noteUrl = new String(noteUrl); + chapterListBean.durChapterUrl = new String(durChapterUrl); + chapterListBean.durChapterName = new String(durChapterName); + chapterListBean.tag = new String(tag); + chapterListBean.hasCache = new Boolean(hasCache); + chapterListBean.bookContentBean = new BookContentBean(); + return chapterListBean; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/DownloadChapterBean.java b/app/src/main/java/com/monke/monkeybook/bean/DownloadChapterBean.java new file mode 100644 index 0000000000..23dac4804b --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/DownloadChapterBean.java @@ -0,0 +1,136 @@ +package com.monke.monkeybook.bean; + +import android.os.Parcel; +import android.os.Parcelable; +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Transient; +import org.greenrobot.greendao.annotation.Generated; + +@Entity +public class DownloadChapterBean implements Parcelable { + private String noteUrl; + + private int durChapterIndex; //当前章节数 + @Id + private String durChapterUrl; //当前章节对应的文章地址 + + private String durChapterName; //当前章节名称 + + private String tag; + + private String bookName; + + private String coverUrl; //小说封面 + + protected DownloadChapterBean(Parcel in) { + noteUrl = in.readString(); + durChapterIndex = in.readInt(); + durChapterUrl = in.readString(); + durChapterName = in.readString(); + tag = in.readString(); + bookName = in.readString(); + coverUrl = in.readString(); + } + + @Generated(hash = 757008458) + public DownloadChapterBean(String noteUrl, int durChapterIndex, String durChapterUrl, + String durChapterName, String tag, String bookName, String coverUrl) { + this.noteUrl = noteUrl; + this.durChapterIndex = durChapterIndex; + this.durChapterUrl = durChapterUrl; + this.durChapterName = durChapterName; + this.tag = tag; + this.bookName = bookName; + this.coverUrl = coverUrl; + } + + @Generated(hash = 301211198) + public DownloadChapterBean() { + } + + @Transient + public static final Creator CREATOR = new Creator() { + @Override + public DownloadChapterBean createFromParcel(Parcel in) { + return new DownloadChapterBean(in); + } + + @Override + public DownloadChapterBean[] newArray(int size) { + return new DownloadChapterBean[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(noteUrl); + dest.writeInt(durChapterIndex); + dest.writeString(durChapterUrl); + dest.writeString(durChapterName); + dest.writeString(tag); + dest.writeString(bookName); + dest.writeString(coverUrl); + } + + public String getNoteUrl() { + return noteUrl; + } + + public void setNoteUrl(String noteUrl) { + this.noteUrl = noteUrl; + } + + public int getDurChapterIndex() { + return durChapterIndex; + } + + public void setDurChapterIndex(int durChapterIndex) { + this.durChapterIndex = durChapterIndex; + } + + public String getDurChapterUrl() { + return durChapterUrl; + } + + public void setDurChapterUrl(String durChapterUrl) { + this.durChapterUrl = durChapterUrl; + } + + public String getDurChapterName() { + return durChapterName; + } + + public void setDurChapterName(String durChapterName) { + this.durChapterName = durChapterName; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getBookName() { + return bookName; + } + + public void setBookName(String bookName) { + this.bookName = bookName; + } + + public String getCoverUrl() { + return coverUrl; + } + + public void setCoverUrl(String coverUrl) { + this.coverUrl = coverUrl; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/DownloadChapterListBean.java b/app/src/main/java/com/monke/monkeybook/bean/DownloadChapterListBean.java new file mode 100644 index 0000000000..83302538a8 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/DownloadChapterListBean.java @@ -0,0 +1,51 @@ +package com.monke.monkeybook.bean; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.List; + +public class DownloadChapterListBean implements Parcelable { + private List data; + + public DownloadChapterListBean(List result) { + this.data = result; + } + + protected DownloadChapterListBean(Parcel in) { + if(data == null) + data = new ArrayList<>(); + in.readTypedList(data,DownloadChapterBean.CREATOR); + } + + public static final Creator CREATOR = new Creator() { + @Override + public DownloadChapterListBean createFromParcel(Parcel in) { + return new DownloadChapterListBean(in); + } + + @Override + public DownloadChapterListBean[] newArray(int size) { + return new DownloadChapterListBean[size]; + } + }; + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeTypedList(data); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/LibraryBean.java b/app/src/main/java/com/monke/monkeybook/bean/LibraryBean.java new file mode 100644 index 0000000000..e82eca6eb6 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/LibraryBean.java @@ -0,0 +1,24 @@ +package com.monke.monkeybook.bean; + +import java.util.List; + +public class LibraryBean { + private List libraryNewBooks; + private List kindBooks; + + public List getLibraryNewBooks() { + return libraryNewBooks; + } + + public void setLibraryNewBooks(List libraryNewBooks) { + this.libraryNewBooks = libraryNewBooks; + } + + public List getKindBooks() { + return kindBooks; + } + + public void setKindBooks(List kindBooks) { + this.kindBooks = kindBooks; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/LibraryKindBookListBean.java b/app/src/main/java/com/monke/monkeybook/bean/LibraryKindBookListBean.java new file mode 100644 index 0000000000..3a18801d7e --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/LibraryKindBookListBean.java @@ -0,0 +1,33 @@ +package com.monke.monkeybook.bean; + +import java.util.List; + +public class LibraryKindBookListBean { + private String kindName; + private String kindUrl; + private List books; + + public String getKindName() { + return kindName; + } + + public void setKindName(String kindName) { + this.kindName = kindName; + } + + public List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } + + public String getKindUrl() { + return kindUrl; + } + + public void setKindUrl(String kindUrl) { + this.kindUrl = kindUrl; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/LibraryNewBookBean.java b/app/src/main/java/com/monke/monkeybook/bean/LibraryNewBookBean.java new file mode 100644 index 0000000000..b8d288316a --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/LibraryNewBookBean.java @@ -0,0 +1,47 @@ +package com.monke.monkeybook.bean; + +public class LibraryNewBookBean { + private String name; + private String url; + private String tag; + private String orgin; + + public LibraryNewBookBean(String name, String url, String tag, String orgin) { + this.name = name; + this.url = url; + this.tag = tag; + this.orgin = orgin; + } + + public String getOrgin() { + return orgin; + } + + public void setOrgin(String orgin) { + this.orgin = orgin; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/LibraryRankBean.java b/app/src/main/java/com/monke/monkeybook/bean/LibraryRankBean.java new file mode 100644 index 0000000000..9d6b23d709 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/LibraryRankBean.java @@ -0,0 +1,31 @@ +package com.monke.monkeybook.bean; + +public class LibraryRankBean { + private String coverUrl; + private String name; + private String author; + + public String getCoverUrl() { + return coverUrl; + } + + public void setCoverUrl(String coverUrl) { + this.coverUrl = coverUrl; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/LocBookShelfBean.java b/app/src/main/java/com/monke/monkeybook/bean/LocBookShelfBean.java new file mode 100644 index 0000000000..96c2068714 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/LocBookShelfBean.java @@ -0,0 +1,27 @@ +package com.monke.monkeybook.bean; + +public class LocBookShelfBean { + private Boolean isNew; + private BookShelfBean bookShelfBean; + + public LocBookShelfBean(Boolean isNew,BookShelfBean bookShelfBean){ + this.isNew = isNew; + this.bookShelfBean = bookShelfBean; + } + + public Boolean getNew() { + return isNew; + } + + public void setNew(Boolean aNew) { + isNew = aNew; + } + + public BookShelfBean getBookShelfBean() { + return bookShelfBean; + } + + public void setBookShelfBean(BookShelfBean bookShelfBean) { + this.bookShelfBean = bookShelfBean; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/ReadBookContentBean.java b/app/src/main/java/com/monke/monkeybook/bean/ReadBookContentBean.java new file mode 100644 index 0000000000..81b84dc163 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/ReadBookContentBean.java @@ -0,0 +1,29 @@ +package com.monke.monkeybook.bean; + +import java.util.List; + +public class ReadBookContentBean { + private List bookContentList; + private int pageIndex; + + public ReadBookContentBean(List bookContentList,int pageIndex){ + this.bookContentList = bookContentList; + this.pageIndex = pageIndex; + } + + public List getBookContentList() { + return bookContentList; + } + + public void setBookContentList(List bookContentList) { + this.bookContentList = bookContentList; + } + + public int getPageIndex() { + return pageIndex; + } + + public void setPageIndex(int pageIndex) { + this.pageIndex = pageIndex; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/SearchBookBean.java b/app/src/main/java/com/monke/monkeybook/bean/SearchBookBean.java new file mode 100644 index 0000000000..bc4a01b7e0 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/SearchBookBean.java @@ -0,0 +1,179 @@ +package com.monke.monkeybook.bean; + +import android.os.Parcel; +import android.os.Parcelable; + +public class SearchBookBean implements Parcelable{ + + private String noteUrl; + + private String coverUrl; + + private String name; + + private String author; + + private long words; + + private String state; + + private String lastChapter; + + private Boolean isAdd = false; + + private String tag; + + private String kind; + + private String origin; + + private String desc; + + public SearchBookBean(){ + + } + + protected SearchBookBean(Parcel in) { + noteUrl = in.readString(); + coverUrl = in.readString(); + name = in.readString(); + author = in.readString(); + words = in.readLong(); + state = in.readString(); + lastChapter = in.readString(); + isAdd = in.readByte() != 0; + tag = in.readString(); + kind = in.readString(); + origin = in.readString(); + desc = in.readString(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(noteUrl); + dest.writeString(coverUrl); + dest.writeString(name); + dest.writeString(author); + dest.writeLong(words); + dest.writeString(state); + dest.writeString(lastChapter); + dest.writeByte((byte)(isAdd?1:0)); + dest.writeString(tag); + dest.writeString(kind); + dest.writeString(origin); + dest.writeString(desc); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator CREATOR = new Creator() { + @Override + public SearchBookBean createFromParcel(Parcel in) { + return new SearchBookBean(in); + } + + @Override + public SearchBookBean[] newArray(int size) { + return new SearchBookBean[size]; + } + }; + + public String getNoteUrl() { + return noteUrl; + } + + public void setNoteUrl(String noteUrl) { + this.noteUrl = noteUrl; + } + + public String getCoverUrl() { + return coverUrl; + } + + public void setCoverUrl(String coverUrl) { + this.coverUrl = coverUrl; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public Boolean getAdd() { + return isAdd; + } + + public void setAdd(Boolean add) { + isAdd = add; + } + + public long getWords() { + return words; + } + + public void setWords(long words) { + this.words = words; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getLastChapter() { + return lastChapter==null?"":lastChapter; + } + + public void setLastChapter(String lastChapter) { + this.lastChapter = lastChapter; + } + + public String getKind() { + return kind; + } + + public void setKind(String kind) { + this.kind = kind; + } + + public String getTag() { + return tag; + } + + public void setTag(String tag) { + this.tag = tag; + } + + public String getOrigin() { + return origin; + } + + public void setOrigin(String origin) { + this.origin = origin; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/bean/SearchHistoryBean.java b/app/src/main/java/com/monke/monkeybook/bean/SearchHistoryBean.java new file mode 100644 index 0000000000..9888620498 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/SearchHistoryBean.java @@ -0,0 +1,56 @@ +package com.monke.monkeybook.bean; + +import org.greenrobot.greendao.annotation.Entity; +import org.greenrobot.greendao.annotation.Id; +import org.greenrobot.greendao.annotation.Unique; +import org.greenrobot.greendao.annotation.Generated; + +@Entity +public class SearchHistoryBean { + @Id(autoincrement = true) + private Long id = null; + private int type; + private String content; + private long date; + public long getDate() { + return this.date; + } + public void setDate(long date) { + this.date = date; + } + public String getContent() { + return this.content; + } + public void setContent(String content) { + this.content = content; + } + public int getType() { + return this.type; + } + public void setType(int type) { + this.type = type; + } + public Long getId() { + return this.id; + } + public void setId(Long id) { + this.id = id; + } + + public SearchHistoryBean(int type, String content, long date) { + this.type = type; + this.content = content; + this.date = date; + } + @Generated(hash = 488115752) + public SearchHistoryBean(Long id, int type, String content, long date) { + this.id = id; + this.type = type; + this.content = content; + this.date = date; + } + @Generated(hash = 1570282321) + public SearchHistoryBean() { + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/WebChapterBean.java b/app/src/main/java/com/monke/monkeybook/bean/WebChapterBean.java new file mode 100644 index 0000000000..5ad55a31ed --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/WebChapterBean.java @@ -0,0 +1,28 @@ +package com.monke.monkeybook.bean; + +public class WebChapterBean { + private T data; + + private Boolean next; + + public WebChapterBean(T data,Boolean next){ + this.data = data; + this.next = next; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } + + public Boolean getNext() { + return next; + } + + public void setNext(Boolean next) { + this.next = next; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/bean/WebContentBean.java b/app/src/main/java/com/monke/monkeybook/bean/WebContentBean.java new file mode 100644 index 0000000000..e682284fb8 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/bean/WebContentBean.java @@ -0,0 +1,27 @@ +package com.monke.monkeybook.bean; + +public class WebContentBean { + private String url; + private String content; + + public WebContentBean(String url,String content){ + this.url = url; + this.content = content; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/cache/ACache.java b/app/src/main/java/com/monke/monkeybook/cache/ACache.java new file mode 100644 index 0000000000..a6150b2b4a --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/cache/ACache.java @@ -0,0 +1,912 @@ +package com.monke.monkeybook.cache; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.RandomAccessFile; +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import org.json.JSONArray; +import org.json.JSONObject; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.PixelFormat; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.util.Log; + +/** + * 本地缓存 + */ +public class ACache { + public static final int TIME_HOUR = 60 * 60; + public static final int TIME_DAY = TIME_HOUR * 24; + private static final int MAX_SIZE = 1000 * 1000 * 50; // 50 mb + private static final int MAX_COUNT = Integer.MAX_VALUE; // 不限制存放数据的数量 + private static Map mInstanceMap = new HashMap(); + private ACacheManager mCache; + + public static ACache get(Context ctx) { + return get(ctx, "ACache"); + } + + public static ACache get(Context ctx, String cacheName) { + File f = new File(ctx.getCacheDir(), cacheName); + return get(f, MAX_SIZE, MAX_COUNT); + } + + public static ACache get(File cacheDir) { + return get(cacheDir, MAX_SIZE, MAX_COUNT); + } + + public static ACache get(Context ctx, long max_zise, int max_count) { + try{ + File f = new File(ctx.getCacheDir(), "ACache"); + return get(f, max_zise, max_count); + }catch (Exception e){ + e.printStackTrace(); + } + + return null; + } + + public static ACache get(File cacheDir, long max_zise, int max_count) { + try{ + ACache manager = mInstanceMap.get(cacheDir.getAbsoluteFile() + myPid()); + if (manager == null) { + manager = new ACache(cacheDir, max_zise, max_count); + mInstanceMap.put(cacheDir.getAbsolutePath() + myPid(), manager); + } + return manager; + }catch (Exception e){ + e.printStackTrace(); + } + + return null; + } + + private static String myPid() { + return "_" + android.os.Process.myPid(); + } + + private ACache(File cacheDir, long max_size, int max_count) { + try{ + if (!cacheDir.exists() && !cacheDir.mkdirs()) { + Log.i("ACache","can't make dirs in " + + cacheDir.getAbsolutePath()); + } + mCache = new ACacheManager(cacheDir, max_size, max_count); + }catch (Exception e){ + e.printStackTrace(); + } + } + + // ======================================= + // ============ String数据 读写 ============== + // ======================================= + /** + * 保存 String数据 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的String数据 + */ + public void put(String key, String value) { + try{ + File file = mCache.newFile(key); + BufferedWriter out = null; + try { + out = new BufferedWriter(new FileWriter(file), 1024); + out.write(value); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (out != null) { + try { + out.flush(); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + mCache.put(file); + } + }catch (Exception e){ + e.printStackTrace(); + } + + } + + /** + * 保存 String数据 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的String数据 + * @param saveTime + * 保存的时间,单位:秒 + */ + public void put(String key, String value, int saveTime) { + put(key, Utils.newStringWithDateInfo(saveTime, value)); + } + + /** + * 读取 String数据 + * + * @param key + * @return String 数据 + */ + public String getAsString(String key) { + File file = mCache.get(key); + if (!file.exists()) + return null; + boolean removeFile = false; + BufferedReader in = null; + try { + in = new BufferedReader(new FileReader(file)); + String readString = ""; + String currentLine; + while ((currentLine = in.readLine()) != null) { + readString += currentLine; + } + if (!Utils.isDue(readString)) { + return Utils.clearDateInfo(readString); + } else { + removeFile = true; + return null; + } + } catch (IOException e) { + e.printStackTrace(); + return null; + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (removeFile) + remove(key); + } + } + + // ======================================= + // ============= JSONObject 数据 读写 ============== + // ======================================= + /** + * 保存 JSONObject数据 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的JSON数据 + */ + public void put(String key, JSONObject value) { + put(key, value.toString()); + } + + /** + * 保存 JSONObject数据 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的JSONObject数据 + * @param saveTime + * 保存的时间,单位:秒 + */ + public void put(String key, JSONObject value, int saveTime) { + put(key, value.toString(), saveTime); + } + + /** + * 读取JSONObject数据 + * + * @param key + * @return JSONObject数据 + */ + public JSONObject getAsJSONObject(String key) { + String JSONString = getAsString(key); + try { + JSONObject obj = new JSONObject(JSONString); + return obj; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + // ======================================= + // ============ JSONArray 数据 读写 ============= + // ======================================= + /** + * 保存 JSONArray数据 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的JSONArray数据 + */ + public void put(String key, JSONArray value) { + put(key, value.toString()); + } + + /** + * 保存 JSONArray数据 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的JSONArray数据 + * @param saveTime + * 保存的时间,单位:秒 + */ + public void put(String key, JSONArray value, int saveTime) { + put(key, value.toString(), saveTime); + } + + /** + * 读取JSONArray数据 + * + * @param key + * @return JSONArray数据 + */ + public JSONArray getAsJSONArray(String key) { + String JSONString = getAsString(key); + try { + JSONArray obj = new JSONArray(JSONString); + return obj; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + // ======================================= + // ============== byte 数据 读写 ============= + // ======================================= + /** + * 保存 byte数据 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的数据 + */ + public void put(String key, byte[] value) { + File file = mCache.newFile(key); + FileOutputStream out = null; + try { + out = new FileOutputStream(file); + out.write(value); + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (out != null) { + try { + out.flush(); + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + mCache.put(file); + } + } + + /** + * 保存 byte数据 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的数据 + * @param saveTime + * 保存的时间,单位:秒 + */ + public void put(String key, byte[] value, int saveTime) { + put(key, Utils.newByteArrayWithDateInfo(saveTime, value)); + } + + /** + * 获取 byte 数据 + * + * @param key + * @return byte 数据 + */ + public byte[] getAsBinary(String key) { + RandomAccessFile RAFile = null; + boolean removeFile = false; + try { + File file = mCache.get(key); + if (!file.exists()) + return null; + RAFile = new RandomAccessFile(file, "r"); + byte[] byteArray = new byte[(int) RAFile.length()]; + RAFile.read(byteArray); + if (!Utils.isDue(byteArray)) { + return Utils.clearDateInfo(byteArray); + } else { + removeFile = true; + return null; + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + if (RAFile != null) { + try { + RAFile.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if (removeFile) + remove(key); + } + } + + // ======================================= + // ============= 序列化 数据 读写 =============== + // ======================================= + /** + * 保存 Serializable数据 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的value + */ + public void put(String key, Serializable value) { + put(key, value, -1); + } + + /** + * 保存 Serializable数据到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的value + * @param saveTime + * 保存的时间,单位:秒 + */ + public void put(String key, Serializable value, int saveTime) { + ByteArrayOutputStream baos = null; + ObjectOutputStream oos = null; + try { + baos = new ByteArrayOutputStream(); + oos = new ObjectOutputStream(baos); + oos.writeObject(value); + byte[] data = baos.toByteArray(); + if (saveTime != -1) { + put(key, data, saveTime); + } else { + put(key, data); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + oos.close(); + } catch (IOException e) { + } + } + } + + /** + * 读取 Serializable数据 + * + * @param key + * @return Serializable 数据 + */ + public Object getAsObject(String key) { + byte[] data = getAsBinary(key); + if (data != null) { + ByteArrayInputStream bais = null; + ObjectInputStream ois = null; + try { + bais = new ByteArrayInputStream(data); + ois = new ObjectInputStream(bais); + Object reObject = ois.readObject(); + return reObject; + } catch (Exception e) { + e.printStackTrace(); + return null; + } finally { + try { + if (bais != null) + bais.close(); + } catch (IOException e) { + e.printStackTrace(); + } + try { + if (ois != null) + ois.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + + } + + // ======================================= + // ============== bitmap 数据 读写 ============= + // ======================================= + /** + * 保存 bitmap 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的bitmap数据 + */ + public void put(String key, Bitmap value) { + put(key, Utils.Bitmap2Bytes(value)); + } + + /** + * 保存 bitmap 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的 bitmap 数据 + * @param saveTime + * 保存的时间,单位:秒 + */ + public void put(String key, Bitmap value, int saveTime) { + put(key, Utils.Bitmap2Bytes(value), saveTime); + } + + /** + * 读取 bitmap 数据 + * + * @param key + * @return bitmap 数据 + */ + public Bitmap getAsBitmap(String key) { + if (getAsBinary(key) == null) { + return null; + } + return Utils.Bytes2Bimap(getAsBinary(key)); + } + + // ======================================= + // ============= drawable 数据 读写 ============= + // ======================================= + /** + * 保存 drawable 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的drawable数据 + */ + public void put(String key, Drawable value) { + put(key, Utils.drawable2Bitmap(value)); + } + + /** + * 保存 drawable 到 缓存中 + * + * @param key + * 保存的key + * @param value + * 保存的 drawable 数据 + * @param saveTime + * 保存的时间,单位:秒 + */ + public void put(String key, Drawable value, int saveTime) { + put(key, Utils.drawable2Bitmap(value), saveTime); + } + + /** + * 读取 Drawable 数据 + * + * @param key + * @return Drawable 数据 + */ + public Drawable getAsDrawable(String key) { + if (getAsBinary(key) == null) { + return null; + } + return Utils.bitmap2Drawable(Utils.Bytes2Bimap(getAsBinary(key))); + } + + /** + * 获取缓存文件 + * + * @param key + * @return value 缓存的文件 + */ + public File file(String key) { + try{ + File f = mCache.newFile(key); + if (f.exists()) + { + return f; + } + }catch (Exception e){ + e.printStackTrace(); + } + + return null; + } + + /** + * 移除某个key + * + * @param key + * @return 是否移除成功 + */ + public boolean remove(String key) { + return mCache.remove(key); + } + + /** + * 清除所有数据 + */ + public void clear() { + mCache.clear(); + } + + /** + * @title 缓存管理器 + * @author 杨福海(michael) www.yangfuhai.com + * @version 1.0 + */ + public class ACacheManager { + private final AtomicLong cacheSize; + private final AtomicInteger cacheCount; + private final long sizeLimit; + private final int countLimit; + private final Map lastUsageDates = Collections + .synchronizedMap(new HashMap()); + protected File cacheDir; + + private ACacheManager(File cacheDir, long sizeLimit, int countLimit) { + this.cacheDir = cacheDir; + this.sizeLimit = sizeLimit; + this.countLimit = countLimit; + cacheSize = new AtomicLong(); + cacheCount = new AtomicInteger(); + calculateCacheSizeAndCacheCount(); + } + + /** + * 计算 cacheSize和cacheCount + */ + private void calculateCacheSizeAndCacheCount() { + new Thread(new Runnable() { + @Override + public void run() { + + try{ + int size = 0; + int count = 0; + File[] cachedFiles = cacheDir.listFiles(); + if (cachedFiles != null) { + for (File cachedFile : cachedFiles) { + size += calculateSize(cachedFile); + count += 1; + lastUsageDates.put(cachedFile, + cachedFile.lastModified()); + } + cacheSize.set(size); + cacheCount.set(count); + } + }catch (Exception e){ + e.printStackTrace(); + } + + } + }).start(); + } + + private void put(File file) { + + try{ + int curCacheCount = cacheCount.get(); + while (curCacheCount + 1 > countLimit) { + long freedSize = removeNext(); + cacheSize.addAndGet(-freedSize); + + curCacheCount = cacheCount.addAndGet(-1); + } + cacheCount.addAndGet(1); + + long valueSize = calculateSize(file); + long curCacheSize = cacheSize.get(); + while (curCacheSize + valueSize > sizeLimit) { + long freedSize = removeNext(); + curCacheSize = cacheSize.addAndGet(-freedSize); + } + cacheSize.addAndGet(valueSize); + + Long currentTime = System.currentTimeMillis(); + file.setLastModified(currentTime); + lastUsageDates.put(file, currentTime); + }catch (Exception e){ + e.printStackTrace(); + } + + } + + private File get(String key) { + File file = newFile(key); + Long currentTime = System.currentTimeMillis(); + file.setLastModified(currentTime); + lastUsageDates.put(file, currentTime); + + return file; + } + + private File newFile(String key) { + return new File(cacheDir, key.hashCode() + ""); + } + + private boolean remove(String key) { + File image = get(key); + return image.delete(); + } + + private void clear() { + try{ + lastUsageDates.clear(); + cacheSize.set(0); + File[] files = cacheDir.listFiles(); + if (files != null) { + for (File f : files) { + f.delete(); + } + } + }catch (Exception e){ + e.printStackTrace(); + } + + } + + /** + * 移除旧的文件 + * + * @return + */ + private long removeNext() { + try{ + if (lastUsageDates.isEmpty()) { + return 0; + } + + Long oldestUsage = null; + File mostLongUsedFile = null; + Set> entries = lastUsageDates.entrySet(); + synchronized (lastUsageDates) { + for (Entry entry : entries) { + if (mostLongUsedFile == null) { + mostLongUsedFile = entry.getKey(); + oldestUsage = entry.getValue(); + } else { + Long lastValueUsage = entry.getValue(); + if (lastValueUsage < oldestUsage) { + oldestUsage = lastValueUsage; + mostLongUsedFile = entry.getKey(); + } + } + } + } + + long fileSize = calculateSize(mostLongUsedFile); + if (mostLongUsedFile.delete()) { + lastUsageDates.remove(mostLongUsedFile); + } + return fileSize; + }catch (Exception e){ + e.printStackTrace(); + return 0; + } + + + } + + private long calculateSize(File file) { + return file.length(); + } + } + + /** + * @title 时间计算工具类 + * @author 杨福海(michael) www.yangfuhai.com + * @version 1.0 + */ + private static class Utils { + + /** + * 判断缓存的String数据是否到期 + * + * @param str + * @return true:到期了 false:还没有到期 + */ + private static boolean isDue(String str) { + return isDue(str.getBytes()); + } + + /** + * 判断缓存的byte数据是否到期 + * + * @param data + * @return true:到期了 false:还没有到期 + */ + private static boolean isDue(byte[] data) { + try{ + String[] strs = getDateInfoFromDate(data); + if (strs != null && strs.length == 2) { + String saveTimeStr = strs[0]; + while (saveTimeStr.startsWith("0")) { + saveTimeStr = saveTimeStr + .substring(1, saveTimeStr.length()); + } + long saveTime = Long.valueOf(saveTimeStr); + long deleteAfter = Long.valueOf(strs[1]); + if (System.currentTimeMillis() > saveTime + deleteAfter * 1000) { + return true; + } + } + }catch (Exception e){ + e.printStackTrace(); + } + + return false; + } + + private static String newStringWithDateInfo(int second, String strInfo) { + return createDateInfo(second) + strInfo; + } + + private static byte[] newByteArrayWithDateInfo(int second, byte[] data2) { + byte[] data1 = createDateInfo(second).getBytes(); + byte[] retdata = new byte[data1.length + data2.length]; + System.arraycopy(data1, 0, retdata, 0, data1.length); + System.arraycopy(data2, 0, retdata, data1.length, data2.length); + return retdata; + } + + private static String clearDateInfo(String strInfo) { + if (strInfo != null && hasDateInfo(strInfo.getBytes())) { + strInfo = strInfo.substring(strInfo.indexOf(mSeparator) + 1, + strInfo.length()); + } + return strInfo; + } + + private static byte[] clearDateInfo(byte[] data) { + if (hasDateInfo(data)) { + return copyOfRange(data, indexOf(data, mSeparator) + 1, + data.length); + } + return data; + } + + private static boolean hasDateInfo(byte[] data) { + return data != null && data.length > 15 && data[13] == '-' + && indexOf(data, mSeparator) > 14; + } + + private static String[] getDateInfoFromDate(byte[] data) { + if (hasDateInfo(data)) { + String saveDate = new String(copyOfRange(data, 0, 13)); + String deleteAfter = new String(copyOfRange(data, 14, + indexOf(data, mSeparator))); + return new String[] { saveDate, deleteAfter }; + } + return null; + } + + private static int indexOf(byte[] data, char c) { + for (int i = 0; i < data.length; i++) { + if (data[i] == c) { + return i; + } + } + return -1; + } + + private static byte[] copyOfRange(byte[] original, int from, int to) { + int newLength = to - from; + if (newLength < 0) + throw new IllegalArgumentException(from + " > " + to); + byte[] copy = new byte[newLength]; + System.arraycopy(original, from, copy, 0, + Math.min(original.length - from, newLength)); + return copy; + } + + private static final char mSeparator = ' '; + + private static String createDateInfo(int second) { + String currentTime = System.currentTimeMillis() + ""; + while (currentTime.length() < 13) { + currentTime = "0" + currentTime; + } + return currentTime + "-" + second + mSeparator; + } + + /* + * Bitmap → byte[] + */ + private static byte[] Bitmap2Bytes(Bitmap bm) { + if (bm == null) { + return null; + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + bm.compress(Bitmap.CompressFormat.PNG, 100, baos); + return baos.toByteArray(); + } + + /* + * byte[] → Bitmap + */ + private static Bitmap Bytes2Bimap(byte[] b) { + if (b.length == 0) { + return null; + } + return BitmapFactory.decodeByteArray(b, 0, b.length); + } + + /* + * Drawable → Bitmap + */ + private static Bitmap drawable2Bitmap(Drawable drawable) { + if (drawable == null) { + return null; + } + // 取 drawable 的长宽 + int w = drawable.getIntrinsicWidth(); + int h = drawable.getIntrinsicHeight(); + // 取 drawable 的颜色格式 + Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 + : Bitmap.Config.RGB_565; + // 建立对应 bitmap + Bitmap bitmap = Bitmap.createBitmap(w, h, config); + // 建立对应 bitmap 的画布 + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, w, h); + // 把 drawable 内容画到画布中 + drawable.draw(canvas); + return bitmap; + } + + /* + * Bitmap → Drawable + */ + @SuppressWarnings("deprecation") + private static Drawable bitmap2Drawable(Bitmap bm) { + if (bm == null) { + return null; + } + return new BitmapDrawable(bm); + } + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/common/RxBusTag.java b/app/src/main/java/com/monke/monkeybook/common/RxBusTag.java new file mode 100644 index 0000000000..c6ac019532 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/common/RxBusTag.java @@ -0,0 +1,25 @@ +package com.monke.monkeybook.common; + + +public class RxBusTag { + + public final static String HAD_ADD_BOOK = "rxbus_add_book"; + + public final static String HAD_REMOVE_BOOK = "rxbus_remove_book"; + + public final static String UPDATE_BOOK_PROGRESS = "rxbus_update_book_progress"; + + public final static String PAUSE_DOWNLOAD_LISTENER = "rxbus_pause_download_listener"; + + public final static String PROGRESS_DOWNLOAD_LISTENER = "rxbus_progress_download_listener"; + + public final static String FINISH_DOWNLOAD_LISTENER = "rxbus_finish_download_listener"; + + public final static String PAUSE_DOWNLOAD = "rxbus_pause_download"; + + public final static String START_DOWNLOAD = "rxbus_start_download"; + + public final static String CANCEL_DOWNLOAD = "rxbus_cancel_download"; + + public final static String ADD_DOWNLOAD_TASK = "rxbus_add_download_task"; +} diff --git a/app/src/main/java/com/monke/monkeybook/common/api/IEasouApi.java b/app/src/main/java/com/monke/monkeybook/common/api/IEasouApi.java new file mode 100644 index 0000000000..9cf52a6774 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/common/api/IEasouApi.java @@ -0,0 +1,44 @@ +package com.monke.monkeybook.common.api; + +import io.reactivex.Observable; +import retrofit2.http.GET; +import retrofit2.http.Headers; +import retrofit2.http.Url; + +public interface IEasouApi { + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getBookInfo(@Url String url); + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable searchBook(@Url String url); + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getBookContent(@Url String url); + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getChapterList(@Url String url); +} diff --git a/app/src/main/java/com/monke/monkeybook/common/api/IGxwztvApi.java b/app/src/main/java/com/monke/monkeybook/common/api/IGxwztvApi.java new file mode 100644 index 0000000000..50fb682f23 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/common/api/IGxwztvApi.java @@ -0,0 +1,66 @@ +package com.monke.monkeybook.common.api; + +import io.reactivex.Observable; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; +import retrofit2.http.Headers; +import retrofit2.http.Query; +import retrofit2.http.Url; + +public interface IGxwztvApi { + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getBookInfo(@Url String url); + + @GET("/search.htm") + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable searchBook(@Query("keyword")String content, @Query("pn")int page); + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getBookContent(@Url String url); + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getChapterList(@Url String url); + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getKindBooks(@Url String url); + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getLibraryData(@Url String url); +} diff --git a/app/src/main/java/com/monke/monkeybook/common/api/ILingdiankanshuApi.java b/app/src/main/java/com/monke/monkeybook/common/api/ILingdiankanshuApi.java new file mode 100644 index 0000000000..9fab0b9f75 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/common/api/ILingdiankanshuApi.java @@ -0,0 +1,46 @@ +package com.monke.monkeybook.common.api; + +import io.reactivex.Observable; +import retrofit2.http.GET; +import retrofit2.http.Headers; +import retrofit2.http.Query; +import retrofit2.http.Url; + +public interface ILingdiankanshuApi { + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getBookInfo(@Url String url); + + @GET("/cse/search") + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable searchBook(@Query("q") String content, @Query("p") int page, @Query("s") String time); + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getBookContent(@Url String url); + + @GET + @Headers({"Accept:text/html,application/xhtml+xml,application/xml", + "User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3", + "Accept-Charset:UTF-8", + "Keep-Alive:300", + "Connection:Keep-Alive", + "Cache-Control:no-cache"}) + Observable getChapterList(@Url String url); +} diff --git a/app/src/main/java/com/monke/monkeybook/dao/BookContentBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/BookContentBeanDao.java new file mode 100644 index 0000000000..6e40f737e0 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/dao/BookContentBeanDao.java @@ -0,0 +1,143 @@ +package com.monke.monkeybook.dao; + +import android.database.Cursor; +import android.database.sqlite.SQLiteStatement; + +import org.greenrobot.greendao.AbstractDao; +import org.greenrobot.greendao.Property; +import org.greenrobot.greendao.internal.DaoConfig; +import org.greenrobot.greendao.database.Database; +import org.greenrobot.greendao.database.DatabaseStatement; + +import com.monke.monkeybook.bean.BookContentBean; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * DAO for table "BOOK_CONTENT_BEAN". +*/ +public class BookContentBeanDao extends AbstractDao { + + public static final String TABLENAME = "BOOK_CONTENT_BEAN"; + + /** + * Properties of entity BookContentBean.
+ * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property DurChapterUrl = new Property(0, String.class, "durChapterUrl", true, "DUR_CHAPTER_URL"); + public final static Property DurChapterIndex = new Property(1, int.class, "durChapterIndex", false, "DUR_CHAPTER_INDEX"); + public final static Property DurCapterContent = new Property(2, String.class, "durCapterContent", false, "DUR_CAPTER_CONTENT"); + public final static Property Tag = new Property(3, String.class, "tag", false, "TAG"); + }; + + + public BookContentBeanDao(DaoConfig config) { + super(config); + } + + public BookContentBeanDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + } + + /** Creates the underlying database table. */ + public static void createTable(Database db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "\"BOOK_CONTENT_BEAN\" (" + // + "\"DUR_CHAPTER_URL\" TEXT PRIMARY KEY NOT NULL ," + // 0: durChapterUrl + "\"DUR_CHAPTER_INDEX\" INTEGER NOT NULL ," + // 1: durChapterIndex + "\"DUR_CAPTER_CONTENT\" TEXT," + // 2: durCapterContent + "\"TAG\" TEXT);"); // 3: tag + } + + /** Drops the underlying database table. */ + public static void dropTable(Database db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"BOOK_CONTENT_BEAN\""; + db.execSQL(sql); + } + + @Override + protected final void bindValues(DatabaseStatement stmt, BookContentBean entity) { + stmt.clearBindings(); + + String durChapterUrl = entity.getDurChapterUrl(); + if (durChapterUrl != null) { + stmt.bindString(1, durChapterUrl); + } + stmt.bindLong(2, entity.getDurChapterIndex()); + + String durCapterContent = entity.getDurCapterContent(); + if (durCapterContent != null) { + stmt.bindString(3, durCapterContent); + } + + String tag = entity.getTag(); + if (tag != null) { + stmt.bindString(4, tag); + } + } + + @Override + protected final void bindValues(SQLiteStatement stmt, BookContentBean entity) { + stmt.clearBindings(); + + String durChapterUrl = entity.getDurChapterUrl(); + if (durChapterUrl != null) { + stmt.bindString(1, durChapterUrl); + } + stmt.bindLong(2, entity.getDurChapterIndex()); + + String durCapterContent = entity.getDurCapterContent(); + if (durCapterContent != null) { + stmt.bindString(3, durCapterContent); + } + + String tag = entity.getTag(); + if (tag != null) { + stmt.bindString(4, tag); + } + } + + @Override + public String readKey(Cursor cursor, int offset) { + return cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0); + } + + @Override + public BookContentBean readEntity(Cursor cursor, int offset) { + BookContentBean entity = new BookContentBean( // + cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // durChapterUrl + cursor.getInt(offset + 1), // durChapterIndex + cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // durCapterContent + cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3) // tag + ); + return entity; + } + + @Override + public void readEntity(Cursor cursor, BookContentBean entity, int offset) { + entity.setDurChapterUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0)); + entity.setDurChapterIndex(cursor.getInt(offset + 1)); + entity.setDurCapterContent(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2)); + entity.setTag(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3)); + } + + @Override + protected final String updateKeyAfterInsert(BookContentBean entity, long rowId) { + return entity.getDurChapterUrl(); + } + + @Override + public String getKey(BookContentBean entity) { + if(entity != null) { + return entity.getDurChapterUrl(); + } else { + return null; + } + } + + @Override + protected final boolean isEntityUpdateable() { + return true; + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/dao/BookInfoBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/BookInfoBeanDao.java new file mode 100644 index 0000000000..3e17cf5677 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/dao/BookInfoBeanDao.java @@ -0,0 +1,213 @@ +package com.monke.monkeybook.dao; + +import android.database.Cursor; +import android.database.sqlite.SQLiteStatement; + +import org.greenrobot.greendao.AbstractDao; +import org.greenrobot.greendao.Property; +import org.greenrobot.greendao.internal.DaoConfig; +import org.greenrobot.greendao.database.Database; +import org.greenrobot.greendao.database.DatabaseStatement; + +import com.monke.monkeybook.bean.BookInfoBean; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * DAO for table "BOOK_INFO_BEAN". +*/ +public class BookInfoBeanDao extends AbstractDao { + + public static final String TABLENAME = "BOOK_INFO_BEAN"; + + /** + * Properties of entity BookInfoBean.
+ * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property Name = new Property(0, String.class, "name", false, "NAME"); + public final static Property Tag = new Property(1, String.class, "tag", false, "TAG"); + public final static Property NoteUrl = new Property(2, String.class, "noteUrl", true, "NOTE_URL"); + public final static Property ChapterUrl = new Property(3, String.class, "chapterUrl", false, "CHAPTER_URL"); + public final static Property FinalRefreshData = new Property(4, long.class, "finalRefreshData", false, "FINAL_REFRESH_DATA"); + public final static Property CoverUrl = new Property(5, String.class, "coverUrl", false, "COVER_URL"); + public final static Property Author = new Property(6, String.class, "author", false, "AUTHOR"); + public final static Property Introduce = new Property(7, String.class, "introduce", false, "INTRODUCE"); + public final static Property Origin = new Property(8, String.class, "origin", false, "ORIGIN"); + }; + + + public BookInfoBeanDao(DaoConfig config) { + super(config); + } + + public BookInfoBeanDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + } + + /** Creates the underlying database table. */ + public static void createTable(Database db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "\"BOOK_INFO_BEAN\" (" + // + "\"NAME\" TEXT," + // 0: name + "\"TAG\" TEXT," + // 1: tag + "\"NOTE_URL\" TEXT PRIMARY KEY NOT NULL ," + // 2: noteUrl + "\"CHAPTER_URL\" TEXT," + // 3: chapterUrl + "\"FINAL_REFRESH_DATA\" INTEGER NOT NULL ," + // 4: finalRefreshData + "\"COVER_URL\" TEXT," + // 5: coverUrl + "\"AUTHOR\" TEXT," + // 6: author + "\"INTRODUCE\" TEXT," + // 7: introduce + "\"ORIGIN\" TEXT);"); // 8: origin + } + + /** Drops the underlying database table. */ + public static void dropTable(Database db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"BOOK_INFO_BEAN\""; + db.execSQL(sql); + } + + @Override + protected final void bindValues(DatabaseStatement stmt, BookInfoBean entity) { + stmt.clearBindings(); + + String name = entity.getName(); + if (name != null) { + stmt.bindString(1, name); + } + + String tag = entity.getTag(); + if (tag != null) { + stmt.bindString(2, tag); + } + + String noteUrl = entity.getNoteUrl(); + if (noteUrl != null) { + stmt.bindString(3, noteUrl); + } + + String chapterUrl = entity.getChapterUrl(); + if (chapterUrl != null) { + stmt.bindString(4, chapterUrl); + } + stmt.bindLong(5, entity.getFinalRefreshData()); + + String coverUrl = entity.getCoverUrl(); + if (coverUrl != null) { + stmt.bindString(6, coverUrl); + } + + String author = entity.getAuthor(); + if (author != null) { + stmt.bindString(7, author); + } + + String introduce = entity.getIntroduce(); + if (introduce != null) { + stmt.bindString(8, introduce); + } + + String origin = entity.getOrigin(); + if (origin != null) { + stmt.bindString(9, origin); + } + } + + @Override + protected final void bindValues(SQLiteStatement stmt, BookInfoBean entity) { + stmt.clearBindings(); + + String name = entity.getName(); + if (name != null) { + stmt.bindString(1, name); + } + + String tag = entity.getTag(); + if (tag != null) { + stmt.bindString(2, tag); + } + + String noteUrl = entity.getNoteUrl(); + if (noteUrl != null) { + stmt.bindString(3, noteUrl); + } + + String chapterUrl = entity.getChapterUrl(); + if (chapterUrl != null) { + stmt.bindString(4, chapterUrl); + } + stmt.bindLong(5, entity.getFinalRefreshData()); + + String coverUrl = entity.getCoverUrl(); + if (coverUrl != null) { + stmt.bindString(6, coverUrl); + } + + String author = entity.getAuthor(); + if (author != null) { + stmt.bindString(7, author); + } + + String introduce = entity.getIntroduce(); + if (introduce != null) { + stmt.bindString(8, introduce); + } + + String origin = entity.getOrigin(); + if (origin != null) { + stmt.bindString(9, origin); + } + } + + @Override + public String readKey(Cursor cursor, int offset) { + return cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2); + } + + @Override + public BookInfoBean readEntity(Cursor cursor, int offset) { + BookInfoBean entity = new BookInfoBean( // + cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // name + cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // tag + cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // noteUrl + cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // chapterUrl + cursor.getLong(offset + 4), // finalRefreshData + cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5), // coverUrl + cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6), // author + cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7), // introduce + cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8) // origin + ); + return entity; + } + + @Override + public void readEntity(Cursor cursor, BookInfoBean entity, int offset) { + entity.setName(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0)); + entity.setTag(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1)); + entity.setNoteUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2)); + entity.setChapterUrl(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3)); + entity.setFinalRefreshData(cursor.getLong(offset + 4)); + entity.setCoverUrl(cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5)); + entity.setAuthor(cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6)); + entity.setIntroduce(cursor.isNull(offset + 7) ? null : cursor.getString(offset + 7)); + entity.setOrigin(cursor.isNull(offset + 8) ? null : cursor.getString(offset + 8)); + } + + @Override + protected final String updateKeyAfterInsert(BookInfoBean entity, long rowId) { + return entity.getNoteUrl(); + } + + @Override + public String getKey(BookInfoBean entity) { + if(entity != null) { + return entity.getNoteUrl(); + } else { + return null; + } + } + + @Override + protected final boolean isEntityUpdateable() { + return true; + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/dao/BookShelfBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/BookShelfBeanDao.java new file mode 100644 index 0000000000..ba34fcb663 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/dao/BookShelfBeanDao.java @@ -0,0 +1,141 @@ +package com.monke.monkeybook.dao; + +import android.database.Cursor; +import android.database.sqlite.SQLiteStatement; + +import org.greenrobot.greendao.AbstractDao; +import org.greenrobot.greendao.Property; +import org.greenrobot.greendao.internal.DaoConfig; +import org.greenrobot.greendao.database.Database; +import org.greenrobot.greendao.database.DatabaseStatement; + +import com.monke.monkeybook.bean.BookShelfBean; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * DAO for table "BOOK_SHELF_BEAN". +*/ +public class BookShelfBeanDao extends AbstractDao { + + public static final String TABLENAME = "BOOK_SHELF_BEAN"; + + /** + * Properties of entity BookShelfBean.
+ * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property NoteUrl = new Property(0, String.class, "noteUrl", true, "NOTE_URL"); + public final static Property DurChapter = new Property(1, int.class, "durChapter", false, "DUR_CHAPTER"); + public final static Property DurChapterPage = new Property(2, int.class, "durChapterPage", false, "DUR_CHAPTER_PAGE"); + public final static Property FinalDate = new Property(3, long.class, "finalDate", false, "FINAL_DATE"); + public final static Property Tag = new Property(4, String.class, "tag", false, "TAG"); + }; + + + public BookShelfBeanDao(DaoConfig config) { + super(config); + } + + public BookShelfBeanDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + } + + /** Creates the underlying database table. */ + public static void createTable(Database db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "\"BOOK_SHELF_BEAN\" (" + // + "\"NOTE_URL\" TEXT PRIMARY KEY NOT NULL ," + // 0: noteUrl + "\"DUR_CHAPTER\" INTEGER NOT NULL ," + // 1: durChapter + "\"DUR_CHAPTER_PAGE\" INTEGER NOT NULL ," + // 2: durChapterPage + "\"FINAL_DATE\" INTEGER NOT NULL ," + // 3: finalDate + "\"TAG\" TEXT);"); // 4: tag + } + + /** Drops the underlying database table. */ + public static void dropTable(Database db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"BOOK_SHELF_BEAN\""; + db.execSQL(sql); + } + + @Override + protected final void bindValues(DatabaseStatement stmt, BookShelfBean entity) { + stmt.clearBindings(); + + String noteUrl = entity.getNoteUrl(); + if (noteUrl != null) { + stmt.bindString(1, noteUrl); + } + stmt.bindLong(2, entity.getDurChapter()); + stmt.bindLong(3, entity.getDurChapterPage()); + stmt.bindLong(4, entity.getFinalDate()); + + String tag = entity.getTag(); + if (tag != null) { + stmt.bindString(5, tag); + } + } + + @Override + protected final void bindValues(SQLiteStatement stmt, BookShelfBean entity) { + stmt.clearBindings(); + + String noteUrl = entity.getNoteUrl(); + if (noteUrl != null) { + stmt.bindString(1, noteUrl); + } + stmt.bindLong(2, entity.getDurChapter()); + stmt.bindLong(3, entity.getDurChapterPage()); + stmt.bindLong(4, entity.getFinalDate()); + + String tag = entity.getTag(); + if (tag != null) { + stmt.bindString(5, tag); + } + } + + @Override + public String readKey(Cursor cursor, int offset) { + return cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0); + } + + @Override + public BookShelfBean readEntity(Cursor cursor, int offset) { + BookShelfBean entity = new BookShelfBean( // + cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // noteUrl + cursor.getInt(offset + 1), // durChapter + cursor.getInt(offset + 2), // durChapterPage + cursor.getLong(offset + 3), // finalDate + cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4) // tag + ); + return entity; + } + + @Override + public void readEntity(Cursor cursor, BookShelfBean entity, int offset) { + entity.setNoteUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0)); + entity.setDurChapter(cursor.getInt(offset + 1)); + entity.setDurChapterPage(cursor.getInt(offset + 2)); + entity.setFinalDate(cursor.getLong(offset + 3)); + entity.setTag(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4)); + } + + @Override + protected final String updateKeyAfterInsert(BookShelfBean entity, long rowId) { + return entity.getNoteUrl(); + } + + @Override + public String getKey(BookShelfBean entity) { + if(entity != null) { + return entity.getNoteUrl(); + } else { + return null; + } + } + + @Override + protected final boolean isEntityUpdateable() { + return true; + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/dao/ChapterListBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/ChapterListBeanDao.java new file mode 100644 index 0000000000..d883f6419f --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/dao/ChapterListBeanDao.java @@ -0,0 +1,171 @@ +package com.monke.monkeybook.dao; + +import android.database.Cursor; +import android.database.sqlite.SQLiteStatement; + +import org.greenrobot.greendao.AbstractDao; +import org.greenrobot.greendao.Property; +import org.greenrobot.greendao.internal.DaoConfig; +import org.greenrobot.greendao.database.Database; +import org.greenrobot.greendao.database.DatabaseStatement; + +import com.monke.monkeybook.bean.ChapterListBean; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * DAO for table "CHAPTER_LIST_BEAN". +*/ +public class ChapterListBeanDao extends AbstractDao { + + public static final String TABLENAME = "CHAPTER_LIST_BEAN"; + + /** + * Properties of entity ChapterListBean.
+ * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property NoteUrl = new Property(0, String.class, "noteUrl", false, "NOTE_URL"); + public final static Property DurChapterIndex = new Property(1, int.class, "durChapterIndex", false, "DUR_CHAPTER_INDEX"); + public final static Property DurChapterUrl = new Property(2, String.class, "durChapterUrl", true, "DUR_CHAPTER_URL"); + public final static Property DurChapterName = new Property(3, String.class, "durChapterName", false, "DUR_CHAPTER_NAME"); + public final static Property Tag = new Property(4, String.class, "tag", false, "TAG"); + public final static Property HasCache = new Property(5, Boolean.class, "hasCache", false, "HAS_CACHE"); + }; + + + public ChapterListBeanDao(DaoConfig config) { + super(config); + } + + public ChapterListBeanDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + } + + /** Creates the underlying database table. */ + public static void createTable(Database db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "\"CHAPTER_LIST_BEAN\" (" + // + "\"NOTE_URL\" TEXT," + // 0: noteUrl + "\"DUR_CHAPTER_INDEX\" INTEGER NOT NULL ," + // 1: durChapterIndex + "\"DUR_CHAPTER_URL\" TEXT PRIMARY KEY NOT NULL ," + // 2: durChapterUrl + "\"DUR_CHAPTER_NAME\" TEXT," + // 3: durChapterName + "\"TAG\" TEXT," + // 4: tag + "\"HAS_CACHE\" INTEGER);"); // 5: hasCache + } + + /** Drops the underlying database table. */ + public static void dropTable(Database db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"CHAPTER_LIST_BEAN\""; + db.execSQL(sql); + } + + @Override + protected final void bindValues(DatabaseStatement stmt, ChapterListBean entity) { + stmt.clearBindings(); + + String noteUrl = entity.getNoteUrl(); + if (noteUrl != null) { + stmt.bindString(1, noteUrl); + } + stmt.bindLong(2, entity.getDurChapterIndex()); + + String durChapterUrl = entity.getDurChapterUrl(); + if (durChapterUrl != null) { + stmt.bindString(3, durChapterUrl); + } + + String durChapterName = entity.getDurChapterName(); + if (durChapterName != null) { + stmt.bindString(4, durChapterName); + } + + String tag = entity.getTag(); + if (tag != null) { + stmt.bindString(5, tag); + } + + Boolean hasCache = entity.getHasCache(); + if (hasCache != null) { + stmt.bindLong(6, hasCache ? 1L: 0L); + } + } + + @Override + protected final void bindValues(SQLiteStatement stmt, ChapterListBean entity) { + stmt.clearBindings(); + + String noteUrl = entity.getNoteUrl(); + if (noteUrl != null) { + stmt.bindString(1, noteUrl); + } + stmt.bindLong(2, entity.getDurChapterIndex()); + + String durChapterUrl = entity.getDurChapterUrl(); + if (durChapterUrl != null) { + stmt.bindString(3, durChapterUrl); + } + + String durChapterName = entity.getDurChapterName(); + if (durChapterName != null) { + stmt.bindString(4, durChapterName); + } + + String tag = entity.getTag(); + if (tag != null) { + stmt.bindString(5, tag); + } + + Boolean hasCache = entity.getHasCache(); + if (hasCache != null) { + stmt.bindLong(6, hasCache ? 1L: 0L); + } + } + + @Override + public String readKey(Cursor cursor, int offset) { + return cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2); + } + + @Override + public ChapterListBean readEntity(Cursor cursor, int offset) { + ChapterListBean entity = new ChapterListBean( // + cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // noteUrl + cursor.getInt(offset + 1), // durChapterIndex + cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // durChapterUrl + cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // durChapterName + cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // tag + cursor.isNull(offset + 5) ? null : cursor.getShort(offset + 5) != 0 // hasCache + ); + return entity; + } + + @Override + public void readEntity(Cursor cursor, ChapterListBean entity, int offset) { + entity.setNoteUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0)); + entity.setDurChapterIndex(cursor.getInt(offset + 1)); + entity.setDurChapterUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2)); + entity.setDurChapterName(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3)); + entity.setTag(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4)); + entity.setHasCache(cursor.isNull(offset + 5) ? null : cursor.getShort(offset + 5) != 0); + } + + @Override + protected final String updateKeyAfterInsert(ChapterListBean entity, long rowId) { + return entity.getDurChapterUrl(); + } + + @Override + public String getKey(ChapterListBean entity) { + if(entity != null) { + return entity.getDurChapterUrl(); + } else { + return null; + } + } + + @Override + protected final boolean isEntityUpdateable() { + return true; + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/dao/DaoMaster.java b/app/src/main/java/com/monke/monkeybook/dao/DaoMaster.java new file mode 100644 index 0000000000..d302a59fd2 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/dao/DaoMaster.java @@ -0,0 +1,111 @@ +package com.monke.monkeybook.dao; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteDatabase.CursorFactory; +import android.util.Log; + +import org.greenrobot.greendao.AbstractDaoMaster; +import org.greenrobot.greendao.database.StandardDatabase; +import org.greenrobot.greendao.database.Database; +import org.greenrobot.greendao.database.DatabaseOpenHelper; +import org.greenrobot.greendao.identityscope.IdentityScopeType; + + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * Master of DAO (schema version 1): knows all DAOs. + */ +public class DaoMaster extends AbstractDaoMaster { + public static final int SCHEMA_VERSION = 1; + + /** Creates underlying database table using DAOs. */ + public static void createAllTables(Database db, boolean ifNotExists) { + BookContentBeanDao.createTable(db, ifNotExists); + BookInfoBeanDao.createTable(db, ifNotExists); + BookShelfBeanDao.createTable(db, ifNotExists); + ChapterListBeanDao.createTable(db, ifNotExists); + DownloadChapterBeanDao.createTable(db, ifNotExists); + SearchHistoryBeanDao.createTable(db, ifNotExists); + } + + /** Drops underlying database table using DAOs. */ + public static void dropAllTables(Database db, boolean ifExists) { + BookContentBeanDao.dropTable(db, ifExists); + BookInfoBeanDao.dropTable(db, ifExists); + BookShelfBeanDao.dropTable(db, ifExists); + ChapterListBeanDao.dropTable(db, ifExists); + DownloadChapterBeanDao.dropTable(db, ifExists); + SearchHistoryBeanDao.dropTable(db, ifExists); + } + + /** + * WARNING: Drops all table on Upgrade! Use only during development. + * Convenience method using a {@link DevOpenHelper}. + */ + public static DaoSession newDevSession(Context context, String name) { + Database db = new DevOpenHelper(context, name).getWritableDb(); + DaoMaster daoMaster = new DaoMaster(db); + return daoMaster.newSession(); + } + + public DaoMaster(SQLiteDatabase db) { + this(new StandardDatabase(db)); + } + + public DaoMaster(Database db) { + super(db, SCHEMA_VERSION); + registerDaoClass(BookContentBeanDao.class); + registerDaoClass(BookInfoBeanDao.class); + registerDaoClass(BookShelfBeanDao.class); + registerDaoClass(ChapterListBeanDao.class); + registerDaoClass(DownloadChapterBeanDao.class); + registerDaoClass(SearchHistoryBeanDao.class); + } + + public DaoSession newSession() { + return new DaoSession(db, IdentityScopeType.Session, daoConfigMap); + } + + public DaoSession newSession(IdentityScopeType type) { + return new DaoSession(db, type, daoConfigMap); + } + + /** + * Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} - + */ + public static abstract class OpenHelper extends DatabaseOpenHelper { + public OpenHelper(Context context, String name) { + super(context, name, SCHEMA_VERSION); + } + + public OpenHelper(Context context, String name, CursorFactory factory) { + super(context, name, factory, SCHEMA_VERSION); + } + + @Override + public void onCreate(Database db) { + Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION); + createAllTables(db, false); + } + } + + /** WARNING: Drops all table on Upgrade! Use only during development. */ + public static class DevOpenHelper extends OpenHelper { + public DevOpenHelper(Context context, String name) { + super(context, name); + } + + public DevOpenHelper(Context context, String name, CursorFactory factory) { + super(context, name, factory); + } + + @Override + public void onUpgrade(Database db, int oldVersion, int newVersion) { + Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables"); + dropAllTables(db, true); + onCreate(db); + } + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/dao/DaoSession.java b/app/src/main/java/com/monke/monkeybook/dao/DaoSession.java new file mode 100644 index 0000000000..4b6ffbf369 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/dao/DaoSession.java @@ -0,0 +1,118 @@ +package com.monke.monkeybook.dao; + +import java.util.Map; + +import org.greenrobot.greendao.AbstractDao; +import org.greenrobot.greendao.AbstractDaoSession; +import org.greenrobot.greendao.database.Database; +import org.greenrobot.greendao.identityscope.IdentityScopeType; +import org.greenrobot.greendao.internal.DaoConfig; + +import com.monke.monkeybook.bean.BookContentBean; +import com.monke.monkeybook.bean.BookInfoBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.ChapterListBean; +import com.monke.monkeybook.bean.DownloadChapterBean; +import com.monke.monkeybook.bean.SearchHistoryBean; + +import com.monke.monkeybook.dao.BookContentBeanDao; +import com.monke.monkeybook.dao.BookInfoBeanDao; +import com.monke.monkeybook.dao.BookShelfBeanDao; +import com.monke.monkeybook.dao.ChapterListBeanDao; +import com.monke.monkeybook.dao.DownloadChapterBeanDao; +import com.monke.monkeybook.dao.SearchHistoryBeanDao; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. + +/** + * {@inheritDoc} + * + * @see org.greenrobot.greendao.AbstractDaoSession + */ +public class DaoSession extends AbstractDaoSession { + + private final DaoConfig bookContentBeanDaoConfig; + private final DaoConfig bookInfoBeanDaoConfig; + private final DaoConfig bookShelfBeanDaoConfig; + private final DaoConfig chapterListBeanDaoConfig; + private final DaoConfig downloadChapterBeanDaoConfig; + private final DaoConfig searchHistoryBeanDaoConfig; + + private final BookContentBeanDao bookContentBeanDao; + private final BookInfoBeanDao bookInfoBeanDao; + private final BookShelfBeanDao bookShelfBeanDao; + private final ChapterListBeanDao chapterListBeanDao; + private final DownloadChapterBeanDao downloadChapterBeanDao; + private final SearchHistoryBeanDao searchHistoryBeanDao; + + public DaoSession(Database db, IdentityScopeType type, Map>, DaoConfig> + daoConfigMap) { + super(db); + + bookContentBeanDaoConfig = daoConfigMap.get(BookContentBeanDao.class).clone(); + bookContentBeanDaoConfig.initIdentityScope(type); + + bookInfoBeanDaoConfig = daoConfigMap.get(BookInfoBeanDao.class).clone(); + bookInfoBeanDaoConfig.initIdentityScope(type); + + bookShelfBeanDaoConfig = daoConfigMap.get(BookShelfBeanDao.class).clone(); + bookShelfBeanDaoConfig.initIdentityScope(type); + + chapterListBeanDaoConfig = daoConfigMap.get(ChapterListBeanDao.class).clone(); + chapterListBeanDaoConfig.initIdentityScope(type); + + downloadChapterBeanDaoConfig = daoConfigMap.get(DownloadChapterBeanDao.class).clone(); + downloadChapterBeanDaoConfig.initIdentityScope(type); + + searchHistoryBeanDaoConfig = daoConfigMap.get(SearchHistoryBeanDao.class).clone(); + searchHistoryBeanDaoConfig.initIdentityScope(type); + + bookContentBeanDao = new BookContentBeanDao(bookContentBeanDaoConfig, this); + bookInfoBeanDao = new BookInfoBeanDao(bookInfoBeanDaoConfig, this); + bookShelfBeanDao = new BookShelfBeanDao(bookShelfBeanDaoConfig, this); + chapterListBeanDao = new ChapterListBeanDao(chapterListBeanDaoConfig, this); + downloadChapterBeanDao = new DownloadChapterBeanDao(downloadChapterBeanDaoConfig, this); + searchHistoryBeanDao = new SearchHistoryBeanDao(searchHistoryBeanDaoConfig, this); + + registerDao(BookContentBean.class, bookContentBeanDao); + registerDao(BookInfoBean.class, bookInfoBeanDao); + registerDao(BookShelfBean.class, bookShelfBeanDao); + registerDao(ChapterListBean.class, chapterListBeanDao); + registerDao(DownloadChapterBean.class, downloadChapterBeanDao); + registerDao(SearchHistoryBean.class, searchHistoryBeanDao); + } + + public void clear() { + bookContentBeanDaoConfig.getIdentityScope().clear(); + bookInfoBeanDaoConfig.getIdentityScope().clear(); + bookShelfBeanDaoConfig.getIdentityScope().clear(); + chapterListBeanDaoConfig.getIdentityScope().clear(); + downloadChapterBeanDaoConfig.getIdentityScope().clear(); + searchHistoryBeanDaoConfig.getIdentityScope().clear(); + } + + public BookContentBeanDao getBookContentBeanDao() { + return bookContentBeanDao; + } + + public BookInfoBeanDao getBookInfoBeanDao() { + return bookInfoBeanDao; + } + + public BookShelfBeanDao getBookShelfBeanDao() { + return bookShelfBeanDao; + } + + public ChapterListBeanDao getChapterListBeanDao() { + return chapterListBeanDao; + } + + public DownloadChapterBeanDao getDownloadChapterBeanDao() { + return downloadChapterBeanDao; + } + + public SearchHistoryBeanDao getSearchHistoryBeanDao() { + return searchHistoryBeanDao; + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/dao/DbHelper.java b/app/src/main/java/com/monke/monkeybook/dao/DbHelper.java new file mode 100644 index 0000000000..99bf7e0e50 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/dao/DbHelper.java @@ -0,0 +1,40 @@ +package com.monke.monkeybook.dao; + +import android.database.sqlite.SQLiteDatabase; +import com.monke.monkeybook.MApplication; + +public class DbHelper { + private DaoMaster.DevOpenHelper mHelper; + private SQLiteDatabase db; + private DaoMaster mDaoMaster; + private DaoSession mDaoSession; + + private DbHelper(){ + mHelper = new DaoMaster.DevOpenHelper(MApplication.getInstance(), "monkebook_db", null); + db = mHelper.getWritableDatabase(); + // 注意:该数据库连接属于 DaoMaster,所以多个 Session 指的是相同的数据库连接。 + mDaoMaster = new DaoMaster(db); + mDaoSession = mDaoMaster.newSession(); + } + + private static DbHelper instance; + + public static DbHelper getInstance(){ + if(null == instance){ + synchronized (DbHelper.class){ + if(null == instance){ + instance = new DbHelper(); + } + } + } + return instance; + } + + public DaoSession getmDaoSession() { + return mDaoSession; + } + + public SQLiteDatabase getDb() { + return db; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/dao/DownloadChapterBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/DownloadChapterBeanDao.java new file mode 100644 index 0000000000..b13abc059c --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/dao/DownloadChapterBeanDao.java @@ -0,0 +1,185 @@ +package com.monke.monkeybook.dao; + +import android.database.Cursor; +import android.database.sqlite.SQLiteStatement; + +import org.greenrobot.greendao.AbstractDao; +import org.greenrobot.greendao.Property; +import org.greenrobot.greendao.internal.DaoConfig; +import org.greenrobot.greendao.database.Database; +import org.greenrobot.greendao.database.DatabaseStatement; + +import com.monke.monkeybook.bean.DownloadChapterBean; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * DAO for table "DOWNLOAD_CHAPTER_BEAN". +*/ +public class DownloadChapterBeanDao extends AbstractDao { + + public static final String TABLENAME = "DOWNLOAD_CHAPTER_BEAN"; + + /** + * Properties of entity DownloadChapterBean.
+ * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property NoteUrl = new Property(0, String.class, "noteUrl", false, "NOTE_URL"); + public final static Property DurChapterIndex = new Property(1, int.class, "durChapterIndex", false, "DUR_CHAPTER_INDEX"); + public final static Property DurChapterUrl = new Property(2, String.class, "durChapterUrl", true, "DUR_CHAPTER_URL"); + public final static Property DurChapterName = new Property(3, String.class, "durChapterName", false, "DUR_CHAPTER_NAME"); + public final static Property Tag = new Property(4, String.class, "tag", false, "TAG"); + public final static Property BookName = new Property(5, String.class, "bookName", false, "BOOK_NAME"); + public final static Property CoverUrl = new Property(6, String.class, "coverUrl", false, "COVER_URL"); + }; + + + public DownloadChapterBeanDao(DaoConfig config) { + super(config); + } + + public DownloadChapterBeanDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + } + + /** Creates the underlying database table. */ + public static void createTable(Database db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "\"DOWNLOAD_CHAPTER_BEAN\" (" + // + "\"NOTE_URL\" TEXT," + // 0: noteUrl + "\"DUR_CHAPTER_INDEX\" INTEGER NOT NULL ," + // 1: durChapterIndex + "\"DUR_CHAPTER_URL\" TEXT PRIMARY KEY NOT NULL ," + // 2: durChapterUrl + "\"DUR_CHAPTER_NAME\" TEXT," + // 3: durChapterName + "\"TAG\" TEXT," + // 4: tag + "\"BOOK_NAME\" TEXT," + // 5: bookName + "\"COVER_URL\" TEXT);"); // 6: coverUrl + } + + /** Drops the underlying database table. */ + public static void dropTable(Database db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"DOWNLOAD_CHAPTER_BEAN\""; + db.execSQL(sql); + } + + @Override + protected final void bindValues(DatabaseStatement stmt, DownloadChapterBean entity) { + stmt.clearBindings(); + + String noteUrl = entity.getNoteUrl(); + if (noteUrl != null) { + stmt.bindString(1, noteUrl); + } + stmt.bindLong(2, entity.getDurChapterIndex()); + + String durChapterUrl = entity.getDurChapterUrl(); + if (durChapterUrl != null) { + stmt.bindString(3, durChapterUrl); + } + + String durChapterName = entity.getDurChapterName(); + if (durChapterName != null) { + stmt.bindString(4, durChapterName); + } + + String tag = entity.getTag(); + if (tag != null) { + stmt.bindString(5, tag); + } + + String bookName = entity.getBookName(); + if (bookName != null) { + stmt.bindString(6, bookName); + } + + String coverUrl = entity.getCoverUrl(); + if (coverUrl != null) { + stmt.bindString(7, coverUrl); + } + } + + @Override + protected final void bindValues(SQLiteStatement stmt, DownloadChapterBean entity) { + stmt.clearBindings(); + + String noteUrl = entity.getNoteUrl(); + if (noteUrl != null) { + stmt.bindString(1, noteUrl); + } + stmt.bindLong(2, entity.getDurChapterIndex()); + + String durChapterUrl = entity.getDurChapterUrl(); + if (durChapterUrl != null) { + stmt.bindString(3, durChapterUrl); + } + + String durChapterName = entity.getDurChapterName(); + if (durChapterName != null) { + stmt.bindString(4, durChapterName); + } + + String tag = entity.getTag(); + if (tag != null) { + stmt.bindString(5, tag); + } + + String bookName = entity.getBookName(); + if (bookName != null) { + stmt.bindString(6, bookName); + } + + String coverUrl = entity.getCoverUrl(); + if (coverUrl != null) { + stmt.bindString(7, coverUrl); + } + } + + @Override + public String readKey(Cursor cursor, int offset) { + return cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2); + } + + @Override + public DownloadChapterBean readEntity(Cursor cursor, int offset) { + DownloadChapterBean entity = new DownloadChapterBean( // + cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // noteUrl + cursor.getInt(offset + 1), // durChapterIndex + cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // durChapterUrl + cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3), // durChapterName + cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4), // tag + cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5), // bookName + cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6) // coverUrl + ); + return entity; + } + + @Override + public void readEntity(Cursor cursor, DownloadChapterBean entity, int offset) { + entity.setNoteUrl(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0)); + entity.setDurChapterIndex(cursor.getInt(offset + 1)); + entity.setDurChapterUrl(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2)); + entity.setDurChapterName(cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3)); + entity.setTag(cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4)); + entity.setBookName(cursor.isNull(offset + 5) ? null : cursor.getString(offset + 5)); + entity.setCoverUrl(cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6)); + } + + @Override + protected final String updateKeyAfterInsert(DownloadChapterBean entity, long rowId) { + return entity.getDurChapterUrl(); + } + + @Override + public String getKey(DownloadChapterBean entity) { + if(entity != null) { + return entity.getDurChapterUrl(); + } else { + return null; + } + } + + @Override + protected final boolean isEntityUpdateable() { + return true; + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/dao/SearchHistoryBeanDao.java b/app/src/main/java/com/monke/monkeybook/dao/SearchHistoryBeanDao.java new file mode 100644 index 0000000000..47e9aa07d8 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/dao/SearchHistoryBeanDao.java @@ -0,0 +1,136 @@ +package com.monke.monkeybook.dao; + +import android.database.Cursor; +import android.database.sqlite.SQLiteStatement; + +import org.greenrobot.greendao.AbstractDao; +import org.greenrobot.greendao.Property; +import org.greenrobot.greendao.internal.DaoConfig; +import org.greenrobot.greendao.database.Database; +import org.greenrobot.greendao.database.DatabaseStatement; + +import com.monke.monkeybook.bean.SearchHistoryBean; + +// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. +/** + * DAO for table "SEARCH_HISTORY_BEAN". +*/ +public class SearchHistoryBeanDao extends AbstractDao { + + public static final String TABLENAME = "SEARCH_HISTORY_BEAN"; + + /** + * Properties of entity SearchHistoryBean.
+ * Can be used for QueryBuilder and for referencing column names. + */ + public static class Properties { + public final static Property Id = new Property(0, Long.class, "id", true, "_id"); + public final static Property Type = new Property(1, int.class, "type", false, "TYPE"); + public final static Property Content = new Property(2, String.class, "content", false, "CONTENT"); + public final static Property Date = new Property(3, long.class, "date", false, "DATE"); + }; + + + public SearchHistoryBeanDao(DaoConfig config) { + super(config); + } + + public SearchHistoryBeanDao(DaoConfig config, DaoSession daoSession) { + super(config, daoSession); + } + + /** Creates the underlying database table. */ + public static void createTable(Database db, boolean ifNotExists) { + String constraint = ifNotExists? "IF NOT EXISTS ": ""; + db.execSQL("CREATE TABLE " + constraint + "\"SEARCH_HISTORY_BEAN\" (" + // + "\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id + "\"TYPE\" INTEGER NOT NULL ," + // 1: type + "\"CONTENT\" TEXT," + // 2: content + "\"DATE\" INTEGER NOT NULL );"); // 3: date + } + + /** Drops the underlying database table. */ + public static void dropTable(Database db, boolean ifExists) { + String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"SEARCH_HISTORY_BEAN\""; + db.execSQL(sql); + } + + @Override + protected final void bindValues(DatabaseStatement stmt, SearchHistoryBean entity) { + stmt.clearBindings(); + + Long id = entity.getId(); + if (id != null) { + stmt.bindLong(1, id); + } + stmt.bindLong(2, entity.getType()); + + String content = entity.getContent(); + if (content != null) { + stmt.bindString(3, content); + } + stmt.bindLong(4, entity.getDate()); + } + + @Override + protected final void bindValues(SQLiteStatement stmt, SearchHistoryBean entity) { + stmt.clearBindings(); + + Long id = entity.getId(); + if (id != null) { + stmt.bindLong(1, id); + } + stmt.bindLong(2, entity.getType()); + + String content = entity.getContent(); + if (content != null) { + stmt.bindString(3, content); + } + stmt.bindLong(4, entity.getDate()); + } + + @Override + public Long readKey(Cursor cursor, int offset) { + return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0); + } + + @Override + public SearchHistoryBean readEntity(Cursor cursor, int offset) { + SearchHistoryBean entity = new SearchHistoryBean( // + cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id + cursor.getInt(offset + 1), // type + cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // content + cursor.getLong(offset + 3) // date + ); + return entity; + } + + @Override + public void readEntity(Cursor cursor, SearchHistoryBean entity, int offset) { + entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0)); + entity.setType(cursor.getInt(offset + 1)); + entity.setContent(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2)); + entity.setDate(cursor.getLong(offset + 3)); + } + + @Override + protected final Long updateKeyAfterInsert(SearchHistoryBean entity, long rowId) { + entity.setId(rowId); + return rowId; + } + + @Override + public Long getKey(SearchHistoryBean entity) { + if(entity != null) { + return entity.getId(); + } else { + return null; + } + } + + @Override + protected final boolean isEntityUpdateable() { + return true; + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/listener/OnGetChapterListListener.java b/app/src/main/java/com/monke/monkeybook/listener/OnGetChapterListListener.java new file mode 100644 index 0000000000..2951140082 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/listener/OnGetChapterListListener.java @@ -0,0 +1,8 @@ +package com.monke.monkeybook.listener; + +import com.monke.monkeybook.bean.BookShelfBean; + +public interface OnGetChapterListListener { + public void success(BookShelfBean bookShelfBean); + public void error(); +} diff --git a/app/src/main/java/com/monke/monkeybook/model/IEasouBookModel.java b/app/src/main/java/com/monke/monkeybook/model/IEasouBookModel.java new file mode 100644 index 0000000000..f7a6fcffb9 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/IEasouBookModel.java @@ -0,0 +1,34 @@ +package com.monke.monkeybook.model; + +import com.monke.monkeybook.bean.BookContentBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.LibraryBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.cache.ACache; +import com.monke.monkeybook.listener.OnGetChapterListListener; + +import java.util.List; + +import io.reactivex.Observable; + +public interface IEasouBookModel { + /** + * 搜索书籍 + */ + public Observable> searchBook(String content, int page, int rankKind); + + /** + * 网络请求并解析书籍信息 + */ + public Observable getBookInfo(final BookShelfBean bookShelfBean); + + /** + * 网络解析图书目录 + */ + public void getChapterList(final BookShelfBean bookShelfBean, OnGetChapterListListener getChapterListListener); + + /** + * 章节缓存 + */ + Observable getBookContent(final String durChapterUrl, final int durChapterIndex); +} diff --git a/app/src/main/java/com/monke/monkeybook/model/IGxwztvBookModel.java b/app/src/main/java/com/monke/monkeybook/model/IGxwztvBookModel.java new file mode 100644 index 0000000000..f93931ff26 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/IGxwztvBookModel.java @@ -0,0 +1,24 @@ +package com.monke.monkeybook.model; + +import com.monke.monkeybook.bean.LibraryBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.cache.ACache; + +import java.util.List; + +import io.reactivex.Observable; + +public interface IGxwztvBookModel extends IStationBookModel { + + public Observable> getKindBook(String url, int page); + + /** + * 获取主页信息 + */ + public Observable getLibraryData(ACache aCache); + + /** + * 解析主页数据 + */ + public Observable analyLibraryData(String data); +} diff --git a/app/src/main/java/com/monke/monkeybook/model/IImportBookModel.java b/app/src/main/java/com/monke/monkeybook/model/IImportBookModel.java new file mode 100644 index 0000000000..a2b0351c4d --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/IImportBookModel.java @@ -0,0 +1,14 @@ +package com.monke.monkeybook.model; + +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.LocBookShelfBean; + +import java.io.File; +import java.util.List; + +import io.reactivex.Observable; + +public interface IImportBookModel { + + Observable importBook(File book); +} diff --git a/app/src/main/java/com/monke/monkeybook/model/IStationBookModel.java b/app/src/main/java/com/monke/monkeybook/model/IStationBookModel.java new file mode 100644 index 0000000000..5a6f31627e --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/IStationBookModel.java @@ -0,0 +1,33 @@ +package com.monke.monkeybook.model; + +import com.monke.monkeybook.bean.BookContentBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.listener.OnGetChapterListListener; + +import java.util.List; + +import io.reactivex.Observable; + +public interface IStationBookModel { + + /** + * 搜索书籍 + */ + public Observable> searchBook(String content, int page); + + /** + * 网络请求并解析书籍信息 + */ + public Observable getBookInfo(final BookShelfBean bookShelfBean); + + /** + * 网络解析图书目录 + */ + public void getChapterList(final BookShelfBean bookShelfBean, OnGetChapterListListener getChapterListListener); + + /** + * 章节缓存 + */ + Observable getBookContent(final String durChapterUrl, final int durChapterIndex); +} diff --git a/app/src/main/java/com/monke/monkeybook/model/IWebBookModel.java b/app/src/main/java/com/monke/monkeybook/model/IWebBookModel.java new file mode 100644 index 0000000000..0b9066bd73 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/IWebBookModel.java @@ -0,0 +1,39 @@ +package com.monke.monkeybook.model; + +import com.monke.monkeybook.bean.BookContentBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.listener.OnGetChapterListListener; +import java.util.List; +import io.reactivex.Observable; + +public interface IWebBookModel { + /** + * 网络请求并解析书籍信息 + */ + public Observable getBookInfo(final BookShelfBean bookShelfBean); + + /** + * 网络解析图书目录 + */ + public void getChapterList(final BookShelfBean bookShelfBean,OnGetChapterListListener getChapterListListener); + + /** + * 章节缓存 + */ + public Observable getBookContent(final String durChapterUrl, final int durChapterIndex, String tag); + + /** + * 搜索书籍 + */ + public Observable> searchBook(String content, int page,int rankKind); + + /** + * 获取分类书籍 + */ + public Observable> getKindBook(String url,int page); + /** + * 其他站点资源整合搜索 + */ + public Observable> searchOtherBook(String content,int page,String tag); +} diff --git a/app/src/main/java/com/monke/monkeybook/model/IWebContentModel.java b/app/src/main/java/com/monke/monkeybook/model/IWebContentModel.java new file mode 100644 index 0000000000..5ad2bec3dd --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/IWebContentModel.java @@ -0,0 +1,6 @@ +package com.monke.monkeybook.model; + +public interface IWebContentModel { + + public String analyBookcontent(String s,String realUrl) throws Exception; +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/Content17duxsModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/Content17duxsModelImpl.java new file mode 100644 index 0000000000..be9d07f939 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/Content17duxsModelImpl.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class Content17duxsModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.17duxs.com"; + + public static Content17duxsModelImpl getInstance() { + return new Content17duxsModelImpl(); + } + + private Content17duxsModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/Content17kModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/Content17kModelImpl.java new file mode 100644 index 0000000000..ad522536ea --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/Content17kModelImpl.java @@ -0,0 +1,39 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class Content17kModelImpl implements IWebContentModel { + public static final String TAG = "http://www.17k.com"; + + public static Content17kModelImpl getInstance() { + return new Content17kModelImpl(); + } + + private Content17kModelImpl() { + + } + + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + Element all = doc.getElementById("chapterContentWapper"); + List contentEs = all.getAllElements().get(0).textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/Content3dllcModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/Content3dllcModelImpl.java new file mode 100644 index 0000000000..d4b0010b48 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/Content3dllcModelImpl.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class Content3dllcModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.3dllc.cc"; + + public static Content3dllcModelImpl getInstance() { + return new Content3dllcModelImpl(); + } + + private Content3dllcModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/Content44pqModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/Content44pqModelImpl.java new file mode 100644 index 0000000000..a4cd8119f8 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/Content44pqModelImpl.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class Content44pqModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.44pq.net"; + + public static Content44pqModelImpl getInstance() { + return new Content44pqModelImpl(); + } + + private Content44pqModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/Content630bookCCModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/Content630bookCCModelImpl.java new file mode 100644 index 0000000000..55d503e536 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/Content630bookCCModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class Content630bookCCModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.630book.cc"; + + public static Content630bookCCModelImpl getInstance() { + return new Content630bookCCModelImpl(); + } + + private Content630bookCCModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/Content92zwModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/Content92zwModelImpl.java new file mode 100644 index 0000000000..80370fc3cf --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/Content92zwModelImpl.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class Content92zwModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.92zw.la"; + + public static Content92zwModelImpl getInstance() { + return new Content92zwModelImpl(); + } + + private Content92zwModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("contents").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentAszwModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentAszwModelImpl.java new file mode 100644 index 0000000000..3d4b25a549 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentAszwModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentAszwModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.aszw.org"; + + public static ContentAszwModelImpl getInstance() { + return new ContentAszwModelImpl(); + } + + private ContentAszwModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("contents").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentBaishukuModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentBaishukuModelImpl.java new file mode 100644 index 0000000000..27fa9ce4af --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentBaishukuModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentBaishukuModelImpl implements IWebContentModel{ + public static final String TAG = "http://baishuku.com"; + + public static ContentBaishukuModelImpl getInstance() { + return new ContentBaishukuModelImpl(); + } + + private ContentBaishukuModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentBxwx9ModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentBxwx9ModelImpl.java new file mode 100644 index 0000000000..54d1ea94cb --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentBxwx9ModelImpl.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class ContentBxwx9ModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.bxwx9.org"; + + public static ContentBxwx9ModelImpl getInstance() { + return new ContentBxwx9ModelImpl(); + } + + private ContentBxwx9ModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentCommendModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentCommendModelImpl.java new file mode 100644 index 0000000000..243b75bf6f --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentCommendModelImpl.java @@ -0,0 +1,45 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.ErrorAnalyContentManager; +import com.monke.monkeybook.bean.BookContentBean; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentCommendModelImpl { + + public static ContentCommendModelImpl getInstance() { + return new ContentCommendModelImpl(); + } + + private ContentCommendModelImpl() { + + } + public BookContentBean analyBookcontent(BookContentBean bookContentBean, String s, String realUrl) throws Exception { + ErrorAnalyContentManager.getInstance().writeNewErrorUrl(realUrl); + try{ + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + bookContentBean.setDurCapterContent(content.toString()); + }catch (Exception e){ + e.printStackTrace(); + bookContentBean.setDurCapterContent(realUrl.substring(0, realUrl.indexOf('/', 8)) + "站点暂时不支持解析,请反馈给Monke QQ:1105075896,半小时内解决,超级效率的程序员"); + bookContentBean.setRight(false); + } + return bookContentBean; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentDhzwModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentDhzwModelImpl.java new file mode 100644 index 0000000000..db7805134a --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentDhzwModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentDhzwModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.dhzw.org"; + + public static ContentDhzwModelImpl getInstance() { + return new ContentDhzwModelImpl(); + } + + private ContentDhzwModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("BookText").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + contentEs.get(i).text().trim().replaceAll(" ","")); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentEasouModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentEasouModelImpl.java new file mode 100644 index 0000000000..dc8d3f48b3 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentEasouModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentEasouModelImpl implements IWebContentModel { + public static final String TAG = "http://book.easou.com"; + + public static ContentEasouModelImpl getInstance(){ + return new ContentEasouModelImpl(); + } + + private ContentEasouModelImpl(){ + + } + + @Override + public String analyBookcontent(String s, String realUrl) throws Exception{ + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementsByClass("show").get(0).textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentFuheishuModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentFuheishuModelImpl.java new file mode 100644 index 0000000000..7713d593ab --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentFuheishuModelImpl.java @@ -0,0 +1,42 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +/** + * 站点有问题 未完全解析 + */ +public class ContentFuheishuModelImpl implements IWebContentModel{ + public static final String TAG = "http://fuheishu.com"; + + public static ContentFuheishuModelImpl getInstance(){ + return new ContentFuheishuModelImpl(); + } + + private ContentFuheishuModelImpl(){ + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception{ + Document doc = Jsoup.parse(s); + String bookId = realUrl.substring(realUrl.indexOf("/",21)+1,realUrl.indexOf(".html")); + List contentTNs = doc.getElementById("content"+bookId).textNodes(); + StringBuilder stringBuilder = new StringBuilder(); + for(int i=0;i 0) { + stringBuilder.append("\u3000\u3000" + temp); + if (i < contentTNs.size() - 1) { + stringBuilder.append("\r\n"); + } + } + } + return stringBuilder.toString(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentKewaishuModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentKewaishuModelImpl.java new file mode 100644 index 0000000000..208914bfc3 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentKewaishuModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentKewaishuModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.kewaishu.org"; + + public static ContentKewaishuModelImpl getInstance() { + return new ContentKewaishuModelImpl(); + } + + private ContentKewaishuModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").getElementsByTag("p").get(0).textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentLeduwoModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentLeduwoModelImpl.java new file mode 100644 index 0000000000..63ebc72eec --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentLeduwoModelImpl.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class ContentLeduwoModelImpl implements IWebContentModel{ + public static final String TAG = "http://leduwo.com"; + + public static ContentLeduwoModelImpl getInstance() { + return new ContentLeduwoModelImpl(); + } + + private ContentLeduwoModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentLewen8ModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentLewen8ModelImpl.java new file mode 100644 index 0000000000..0f975ed4d5 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentLewen8ModelImpl.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class ContentLewen8ModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.lewen8.com"; + + public static ContentLewen8ModelImpl getInstance() { + return new ContentLewen8ModelImpl(); + } + + private ContentLewen8ModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentPbtxtModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentPbtxtModelImpl.java new file mode 100644 index 0000000000..feb34da550 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentPbtxtModelImpl.java @@ -0,0 +1,37 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class ContentPbtxtModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.pbtxt.com"; + + public static ContentPbtxtModelImpl getInstance(){ + return new ContentPbtxtModelImpl(); + } + + private ContentPbtxtModelImpl(){ + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception{ + Document doc = Jsoup.parse(s); + String bookId = realUrl.substring(realUrl.indexOf("/",21)+1,realUrl.indexOf(".html")); + List contentTNs = doc.getElementById("content"+bookId).textNodes(); + StringBuilder stringBuilder = new StringBuilder(); + for(int i=0;i 0) { + stringBuilder.append("\u3000\u3000" + temp); + if (i < contentTNs.size() - 1) { + stringBuilder.append("\r\n"); + } + } + } + return stringBuilder.toString(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentPpxsModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentPpxsModelImpl.java new file mode 100644 index 0000000000..374fb805c8 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentPpxsModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentPpxsModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.ppxs.net"; + + public static ContentPpxsModelImpl getInstance() { + return new ContentPpxsModelImpl(); + } + + private ContentPpxsModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("booktext").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentQulaModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentQulaModelImpl.java new file mode 100644 index 0000000000..06d5d70004 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentQulaModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentQulaModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.qu.la"; + + public static ContentQulaModelImpl getInstance() { + return new ContentQulaModelImpl(); + } + + private ContentQulaModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentQzreadModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentQzreadModelImpl.java new file mode 100644 index 0000000000..f4ab41e605 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentQzreadModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentQzreadModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.qzread.com"; + + public static ContentQzreadModelImpl getInstance() { + return new ContentQzreadModelImpl(); + } + + private ContentQzreadModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementsByClass("txt").get(0).getElementsByTag("p").get(0).textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentRanwenaModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentRanwenaModelImpl.java new file mode 100644 index 0000000000..fcd94f5c7c --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentRanwenaModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentRanwenaModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.ranwena.com"; + + public static ContentRanwenaModelImpl getInstance() { + return new ContentRanwenaModelImpl(); + } + + private ContentRanwenaModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentShulouModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentShulouModelImpl.java new file mode 100644 index 0000000000..a1e329edcc --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentShulouModelImpl.java @@ -0,0 +1,27 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; + +public class ContentShulouModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.shulou.cc"; + + public static ContentShulouModelImpl getInstance(){ + return new ContentShulouModelImpl(); + } + private ContentShulouModelImpl(){ + + } + + @Override + public String analyBookcontent(String s, String realUrl) throws Exception{ + Document doc = Jsoup.parse(s); + Element contentE = doc.getElementById("content"); + String contentString = contentE.toString(); + contentString = contentString.replaceAll(" ", "").replaceAll("\n", "").replaceAll(" ", "").replaceAll("", "").replaceAll("", "").replaceAll("

","").replaceAll("

", "\r\n\u3000\u3000"); + contentString = "\u3000\u3000" + contentString; + return contentString; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentSnwx8ModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentSnwx8ModelImpl.java new file mode 100644 index 0000000000..1eddf2f7e9 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentSnwx8ModelImpl.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class ContentSnwx8ModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.snwx8.com"; + + public static ContentSnwx8ModelImpl getInstance() { + return new ContentSnwx8ModelImpl(); + } + + private ContentSnwx8ModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("BookText").textNodes(); + StringBuilder content = new StringBuilder(); + for(int i=0;i0){ + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentSuimengModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentSuimengModelImpl.java new file mode 100644 index 0000000000..719dfe9d93 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentSuimengModelImpl.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; + +import java.util.List; + +public class ContentSuimengModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.suimeng.la"; + + public static ContentSuimengModelImpl getInstance() { + return new ContentSuimengModelImpl(); + } + + private ContentSuimengModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("ccontent").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentSyzwwModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentSyzwwModelImpl.java new file mode 100644 index 0000000000..bf7138d43a --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentSyzwwModelImpl.java @@ -0,0 +1,39 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +/** + * 站点有问题 未完全解析 + */ +public class ContentSyzwwModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.syzww.net"; + + public static ContentSyzwwModelImpl getInstance() { + return new ContentSyzwwModelImpl(); + } + + private ContentSyzwwModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentVodtwModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentVodtwModelImpl.java new file mode 100644 index 0000000000..6f34d7ab28 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentVodtwModelImpl.java @@ -0,0 +1,43 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.Elements; + +import java.util.List; + +public class ContentVodtwModelImpl implements IWebContentModel { + public static final String TAG = "http://www.vodtw.com"; + + public static ContentVodtwModelImpl getInstance() { + return new ContentVodtwModelImpl(); + } + + private ContentVodtwModelImpl() { + + } + + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + Element contentE = doc.getElementById("BookText"); + StringBuilder content = new StringBuilder(); + + Elements contentEs = contentE.getElementsByTag("p"); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentWxguanModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentWxguanModelImpl.java new file mode 100644 index 0000000000..39dd395c96 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentWxguanModelImpl.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import java.util.List; + +public class ContentWxguanModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.wxguan.com"; + + public static ContentWxguanModelImpl getInstance() { + return new ContentWxguanModelImpl(); + } + + private ContentWxguanModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentXqingdouCCModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentXqingdouCCModelImpl.java new file mode 100644 index 0000000000..bc8cd276c3 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentXqingdouCCModelImpl.java @@ -0,0 +1,37 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.select.Elements; + +public class ContentXqingdouCCModelImpl implements IWebContentModel { + public static final String TAG = "http://www.xqingdou.cc"; + + public static ContentXqingdouCCModelImpl getInstance() { + return new ContentXqingdouCCModelImpl(); + } + + private ContentXqingdouCCModelImpl() { + + } + + @Override + public String analyBookcontent(String s, String realUrl) throws Exception{ + Document doc = Jsoup.parse(s); + Elements contentEs = doc.getElementById("chapter_content").getElementsByTag("p"); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentXqingdouModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentXqingdouModelImpl.java new file mode 100644 index 0000000000..3602a5204a --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentXqingdouModelImpl.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.select.Elements; + +public class ContentXqingdouModelImpl implements IWebContentModel { + public static final String TAG = "http://www.xqingdou.com"; + + public static ContentXqingdouModelImpl getInstance() { + return new ContentXqingdouModelImpl(); + } + + private ContentXqingdouModelImpl() { + + } + + @Override + public String analyBookcontent(String s, String realUrl) throws Exception{ + Document doc = Jsoup.parse(s); + Elements contentEs = doc.getElementById("chapter_content").getElementsByTag("p"); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentYb3ModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentYb3ModelImpl.java new file mode 100644 index 0000000000..d3043bcc5d --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentYb3ModelImpl.java @@ -0,0 +1,61 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.Elements; + +import java.util.List; + +public class ContentYb3ModelImpl implements IWebContentModel{ + public static final String TAG = "http://www.yb3.cc"; + + public static ContentYb3ModelImpl getInstance() { + return new ContentYb3ModelImpl(); + } + + private ContentYb3ModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + Element contentE = doc.getElementById("content"); + List contentTextNodes = contentE.textNodes(); + StringBuilder content = new StringBuilder(); + if(contentTextNodes!=null && contentTextNodes.size()>0){ + for (int i = 0; i < contentTextNodes.size(); i++) { + if (contentTextNodes.get(i).text().trim().length() > 0) { + content.append("\u3000\u3000" + contentTextNodes.get(i).text().trim()); + if (i < contentTextNodes.size() - 1) { + content.append("\r\n"); + } + } + } + }else{ + Elements contentEs = contentE.children(); + for (int i = 0; i < contentEs.size(); i++) { + if (contentEs.get(i).text().toString().trim().replaceAll(" ","").length() > 0) { + List tempTextNodes = contentEs.get(i).textNodes(); + if(tempTextNodes!=null && tempTextNodes.size()>0){ + for (int j = 0; j < tempTextNodes.size(); j++) { + String temp = tempTextNodes.get(j).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + content.append("\r\n"); + } + } + }else{ + content.append("\u3000\u3000" + contentEs.get(i).text().trim().replaceAll(" ","")); + content.append("\r\n"); + } + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ContentZhulangModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ContentZhulangModelImpl.java new file mode 100644 index 0000000000..85a6db9015 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ContentZhulangModelImpl.java @@ -0,0 +1,39 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.model.IWebContentModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.Elements; + +import java.util.List; + +public class ContentZhulangModelImpl implements IWebContentModel{ + public static final String TAG = "http://book.zhulang.com"; + + public static ContentZhulangModelImpl getInstance() { + return new ContentZhulangModelImpl(); + } + + private ContentZhulangModelImpl() { + + } + @Override + public String analyBookcontent(String s, String realUrl) throws Exception { + Document doc = Jsoup.parse(s); + Elements contentEs = doc.getElementById("read-content").children(); + StringBuilder content = new StringBuilder(); + for (int i = 3; i < contentEs.size()-1; i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ","").replaceAll(" ",""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + return content.toString(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/EasouBookModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/EasouBookModelImpl.java new file mode 100644 index 0000000000..a02ebb9a11 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/EasouBookModelImpl.java @@ -0,0 +1,555 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.basemvplib.impl.BaseModelImpl; +import com.monke.monkeybook.ErrorAnalyContentManager; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookContentBean; +import com.monke.monkeybook.bean.BookInfoBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.ChapterListBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.bean.WebChapterBean; +import com.monke.monkeybook.common.api.IEasouApi; +import com.monke.monkeybook.listener.OnGetChapterListListener; +import com.monke.monkeybook.model.IEasouBookModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.ObservableSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; +import okhttp3.Call; +import okhttp3.Callback; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +public class EasouBookModelImpl extends BaseModelImpl implements IEasouBookModel { + public static final String TAG = "http://book.easou.com"; + + public static EasouBookModelImpl getInstance() { + return new EasouBookModelImpl(); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * 搜索书籍 + */ + @Override + public Observable> searchBook(String content, int page, int rankKind) { + String temp = "/w/searchNovel/" + content + "_" + rankKind + "_" + page + ".html"; + return getRetrofitObject(TAG).create(IEasouApi.class).searchBook(temp).flatMap(new Function>>() { + @Override + public ObservableSource> apply(String s) throws Exception { + return analySearchBook(s); + } + }); + } + + public Observable> analySearchBook(final String s) { + return Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + try { + Document doc = Jsoup.parse(s); + Elements booksE = doc.getElementsByClass("resultContent").get(0).getElementsByTag("li"); + if (null != booksE && booksE.size() > 1) { + List books = new ArrayList(); + for (Element bookItem : booksE) { + SearchBookBean item = new SearchBookBean(); + item.setTag(TAG); + item.setAuthor(bookItem.getElementsByClass("attr").get(0).getElementsByTag("a").get(0).text()); + item.setKind(bookItem.getElementsByClass("attr").get(0).getElementsByTag("a").get(1).text()); + item.setState(bookItem.getElementsByTag("span").get(0).text()); + item.setLastChapter(bookItem.getElementsByClass("lastchapter").get(0).text()); + item.setOrigin(bookItem.getElementsByClass("source").get(0).text().replaceAll("来源:", "")); + item.setName(bookItem.getElementsByClass("name").get(0).getElementsByClass("common").get(0).text()); + item.setNoteUrl(TAG + bookItem.getElementsByClass("name").get(0).getElementsByClass("common").get(0).attr("href")); + item.setCoverUrl(bookItem.getElementsByTag("img").get(0).attr("src")); + books.add(item); + } + e.onNext(books); + } else { + e.onNext(new ArrayList()); + } + } catch (Exception ex) { + ex.printStackTrace(); + e.onNext(new ArrayList()); + } + e.onComplete(); + } + }); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * 网络请求并解析书籍信息 + * return BookShelfBean + */ + @Override + public Observable getBookInfo(final BookShelfBean bookShelfBean) { + return getRetrofitObject(TAG).create(IEasouApi.class).getBookInfo(bookShelfBean.getNoteUrl().replace(TAG, "")).flatMap(new Function>() { + @Override + public ObservableSource apply(String s) throws Exception { + return analyBookInfo(s, bookShelfBean); + } + }); + } + + private Observable analyBookInfo(final String s, final BookShelfBean bookShelfBean) { + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + bookShelfBean.setTag(TAG); + bookShelfBean.setBookInfoBean(analyBookinfo(s, bookShelfBean.getNoteUrl())); + e.onNext(bookShelfBean); + e.onComplete(); + } + }); + } + + private BookInfoBean analyBookinfo(String s, String novelUrl) { + BookInfoBean bookInfoBean = new BookInfoBean(); + bookInfoBean.setNoteUrl(novelUrl); //id + bookInfoBean.setTag(TAG); + Document doc = Jsoup.parse(s); + Element resultE = doc.getElementsByClass("content").get(0); + String coverUrl = resultE.getElementsByClass("imgShow").get(0).getElementsByTag("img").get(0).attr("src"); + bookInfoBean.setCoverUrl(coverUrl.startsWith("http") ? coverUrl : (TAG + coverUrl)); + bookInfoBean.setName(resultE.getElementsByClass("tit").get(1).getElementsByTag("h1").get(0).text()); + bookInfoBean.setAuthor(resultE.getElementsByClass("author").get(0).getElementsByClass("common").get(0).text()); + bookInfoBean.setIntroduce("\u3000\u3000" + resultE.getElementsByClass("desc").get(0).text().trim()); + bookInfoBean.setChapterUrl(TAG + resultE.getElementsByClass("category").get(0).getElementsByTag("a").get(0).attr("href")); + bookInfoBean.setOrigin(resultE.getElementsByClass("attribute").get(0).getElementsByClass("source").get(0).getElementsByClass("t").get(0).text()); + return bookInfoBean; + } + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * 网络解析图书目录 + * return BookShelfBean + */ + @Override + public void getChapterList(final BookShelfBean bookShelfBean, OnGetChapterListListener getChapterListListener) { + getChapterListPage(bookShelfBean, getChapterListListener, 1); + } + + private void getChapterListPage(final BookShelfBean bookShelfBean, final OnGetChapterListListener getChapterListListener, final int page) { + getRetrofitObject(TAG).create(IEasouApi.class).getChapterList(bookShelfBean.getBookInfoBean().getChapterUrl().replace(TAG, "").replace("1_", page + "_")).flatMap(new Function>>() { + @Override + public ObservableSource> apply(String s) throws Exception { + return analyChapterList(s, bookShelfBean, page == 1 ? true : false); + } + }) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver>() { + @Override + public void onNext(WebChapterBean value) { + if (value.getNext()) { + getChapterListPage(value.getData(), getChapterListListener, page + 1); + } else { + if (value.getData().getBookInfoBean().getChapterlist() != null && value.getData().getBookInfoBean().getChapterlist().size() > 0) { + for (int i = 0; i < value.getData().getBookInfoBean().getChapterlist().size(); i++) { + int temp = i; + for (int j = i; j < value.getData().getBookInfoBean().getChapterlist().size(); j++) { + if (value.getData().getBookInfoBean().getChapterlist().get(temp).getDurChapterIndex() > value.getData().getBookInfoBean().getChapterlist().get(j).getDurChapterIndex()) { + temp = j; + } + } + ChapterListBean tempBean = value.getData().getBookInfoBean().getChapterlist().get(i); + value.getData().getBookInfoBean().getChapterlist().set(i, value.getData().getBookInfoBean().getChapterlist().get(temp)); + value.getData().getBookInfoBean().getChapterlist().set(temp, tempBean); + } + for (int i = 0; i < value.getData().getBookInfoBean().getChapterlist().size(); i++) { + value.getData().getBookInfoBean().getChapterlist().get(i).setDurChapterIndex(i); + } + } + if (getChapterListListener != null) { + getChapterListListener.success(value.getData()); + } + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + if (getChapterListListener != null) { + getChapterListListener.error(); + } + } + }); + } + + private Observable> analyChapterList(final String s, final BookShelfBean bookShelfBean, final Boolean isFirstPage) { + return Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + bookShelfBean.setTag(TAG); + WebChapterBean> temp = analyChapterlist(s, bookShelfBean.getNoteUrl(), bookShelfBean.getTag()); + if (isFirstPage) { + bookShelfBean.getBookInfoBean().setChapterlist(temp.getData()); + } else { + bookShelfBean.getBookInfoBean().addChapterlist(temp.getData()); + } + e.onNext(new WebChapterBean(bookShelfBean, temp.getNext())); + e.onComplete(); + } + }); + } + + private WebChapterBean> analyChapterlist(String s, String novelUrl, String chapterUrl) { + Document doc = Jsoup.parse(s); + Element element = doc.getElementsByClass("content").get(0); + Elements chapterlist = element.getElementsByClass("category").get(0).getElementsByTag("li"); + List chapterBeans = new ArrayList(); + for (int i = 0; i < chapterlist.size(); i++) { + ChapterListBean temp = new ChapterListBean(); + temp.setDurChapterUrl(chapterUrl + chapterlist.get(i).getElementsByTag("a").get(0).attr("href")); //id + String name = chapterlist.get(i).getElementsByTag("a").get(0).text(); + setDurChapterData(i, name, temp); + temp.setNoteUrl(novelUrl); + temp.setTag(TAG); + + chapterBeans.add(temp); + } + + Elements nextE = doc.getElementsByClass("pager").get(0).getElementsByClass("next unable"); + Boolean next = (nextE == null || nextE.size() <= 0) ? true : false; + return new WebChapterBean>(chapterBeans, next); + } + + private void setDurChapterData(int i, String name, ChapterListBean temp) { + try { + String regex = "第.{1,7}章"; + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(name); + if (m.find()) { + String indexTemp = m.group(); + indexTemp = indexTemp.replace("第", "").replace("章", "").trim(); + String regex3 = "[0-9]{1,6}"; + Pattern p3 = Pattern.compile(regex3); + Matcher m3 = p3.matcher(indexTemp); + int resultIndex = i; + if (m3.matches()) { + resultIndex = Integer.parseInt(indexTemp); + } else { + resultIndex = parse(indexTemp); + } + temp.setDurChapterIndex(resultIndex); + } else { + String regex2 = "[0-9]{1,6}\\."; + Pattern p2 = Pattern.compile(regex2); + Matcher m2 = p2.matcher(name); + if (m2.find()) { + String indexTemp = m2.group(); + indexTemp = indexTemp.replaceAll("\\.", "").trim(); + int resultIndex = Integer.parseInt(indexTemp); + temp.setDurChapterIndex(resultIndex); + } else { + temp.setDurChapterIndex(i); + } + } + } catch (Exception e) { + e.printStackTrace(); + temp.setDurChapterIndex(i); + }finally { + temp.setDurChapterName(name); + } + } + + public static int parse(String money) { + int result = 0; + char c = 0; + + boolean flag = Pattern.matches("^.*亿.*万.*$", money); + + for (int i = 0; i < money.length(); i++) { + switch (money.charAt(i)) { + case '零': + break; + case '一': + c = 1; + break; + case '二': + c = 2; + break; + case '三': + c = 3; + break; + case '四': + c = 4; + break; + case '五': + c = 5; + break; + case '六': + c = 6; + break; + case '七': + c = 7; + break; + case '八': + c = 8; + break; + case '九': + c = 9; + break; + case '十': + result += (c == 0 ? 10 : c * 10); + c = 0; + break; + case '百': + result += c * 100; + c = 0; + break; + case '千': + result += c * 1000; + c = 0; + break; + case '万': + result = (result + c) * 10000; + c = 0; + break; + case '亿': + if (flag) { + result = (result + c) * 10000; + } else { + result = (result + c) * 100000000; + } + c = 0; + break; + default: + c = 0; + } + + } + if (c != 0) + result += c; + return result; + + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * 章节缓存 + */ + @Override + public Observable getBookContent(final String durChapterUrl, final int durChapterIndex) { + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(final ObservableEmitter e) throws Exception { + OkHttpClient client = clientBuilder.build(); + Request.Builder requestBuilder = new Request.Builder().url(durChapterUrl).method("GET", null); + requestBuilder.addHeader("Accept", "text/html,application/xhtml+xml,application/xml"); + requestBuilder.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3"); + requestBuilder.addHeader("Accept-Charset", "UTF-8"); + requestBuilder.addHeader("Keep-Alive", "300"); + requestBuilder.addHeader("Cache-Control", "no-cache"); + requestBuilder.addHeader("Connection", "Keep-Alive"); + Call mcall = client.newCall(requestBuilder.build()); + mcall.enqueue(new Callback() { + @Override + public void onFailure(Call call, IOException ex) { + ex.printStackTrace(); + if (!e.isDisposed()) { + e.onError(ex); + } + } + + @Override + public void onResponse(Call call, Response response) throws IOException { + String url = response.request().url().toString(); + BookContentBean bookContentBean = new BookContentBean(); + try { + bookContentBean = choiceAnaly(response, url, durChapterUrl, durChapterIndex); + } catch (Exception e) { + e.printStackTrace(); + ErrorAnalyContentManager.getInstance().writeMayByNetError(url); + bookContentBean = new BookContentBean(); + bookContentBean.setDurChapterIndex(durChapterIndex); + bookContentBean.setDurChapterUrl(durChapterUrl); + bookContentBean.setDurCapterContent(url.substring(0, url.indexOf('/', 8)) + "站点服务器异常"); + bookContentBean.setTag(TAG); + bookContentBean.setRight(false); + } + if (!e.isDisposed()) { + e.onNext(bookContentBean); + e.onComplete(); + } + } + }); + } + }); + } + + private BookContentBean choiceAnaly(Response response, String url, String durChapterUrl, int durChapterIndex) throws Exception { + BookContentBean bookContentBean = new BookContentBean(); + bookContentBean.setDurChapterIndex(durChapterIndex); + bookContentBean.setDurChapterUrl(durChapterUrl); + bookContentBean.setTag(TAG); + if (url.contains(ContentEasouModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(ContentEasouModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentShulouModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(ContentShulouModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentPbtxtModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentPbtxtModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentXqingdouModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(ContentXqingdouModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentSnwx8ModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentSnwx8ModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(Content17kModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(Content17kModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(Content92zwModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(Content92zwModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentSuimengModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentSuimengModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentKewaishuModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentKewaishuModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentWxguanModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(ContentWxguanModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentBaishukuModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentBaishukuModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentAszwModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentAszwModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentXqingdouCCModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(ContentXqingdouCCModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentFuheishuModelImpl.TAG)) { + String xml = response.body().string(); + //站点有问题 未完全解析 + bookContentBean.setDurCapterContent(ContentFuheishuModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentSyzwwModelImpl.TAG)) { + String xml = response.body().string(); + //站点有问题 未完全解析 + bookContentBean.setDurCapterContent(ContentSyzwwModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(Content630bookCCModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(Content630bookCCModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentBxwx9ModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentBxwx9ModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(Content44pqModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(Content44pqModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentQzreadModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentQzreadModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentLeduwoModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentLeduwoModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(Content17duxsModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(Content17duxsModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentDhzwModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentDhzwModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentYb3ModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(ContentYb3ModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentZhulangModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(ContentZhulangModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentRanwenaModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(ContentRanwenaModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentPpxsModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GBK")); + bookContentBean.setDurCapterContent(ContentPpxsModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentVodtwModelImpl.TAG)) { + String xml = response.body().source().readString(Charset.forName("GB2312")); + bookContentBean.setDurCapterContent(ContentVodtwModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentQulaModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(ContentQulaModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(ContentLewen8ModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(ContentLewen8ModelImpl.getInstance().analyBookcontent(xml, url)); + } else if (url.contains(Content3dllcModelImpl.TAG)) { + String xml = response.body().string(); + bookContentBean.setDurCapterContent(Content3dllcModelImpl.getInstance().analyBookcontent(xml, url)); + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + else { + byte[] xmlData = response.body().source().readByteArray(); + String xml = new String(xmlData, "UTF-8"); + String charset = "UTF-8"; + try { + Document doc = Jsoup.parse(xml); + String data = doc.getElementsByTag("head").get(0).getElementsByTag("meta").get(0).attr("content").toUpperCase().trim(); + if (data.contains("CHARSET")) { + data = data.substring(data.indexOf("CHARSET=") + 8); + if (data.contains(";")) { + data = data.substring(0, data.indexOf(";")); + } + charset = data; + if (!charset.equals("UTF-8")) { + xml = new String(xmlData, charset); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + bookContentBean = ContentCommendModelImpl.getInstance().analyBookcontent(bookContentBean, xml, url); + } + return bookContentBean; + } + + /* + 测试各个网站目录解析 + */ + public static void main(String[] args) { + EasouBookModelImpl.getInstance().getBookContent("http://www.yb3.cc/5200/3186/7426551.html", 0) + .subscribe(new SimpleObserver() { + @Override + public void onNext(BookContentBean value) { + value.getRight(); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); +// EasouBookModelImpl.getInstance().setDurChapterData(1,"第42章学习",new ChapterListBean()); +// EasouBookModelImpl.getInstance().getLibraryData(null) +// .subscribe(new SimpleObserver() { +// @Override +// public void onNext(LibraryBean value) { +// } +// +// @Override +// public void onError(Throwable e) { +// e.printStackTrace(); +// } +// }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/GxwztvBookModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/GxwztvBookModelImpl.java new file mode 100644 index 0000000000..2737b4942f --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/GxwztvBookModelImpl.java @@ -0,0 +1,355 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.basemvplib.impl.BaseModelImpl; +import com.monke.monkeybook.ErrorAnalyContentManager; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookContentBean; +import com.monke.monkeybook.bean.BookInfoBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.ChapterListBean; +import com.monke.monkeybook.bean.LibraryBean; +import com.monke.monkeybook.bean.LibraryKindBookListBean; +import com.monke.monkeybook.bean.LibraryNewBookBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.bean.WebChapterBean; +import com.monke.monkeybook.cache.ACache; +import com.monke.monkeybook.common.api.IGxwztvApi; +import com.monke.monkeybook.listener.OnGetChapterListListener; +import com.monke.monkeybook.model.IGxwztvBookModel; +import com.monke.monkeybook.presenter.impl.LibraryPresenterImpl; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.Elements; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.ObservableSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + +public class GxwztvBookModelImpl extends BaseModelImpl implements IGxwztvBookModel { + public static final String TAG = "http://www.gxwztv.com"; + + public static GxwztvBookModelImpl getInstance() { + return new GxwztvBookModelImpl(); + } + + + /** + * 获取主页信息 + */ + @Override + public Observable getLibraryData(final ACache aCache) { + return getRetrofitObject(TAG).create(IGxwztvApi.class).getLibraryData("").flatMap(new Function>() { + @Override + public ObservableSource apply(String s) throws Exception { + if (s != null && s.length() > 0 && aCache != null) { + aCache.put(LibraryPresenterImpl.LIBRARY_CACHE_KEY, s); + } + return analyLibraryData(s); + } + }); + } + + /** + * 解析主页数据 + */ + @Override + public Observable analyLibraryData(final String data) { + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + LibraryBean result = new LibraryBean(); + Document doc = Jsoup.parse(data); + Element contentE = doc.getElementsByClass("container").get(0); + //解析最新书籍 + Elements newBookEs = contentE.getElementsByClass("list-group-item text-nowrap modal-open"); + List libraryNewBooks = new ArrayList(); + for (int i = 0; i < newBookEs.size(); i++) { + Element itemE = newBookEs.get(i).getElementsByTag("a").get(0); + LibraryNewBookBean item = new LibraryNewBookBean(itemE.text(), TAG + itemE.attr("href"), TAG, "gxwztv.com"); + libraryNewBooks.add(item); + } + result.setLibraryNewBooks(libraryNewBooks); + ////////////////////////////////////////////////////////////////////// + List kindBooks = new ArrayList(); + //解析男频女频 + Elements hotEs = contentE.getElementsByClass("col-xs-12"); + for (int i = 1; i < hotEs.size(); i++) { + LibraryKindBookListBean kindItem = new LibraryKindBookListBean(); + kindItem.setKindName(hotEs.get(i).getElementsByClass("panel-title").get(0).text()); + Elements bookEs = hotEs.get(i).getElementsByClass("panel-body").get(0).getElementsByTag("li"); + + List books = new ArrayList(); + for (int j = 0; j < bookEs.size(); j++) { + SearchBookBean searchBookBean = new SearchBookBean(); + searchBookBean.setOrigin("gxwztv.com"); + searchBookBean.setTag(TAG); + searchBookBean.setName(bookEs.get(j).getElementsByTag("span").get(0).text()); + searchBookBean.setNoteUrl(TAG + bookEs.get(j).getElementsByTag("a").get(0).attr("href")); + searchBookBean.setCoverUrl(bookEs.get(j).getElementsByTag("img").get(0).attr("src")); + books.add(searchBookBean); + } + kindItem.setBooks(books); + kindBooks.add(kindItem); + } + //解析部分分类推荐 + Elements kindEs = contentE.getElementsByClass("panel panel-info index-category-qk"); + for (int i = 0; i < kindEs.size(); i++) { + LibraryKindBookListBean kindItem = new LibraryKindBookListBean(); + kindItem.setKindName(kindEs.get(i).getElementsByClass("panel-title").get(0).text()); + kindItem.setKindUrl(TAG + kindEs.get(i).getElementsByClass("listMore").get(0).getElementsByTag("a").get(0).attr("href")); + + List books = new ArrayList(); + Element firstBookE = kindEs.get(i).getElementsByTag("dl").get(0); + SearchBookBean firstBook = new SearchBookBean(); + firstBook.setTag(TAG); + firstBook.setOrigin("gxwztv.com"); + firstBook.setName(firstBookE.getElementsByTag("a").get(1).text()); + firstBook.setNoteUrl(TAG + firstBookE.getElementsByTag("a").get(0).attr("href")); + firstBook.setCoverUrl(firstBookE.getElementsByTag("a").get(0).getElementsByTag("img").get(0).attr("src")); + firstBook.setKind(kindItem.getKindName()); + books.add(firstBook); + + Elements otherBookEs = kindEs.get(i).getElementsByClass("book_textList").get(0).getElementsByTag("li"); + for (int j = 0; j < otherBookEs.size(); j++) { + SearchBookBean item = new SearchBookBean(); + item.setTag(TAG); + item.setOrigin("gxwztv.com"); + item.setKind(kindItem.getKindName()); + item.setNoteUrl(TAG+otherBookEs.get(j).getElementsByTag("a").get(0).attr("href")); + item.setName(otherBookEs.get(j).getElementsByTag("a").get(0).text()); + books.add(item); + } + kindItem.setBooks(books); + kindBooks.add(kindItem); + } + ////////////// + result.setKindBooks(kindBooks); + e.onNext(result); + e.onComplete(); + } + }); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override + public Observable> searchBook(String content, int page) { + return getRetrofitObject(TAG).create(IGxwztvApi.class).searchBook(content, page).flatMap(new Function>>() { + @Override + public ObservableSource> apply(String s) throws Exception { + return analySearchBook(s); + } + }); + } + + public Observable> analySearchBook(final String s) { + return Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + try { + Document doc = Jsoup.parse(s); + Elements booksE = doc.getElementById("novel-list").getElementsByClass("list-group-item clearfix"); + if (null != booksE && booksE.size() >= 2) { + List books = new ArrayList(); + for (int i = 1; i < booksE.size(); i++) { + SearchBookBean item = new SearchBookBean(); + item.setTag(TAG); + item.setAuthor(booksE.get(i).getElementsByClass("col-xs-2").get(0).text()); + item.setKind(booksE.get(i).getElementsByClass("col-xs-1").get(0).text()); + item.setLastChapter(booksE.get(i).getElementsByClass("col-xs-4").get(0).getElementsByTag("a").get(0).text()); + item.setOrigin("gxwztv.com"); + item.setName(booksE.get(i).getElementsByClass("col-xs-3").get(0).getElementsByTag("a").get(0).text()); + item.setNoteUrl(TAG + booksE.get(i).getElementsByClass("col-xs-3").get(0).getElementsByTag("a").get(0).attr("href")); + item.setCoverUrl("noimage"); + books.add(item); + } + e.onNext(books); + } else { + e.onNext(new ArrayList()); + } + } catch (Exception ex) { + ex.printStackTrace(); + e.onNext(new ArrayList()); + } + e.onComplete(); + } + }); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override + public Observable getBookInfo(final BookShelfBean bookShelfBean) { + return getRetrofitObject(TAG).create(IGxwztvApi.class).getBookInfo(bookShelfBean.getNoteUrl().replace(TAG, "")).flatMap(new Function>() { + @Override + public ObservableSource apply(String s) throws Exception { + return analyBookInfo(s, bookShelfBean); + } + }); + } + + private Observable analyBookInfo(final String s, final BookShelfBean bookShelfBean) { + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + bookShelfBean.setTag(TAG); + bookShelfBean.setBookInfoBean(analyBookinfo(s, bookShelfBean.getNoteUrl())); + e.onNext(bookShelfBean); + e.onComplete(); + } + }); + } + + private BookInfoBean analyBookinfo(String s, String novelUrl) { + BookInfoBean bookInfoBean = new BookInfoBean(); + bookInfoBean.setNoteUrl(novelUrl); //id + bookInfoBean.setTag(TAG); + Document doc = Jsoup.parse(s); + Element resultE = doc.getElementsByClass("panel panel-warning").get(0); + bookInfoBean.setCoverUrl(resultE.getElementsByClass("panel-body").get(0).getElementsByClass("img-thumbnail").get(0).attr("src")); + bookInfoBean.setName(resultE.getElementsByClass("active").get(0).text()); + bookInfoBean.setAuthor(resultE.getElementsByClass("col-xs-12 list-group-item no-border").get(0).getElementsByTag("small").get(0).text()); + Element introduceE = resultE.getElementsByClass("panel panel-default mt20").get(0); + String introduce = ""; + if (introduceE.getElementById("all") != null) { + introduce = introduceE.getElementById("all").text().replace("[收起]", ""); + } else { + introduce = introduceE.getElementById("shot").text(); + } + bookInfoBean.setIntroduce("\u3000\u3000" + introduce); + bookInfoBean.setChapterUrl(TAG + resultE.getElementsByClass("list-group-item tac").get(0).getElementsByTag("a").get(0).attr("href")); + bookInfoBean.setOrigin("gxwztv.com"); + return bookInfoBean; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override + public void getChapterList(final BookShelfBean bookShelfBean, final OnGetChapterListListener getChapterListListener) { + getRetrofitObject(TAG).create(IGxwztvApi.class).getChapterList(bookShelfBean.getBookInfoBean().getChapterUrl().replace(TAG, "")).flatMap(new Function>>() { + @Override + public ObservableSource> apply(String s) throws Exception { + return analyChapterList(s, bookShelfBean); + } + }) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver>() { + @Override + public void onNext(WebChapterBean value) { + if (getChapterListListener != null) { + getChapterListListener.success(value.getData()); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + if (getChapterListListener != null) { + getChapterListListener.error(); + } + } + }); + } + + private Observable> analyChapterList(final String s, final BookShelfBean bookShelfBean) { + return Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + bookShelfBean.setTag(TAG); + WebChapterBean> temp = analyChapterlist(s, bookShelfBean.getNoteUrl()); + bookShelfBean.getBookInfoBean().setChapterlist(temp.getData()); + e.onNext(new WebChapterBean(bookShelfBean, temp.getNext())); + e.onComplete(); + } + }); + } + + private WebChapterBean> analyChapterlist(String s, String novelUrl) { + Document doc = Jsoup.parse(s); + Elements chapterlist = doc.getElementById("chapters-list").getElementsByTag("a"); + List chapterBeans = new ArrayList(); + for (int i = 0; i < chapterlist.size(); i++) { + ChapterListBean temp = new ChapterListBean(); + temp.setDurChapterUrl(TAG + chapterlist.get(i).attr("href")); //id + temp.setDurChapterIndex(i); + temp.setDurChapterName(chapterlist.get(i).text()); + temp.setNoteUrl(novelUrl); + temp.setTag(TAG); + + chapterBeans.add(temp); + } + Boolean next = false; + return new WebChapterBean>(chapterBeans, next); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override + public Observable getBookContent(final String durChapterUrl, final int durChapterIndex) { + return getRetrofitObject(TAG).create(IGxwztvApi.class).getBookContent(durChapterUrl.replace(TAG, "")).flatMap(new Function>() { + @Override + public ObservableSource apply(String s) throws Exception { + return analyBookContent(s, durChapterUrl, durChapterIndex); + } + }); + } + + private Observable analyBookContent(final String s, final String durChapterUrl, final int durChapterIndex) { + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + BookContentBean bookContentBean = new BookContentBean(); + bookContentBean.setDurChapterIndex(durChapterIndex); + bookContentBean.setDurChapterUrl(durChapterUrl); + bookContentBean.setTag(TAG); + try { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("txtContent").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ", "").replaceAll(" ", ""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + bookContentBean.setDurCapterContent(content.toString()); + bookContentBean.setRight(true); + } catch (Exception ex) { + ex.printStackTrace(); + ErrorAnalyContentManager.getInstance().writeNewErrorUrl(durChapterUrl); + bookContentBean.setDurCapterContent(durChapterUrl.substring(0, durChapterUrl.indexOf('/', 8)) + "站点暂时不支持解析,请反馈给Monke QQ:1105075896,半小时内解决,超级效率的程序员"); + bookContentBean.setRight(false); + } + e.onNext(bookContentBean); + e.onComplete(); + } + }); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * 获取分类书籍 + */ + @Override + public Observable> getKindBook(String url, int page) { + url = url + page + ".htm"; + return getRetrofitObject(GxwztvBookModelImpl.TAG).create(IGxwztvApi.class).getKindBooks(url.replace(GxwztvBookModelImpl.TAG, "")).flatMap(new Function>>() { + @Override + public ObservableSource> apply(String s) throws Exception { + return analySearchBook(s); + } + }); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/ImportBookModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/ImportBookModelImpl.java new file mode 100644 index 0000000000..56ee5f9661 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/ImportBookModelImpl.java @@ -0,0 +1,184 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.basemvplib.impl.BaseModelImpl; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.ChapterListBean; +import com.monke.monkeybook.bean.LocBookShelfBean; +import com.monke.monkeybook.dao.BookInfoBeanDao; +import com.monke.monkeybook.dao.BookShelfBeanDao; +import com.monke.monkeybook.dao.ChapterListBeanDao; +import com.monke.monkeybook.dao.DbHelper; +import com.monke.monkeybook.model.IImportBookModel; +import org.mozilla.universalchardet.UniversalDetector; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; + +public class ImportBookModelImpl extends BaseModelImpl implements IImportBookModel { + + public static ImportBookModelImpl getInstance() { + return new ImportBookModelImpl(); + } + + @Override + public Observable importBook(final File book) { + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + FileInputStream in = new FileInputStream(book); + byte[] buffer = new byte[2048]; + int len; + while ((len = in.read(buffer, 0, 2048)) != -1) { + md.update(buffer, 0, len); + } + in.close(); + in = null; + + String md5 = new BigInteger(1, md.digest()).toString(16); + BookShelfBean bookShelfBean = null; + List temp = DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().queryBuilder().where(BookShelfBeanDao.Properties.NoteUrl.eq(md5)).build().list(); + Boolean isNew = true; + if (temp!=null && temp.size()>0) { + isNew = false; + bookShelfBean = temp.get(0); + bookShelfBean.setBookInfoBean(DbHelper.getInstance().getmDaoSession().getBookInfoBeanDao().queryBuilder().where(BookInfoBeanDao.Properties.NoteUrl.eq(bookShelfBean.getNoteUrl())).build().list().get(0)); + } else { + bookShelfBean = new BookShelfBean(); + bookShelfBean.setFinalDate(System.currentTimeMillis()); + bookShelfBean.setDurChapter(0); + bookShelfBean.setDurChapterPage(0); + bookShelfBean.setTag(BookShelfBean.LOCAL_TAG); + bookShelfBean.setNoteUrl(md5); + + bookShelfBean.getBookInfoBean().setAuthor("佚名"); + bookShelfBean.getBookInfoBean().setName(book.getName().replace(".txt", "").replace(".TXT", "")); + bookShelfBean.getBookInfoBean().setFinalRefreshData(System.currentTimeMillis()); + bookShelfBean.getBookInfoBean().setCoverUrl(""); + bookShelfBean.getBookInfoBean().setNoteUrl(md5); + bookShelfBean.getBookInfoBean().setTag(BookShelfBean.LOCAL_TAG); + + saveChapter(book, md5); + DbHelper.getInstance().getmDaoSession().getBookInfoBeanDao().insertOrReplace(bookShelfBean.getBookInfoBean()); + DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().insertOrReplace(bookShelfBean); + } + bookShelfBean.getBookInfoBean().setChapterlist(DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().queryBuilder().where(ChapterListBeanDao.Properties.NoteUrl.eq(bookShelfBean.getNoteUrl())).orderAsc(ChapterListBeanDao.Properties.DurChapterIndex).build().list()); + e.onNext(new LocBookShelfBean(isNew,bookShelfBean)); + e.onComplete(); + } + }); + } + + private Boolean isAdded(BookShelfBean temp, List shelfs) { + if (shelfs == null || shelfs.size() == 0) { + return false; + } else { + int a = 0; + for (int i = 0; i < shelfs.size(); i++) { + if (temp.getNoteUrl().equals(shelfs.get(i).getNoteUrl())) { + break; + } else { + a++; + } + } + if (a == shelfs.size()) { + return false; + } else + return true; + } + } + + private void saveChapter(File book, String md5) throws IOException { + String regex = "第.{1,7}章.{0,}"; + + String encoding; + + FileInputStream fis = new FileInputStream(book); + byte[] buf = new byte[4096]; + UniversalDetector detector = new UniversalDetector(null); + int nread; + while ((nread = fis.read(buf)) > 0 && !detector.isDone()) { + detector.handleData(buf, 0, nread); + } + detector.dataEnd(); + encoding = detector.getDetectedCharset(); + if (encoding == null || encoding.length() == 0) + encoding = "utf-8"; + fis.close(); + fis = null; + + int chapterPageIndex = 0; + String title = null; + StringBuilder contentBuilder = new StringBuilder(); + fis = new FileInputStream(book); + InputStreamReader inputreader = new InputStreamReader(fis, encoding); + BufferedReader buffreader = new BufferedReader(inputreader); + String line; + while ((line = buffreader.readLine()) != null) { + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(line); + if (m.find()) { + String temp = line.trim().substring(0,line.trim().indexOf("第")); + if(temp!= null && temp.trim().length()>0){ + contentBuilder.append(temp); + } + if (contentBuilder.toString().length() > 0) { + if(contentBuilder.toString().replaceAll(" ","").trim().length()>0){ + saveDurChapterContent(md5, chapterPageIndex, title, contentBuilder.toString()); + chapterPageIndex++; + } + contentBuilder.delete(0, contentBuilder.length()); + } + title = line.trim().substring(line.trim().indexOf("第")); + } else { + if (line.trim().length() == 0) { + if (contentBuilder.length() > 0) { + contentBuilder.append("\r\n\u3000\u3000"); + } else { + contentBuilder.append("\r\u3000\u3000"); + } + } else { + contentBuilder.append(line); + if (title == null) { + title = line.trim(); + } + } + } + } + if (contentBuilder.length() > 0) { + saveDurChapterContent(md5, chapterPageIndex, title, contentBuilder.toString()); + contentBuilder.delete(0, contentBuilder.length()); + title = null; + } + buffreader.close(); + inputreader.close(); + fis.close(); + fis = null; + } + + private void saveDurChapterContent(String md5, int chapterPageIndex, String name, String content) { + ChapterListBean chapterListBean = new ChapterListBean(); + chapterListBean.setNoteUrl(md5); + chapterListBean.setDurChapterIndex(chapterPageIndex); + chapterListBean.setTag(BookShelfBean.LOCAL_TAG); + chapterListBean.setDurChapterUrl(md5 + "_" + chapterPageIndex); + chapterListBean.setDurChapterName(name); + chapterListBean.getBookContentBean().setDurChapterUrl(chapterListBean.getDurChapterUrl()); + chapterListBean.getBookContentBean().setTag(BookShelfBean.LOCAL_TAG); + chapterListBean.getBookContentBean().setDurChapterIndex(chapterListBean.getDurChapterIndex()); + chapterListBean.getBookContentBean().setDurCapterContent(content); + + DbHelper.getInstance().getmDaoSession().getBookContentBeanDao().insertOrReplace(chapterListBean.getBookContentBean()); + DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().insertOrReplace(chapterListBean); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/LingdiankanshuStationBookModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/LingdiankanshuStationBookModelImpl.java new file mode 100644 index 0000000000..936bfca940 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/LingdiankanshuStationBookModelImpl.java @@ -0,0 +1,247 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.basemvplib.impl.BaseModelImpl; +import com.monke.monkeybook.ErrorAnalyContentManager; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookContentBean; +import com.monke.monkeybook.bean.BookInfoBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.ChapterListBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.bean.WebChapterBean; +import com.monke.monkeybook.common.api.ILingdiankanshuApi; +import com.monke.monkeybook.listener.OnGetChapterListListener; +import com.monke.monkeybook.model.IStationBookModel; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.TextNode; +import org.jsoup.select.Elements; + +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.ObservableSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + +public class LingdiankanshuStationBookModelImpl extends BaseModelImpl implements IStationBookModel { + public static final String TAG = "http://www.lingdiankanshu.co"; + + public static LingdiankanshuStationBookModelImpl getInstance() { + return new LingdiankanshuStationBookModelImpl(); + } + + @Override + public Observable> searchBook(String content, int page) { + return getRetrofitObject("http://zhannei.baidu.com").create(ILingdiankanshuApi.class).searchBook(content, page - 1, "16865089933227718744").flatMap(new Function>>() { + @Override + public ObservableSource> apply(String s) throws Exception { + return analySearchBook(s); + } + }); + } + + public Observable> analySearchBook(final String s) { + return Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + try { + Document doc = Jsoup.parse(s); + Elements booksE = doc.getElementsByClass("result-list").get(0).getElementsByClass("result-item result-game-item"); + if (null != booksE && booksE.size() > 1) { + List books = new ArrayList(); + for (int i = 0; i < booksE.size(); i++) { + SearchBookBean item = new SearchBookBean(); + item.setTag(TAG); + item.setAuthor(booksE.get(i).getElementsByClass("result-game-item-info").get(0).getElementsByClass("result-game-item-info-tag").get(0).getElementsByTag("span").get(1).text()); + item.setKind(booksE.get(i).getElementsByClass("result-game-item-info").get(0).getElementsByClass("result-game-item-info-tag").get(1).getElementsByTag("span").get(1).text()); +// item.setState(); + item.setLastChapter(booksE.get(i).getElementsByClass("result-game-item-info").get(0).getElementsByClass("result-game-item-info-tag").get(3).getElementsByTag("a").get(0).text()); + item.setOrigin("lingdiankanshu.co"); + item.setName(booksE.get(i).getElementsByClass("result-item-title result-game-item-title").get(0).getElementsByTag("a").get(0).text()); + item.setNoteUrl(booksE.get(i).getElementsByClass("result-item-title result-game-item-title").get(0).getElementsByTag("a").get(0).attr("href")); + item.setCoverUrl(booksE.get(i).getElementsByTag("img").get(0).attr("src")); + books.add(item); + } + e.onNext(books); + } else { + e.onNext(new ArrayList()); + } + } catch (Exception ex) { + ex.printStackTrace(); + e.onNext(new ArrayList()); + } + e.onComplete(); + } + }); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override + public Observable getBookInfo(final BookShelfBean bookShelfBean) { + return getRetrofitObject(TAG).create(ILingdiankanshuApi.class).getBookInfo(bookShelfBean.getNoteUrl().replace(TAG, "")).flatMap(new Function>() { + @Override + public ObservableSource apply(String s) throws Exception { + return analyBookInfo(s, bookShelfBean); + } + }); + } + + private Observable analyBookInfo(final String s, final BookShelfBean bookShelfBean) { + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + bookShelfBean.setTag(TAG); + bookShelfBean.setBookInfoBean(analyBookinfo(s, bookShelfBean.getNoteUrl())); + e.onNext(bookShelfBean); + e.onComplete(); + } + }); + } + + private BookInfoBean analyBookinfo(String s, String novelUrl) { + BookInfoBean bookInfoBean = new BookInfoBean(); + bookInfoBean.setNoteUrl(novelUrl); //id + bookInfoBean.setTag(TAG); + Document doc = Jsoup.parse(s); + Element resultE = doc.getElementsByClass("box_con").get(0); + bookInfoBean.setCoverUrl(resultE.getElementById("fmimg").getElementsByTag("img").get(0).attr("src")); + bookInfoBean.setName(resultE.getElementById("info").getElementsByTag("h1").get(0).text()); + String author = resultE.getElementById("info").getElementsByTag("p").get(0).text().toString().trim(); + author = author.replace(" ", "").replace("  ", "").replace("作者:", ""); + bookInfoBean.setAuthor(author); + + List contentEs = resultE.getElementById("intro").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ", "").replaceAll(" ", ""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + + bookInfoBean.setIntroduce(content.toString()); + bookInfoBean.setChapterUrl(novelUrl); + bookInfoBean.setOrigin("gxwztv.com"); + return bookInfoBean; + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override + public void getChapterList(final BookShelfBean bookShelfBean, final OnGetChapterListListener getChapterListListener) { + getRetrofitObject(TAG).create(ILingdiankanshuApi.class).getChapterList(bookShelfBean.getBookInfoBean().getChapterUrl().replace(TAG, "")).flatMap(new Function>>() { + @Override + public ObservableSource> apply(String s) throws Exception { + return analyChapterList(s, bookShelfBean); + } + }) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver>() { + @Override + public void onNext(WebChapterBean value) { + if (getChapterListListener != null) { + getChapterListListener.success(value.getData()); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + if (getChapterListListener != null) { + getChapterListListener.error(); + } + } + }); + } + + private Observable> analyChapterList(final String s, final BookShelfBean bookShelfBean) { + return Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + bookShelfBean.setTag(TAG); + WebChapterBean> temp = analyChapterlist(s, bookShelfBean.getNoteUrl()); + bookShelfBean.getBookInfoBean().setChapterlist(temp.getData()); + e.onNext(new WebChapterBean(bookShelfBean, temp.getNext())); + e.onComplete(); + } + }); + } + + private WebChapterBean> analyChapterlist(String s, String novelUrl) { + Document doc = Jsoup.parse(s); + Elements chapterlist = doc.getElementById("list").getElementsByTag("dd"); + List chapterBeans = new ArrayList(); + for (int i = 0; i < chapterlist.size(); i++) { + ChapterListBean temp = new ChapterListBean(); + temp.setDurChapterUrl(novelUrl + chapterlist.get(i).getElementsByTag("a").get(0).attr("href")); //id + temp.setDurChapterIndex(i); + temp.setDurChapterName(chapterlist.get(i).getElementsByTag("a").get(0).text()); + temp.setNoteUrl(novelUrl); + temp.setTag(TAG); + + chapterBeans.add(temp); + } + Boolean next = false; + return new WebChapterBean>(chapterBeans, next); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + @Override + public Observable getBookContent(final String durChapterUrl, final int durChapterIndex) { + return getRetrofitObject(TAG).create(ILingdiankanshuApi.class).getBookContent(durChapterUrl.replace(TAG, "")).flatMap(new Function>() { + @Override + public ObservableSource apply(String s) throws Exception { + return analyBookContent(s, durChapterUrl, durChapterIndex); + } + }); + } + + private Observable analyBookContent(final String s, final String durChapterUrl, final int durChapterIndex) { + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + BookContentBean bookContentBean = new BookContentBean(); + bookContentBean.setDurChapterIndex(durChapterIndex); + bookContentBean.setDurChapterUrl(durChapterUrl); + bookContentBean.setTag(TAG); + try { + Document doc = Jsoup.parse(s); + List contentEs = doc.getElementById("content").textNodes(); + StringBuilder content = new StringBuilder(); + for (int i = 0; i < contentEs.size(); i++) { + String temp = contentEs.get(i).text().trim(); + temp = temp.replaceAll(" ", "").replaceAll(" ", ""); + if (temp.length() > 0) { + content.append("\u3000\u3000" + temp); + if (i < contentEs.size() - 1) { + content.append("\r\n"); + } + } + } + bookContentBean.setDurCapterContent(content.toString()); + bookContentBean.setRight(true); + } catch (Exception ex) { + ex.printStackTrace(); + ErrorAnalyContentManager.getInstance().writeNewErrorUrl(durChapterUrl); + bookContentBean.setDurCapterContent(durChapterUrl.substring(0, durChapterUrl.indexOf('/', 8)) + "站点暂时不支持解析,请反馈给Monke QQ:1105075896,半小时内解决,超级效率的程序员"); + bookContentBean.setRight(false); + } + e.onNext(bookContentBean); + e.onComplete(); + } + }); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// +} diff --git a/app/src/main/java/com/monke/monkeybook/model/impl/WebBookModelImpl.java b/app/src/main/java/com/monke/monkeybook/model/impl/WebBookModelImpl.java new file mode 100644 index 0000000000..c8acb3df53 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/model/impl/WebBookModelImpl.java @@ -0,0 +1,130 @@ +package com.monke.monkeybook.model.impl; + +import com.monke.monkeybook.bean.BookContentBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.listener.OnGetChapterListListener; +import com.monke.monkeybook.model.IWebBookModel; +import java.util.ArrayList; +import java.util.List; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; + +public class WebBookModelImpl implements IWebBookModel { + + public static WebBookModelImpl getInstance() { + return new WebBookModelImpl(); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * 网络请求并解析书籍信息 + * return BookShelfBean + */ + @Override + public Observable getBookInfo(BookShelfBean bookShelfBean) { + if (bookShelfBean.getTag().equals(EasouBookModelImpl.TAG)) { + return EasouBookModelImpl.getInstance().getBookInfo(bookShelfBean); + } + else if(bookShelfBean.getTag().equals(GxwztvBookModelImpl.TAG)){ + return GxwztvBookModelImpl.getInstance().getBookInfo(bookShelfBean); + } + else if(bookShelfBean.getTag().equals(LingdiankanshuStationBookModelImpl.TAG)){ + return LingdiankanshuStationBookModelImpl.getInstance().getBookInfo(bookShelfBean); + } + else { + return null; + } + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * 网络解析图书目录 + * return BookShelfBean + */ + @Override + public void getChapterList(final BookShelfBean bookShelfBean, OnGetChapterListListener getChapterListListener) { + if (bookShelfBean.getTag().equals(EasouBookModelImpl.TAG)) { + EasouBookModelImpl.getInstance().getChapterList(bookShelfBean, getChapterListListener); + } + else if(bookShelfBean.getTag().equals(GxwztvBookModelImpl.TAG)){ + GxwztvBookModelImpl.getInstance().getChapterList(bookShelfBean, getChapterListListener); + } + else if(bookShelfBean.getTag().equals(LingdiankanshuStationBookModelImpl.TAG)){ + LingdiankanshuStationBookModelImpl.getInstance().getChapterList(bookShelfBean, getChapterListListener); + } + else{ + if(getChapterListListener!=null) + getChapterListListener.success(bookShelfBean); + } + } + + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * 章节缓存 + */ + @Override + public Observable getBookContent(String durChapterUrl, int durChapterIndex, String tag) { + if (tag.equals(EasouBookModelImpl.TAG)) { + return EasouBookModelImpl.getInstance().getBookContent(durChapterUrl, durChapterIndex); + } + else if(tag.equals(GxwztvBookModelImpl.TAG)){ + return GxwztvBookModelImpl.getInstance().getBookContent(durChapterUrl, durChapterIndex); + } + else if(tag.equals(LingdiankanshuStationBookModelImpl.TAG)){ + return LingdiankanshuStationBookModelImpl.getInstance().getBookContent(durChapterUrl, durChapterIndex); + } + else + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + e.onNext(new BookContentBean()); + e.onComplete(); + } + }); + } + + /** + * 其他站点集合搜索 + */ + @Override + public Observable> searchOtherBook(String content,int page,String tag){ + if(tag.equals(EasouBookModelImpl.TAG)){ + return EasouBookModelImpl.getInstance().searchBook(content, page, 0); + } + else if(tag.equals(GxwztvBookModelImpl.TAG)){ + return GxwztvBookModelImpl.getInstance().searchBook(content, page); + } + else if(tag.equals(LingdiankanshuStationBookModelImpl.TAG)){ + return LingdiankanshuStationBookModelImpl.getInstance().searchBook(content, page); + } + else{ + return Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + e.onNext(new ArrayList()); + e.onComplete(); + } + }); + } + } + + /** + * 搜索书籍 //专用 + */ + @Override + public Observable> searchBook(String content, int page,int rankKind) { + return EasouBookModelImpl.getInstance().searchBook(content, page, rankKind); + } + /** + * 获取分类书籍 + */ + @Override + public Observable> getKindBook(String url,int page) { + return GxwztvBookModelImpl.getInstance().getKindBook(url,page); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/IBookDetailPresenter.java b/app/src/main/java/com/monke/monkeybook/presenter/IBookDetailPresenter.java new file mode 100644 index 0000000000..12b1d47b2e --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/IBookDetailPresenter.java @@ -0,0 +1,22 @@ +package com.monke.monkeybook.presenter; + +import com.monke.basemvplib.IPresenter; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.SearchBookBean; + +public interface IBookDetailPresenter extends IPresenter{ + + public int getOpenfrom(); + + public SearchBookBean getSearchBook(); + + public BookShelfBean getBookShelf(); + + public Boolean getInBookShelf(); + + public void getBookShelfInfo(); + + public void addToBookShelf(); + + public void removeFromBookShelf(); +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/IBookReadPresenter.java b/app/src/main/java/com/monke/monkeybook/presenter/IBookReadPresenter.java new file mode 100644 index 0000000000..2982d643b3 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/IBookReadPresenter.java @@ -0,0 +1,36 @@ +package com.monke.monkeybook.presenter; + +import android.app.Activity; +import android.content.Intent; + +import com.monke.basemvplib.IPresenter; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.presenter.impl.ReadBookPresenterImpl; +import com.monke.monkeybook.widget.contentswitchview.BookContentView; + +public interface IBookReadPresenter extends IPresenter{ + + public int getOpen_from(); + + public BookShelfBean getBookShelf(); + + public void initContent(); + + public void loadContent(BookContentView bookContentView,long bookTag, final int chapterIndex, final int page); + + public void updateProgress(int chapterIndex, int pageIndex); + + public void saveProgress(); + + public String getChapterTitle(int chapterIndex); + + public void setPageLineCount(int pageLineCount); + + public void addToShelf(final ReadBookPresenterImpl.OnAddListner addListner); + + public Boolean getAdd(); + + public void initData(Activity activity); + + public void openBookFromOther(Activity activity); +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/IChoiceBookPresenter.java b/app/src/main/java/com/monke/monkeybook/presenter/IChoiceBookPresenter.java new file mode 100644 index 0000000000..cfd2b875f0 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/IChoiceBookPresenter.java @@ -0,0 +1,17 @@ +package com.monke.monkeybook.presenter; + +import com.monke.basemvplib.IPresenter; +import com.monke.monkeybook.bean.SearchBookBean; + +public interface IChoiceBookPresenter extends IPresenter{ + + public int getPage(); + + public void initPage(); + + public void toSearchBooks(String key); + + public void addBookToShelf(final SearchBookBean searchBookBean); + + public String getTitle(); +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/presenter/IImportBookPresenter.java b/app/src/main/java/com/monke/monkeybook/presenter/IImportBookPresenter.java new file mode 100644 index 0000000000..bc06a7ff9f --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/IImportBookPresenter.java @@ -0,0 +1,12 @@ +package com.monke.monkeybook.presenter; + +import com.monke.basemvplib.IPresenter; + +import java.io.File; +import java.util.List; + +public interface IImportBookPresenter extends IPresenter{ + void searchLocationBook(); + + void importBooks(List books); +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/ILibraryPresenter.java b/app/src/main/java/com/monke/monkeybook/presenter/ILibraryPresenter.java new file mode 100644 index 0000000000..db81b2ef31 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/ILibraryPresenter.java @@ -0,0 +1,11 @@ +package com.monke.monkeybook.presenter; + +import com.monke.basemvplib.IPresenter; +import java.util.LinkedHashMap; + +public interface ILibraryPresenter extends IPresenter{ + + public LinkedHashMap getKinds(); + + public void getLibraryData(); +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/IMainPresenter.java b/app/src/main/java/com/monke/monkeybook/presenter/IMainPresenter.java new file mode 100644 index 0000000000..4187c69ba4 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/IMainPresenter.java @@ -0,0 +1,7 @@ +package com.monke.monkeybook.presenter; + +import com.monke.basemvplib.IPresenter; + +public interface IMainPresenter extends IPresenter{ + public void queryBookShelf(Boolean needRefresh); +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/ISearchPresenter.java b/app/src/main/java/com/monke/monkeybook/presenter/ISearchPresenter.java new file mode 100644 index 0000000000..a081ad389b --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/ISearchPresenter.java @@ -0,0 +1,29 @@ +package com.monke.monkeybook.presenter; + +import com.monke.basemvplib.IPresenter; +import com.monke.monkeybook.bean.SearchBookBean; + +public interface ISearchPresenter extends IPresenter{ + + public Boolean getHasSearch(); + + public void setHasSearch(Boolean hasSearch); + + public void insertSearchHistory(); + + public void querySearchHistory(); + + public void cleanSearchHistory(); + + public int getPage(); + + public void initPage(); + + public void toSearchBooks(String key); + + public void addBookToShelf(final SearchBookBean searchBookBean); + + public Boolean getInput(); + + public void setInput(Boolean input); +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/impl/BookDetailPresenterImpl.java b/app/src/main/java/com/monke/monkeybook/presenter/impl/BookDetailPresenterImpl.java new file mode 100644 index 0000000000..45ce51d410 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/impl/BookDetailPresenterImpl.java @@ -0,0 +1,249 @@ +package com.monke.monkeybook.presenter.impl; + +import android.content.Intent; +import android.support.annotation.NonNull; +import android.widget.Toast; +import com.hwangjr.rxbus.RxBus; +import com.hwangjr.rxbus.annotation.Subscribe; +import com.hwangjr.rxbus.annotation.Tag; +import com.hwangjr.rxbus.thread.EventThread; +import com.monke.basemvplib.IView; +import com.monke.basemvplib.impl.BaseActivity; +import com.monke.basemvplib.impl.BasePresenterImpl; +import com.monke.monkeybook.BitIntentDataManager; +import com.monke.monkeybook.MApplication; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.common.RxBusTag; +import com.monke.monkeybook.dao.DbHelper; +import com.monke.monkeybook.listener.OnGetChapterListListener; +import com.monke.monkeybook.model.impl.WebBookModelImpl; +import com.monke.monkeybook.presenter.IBookDetailPresenter; +import com.monke.monkeybook.view.IBookDetailView; +import com.trello.rxlifecycle2.android.ActivityEvent; + +import java.util.ArrayList; +import java.util.List; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +public class BookDetailPresenterImpl extends BasePresenterImpl implements IBookDetailPresenter { + public final static int FROM_BOOKSHELF = 1; + public final static int FROM_SEARCH = 2; + + private int openfrom; + private SearchBookBean searchBook; + private BookShelfBean bookShelf; + private Boolean inBookShelf = false; + + public BookDetailPresenterImpl(Intent intent) { + openfrom = intent.getIntExtra("from", FROM_BOOKSHELF); + if (openfrom == FROM_BOOKSHELF) { + String key = intent.getStringExtra("data_key"); + bookShelf = (BookShelfBean) BitIntentDataManager.getInstance().getData(key); + BitIntentDataManager.getInstance().cleanData(key); + inBookShelf = true; + } else { + searchBook = intent.getParcelableExtra("data"); + inBookShelf = searchBook.getAdd(); + } + } + + public Boolean getInBookShelf() { + return inBookShelf; + } + + public void setInBookShelf(Boolean inBookShelf) { + this.inBookShelf = inBookShelf; + } + + public int getOpenfrom() { + return openfrom; + } + + public SearchBookBean getSearchBook() { + return searchBook; + } + + public BookShelfBean getBookShelf() { + return bookShelf; + } + + @Override + public void getBookShelfInfo() { + final BookShelfBean bookShelfResult = new BookShelfBean(); + bookShelfResult.setNoteUrl(searchBook.getNoteUrl()); + bookShelfResult.setFinalDate(System.currentTimeMillis()); + bookShelfResult.setDurChapter(0); + bookShelfResult.setDurChapterPage(0); + bookShelfResult.setTag(searchBook.getTag()); + + WebBookModelImpl.getInstance().getBookInfo(bookShelfResult) + .subscribeOn(Schedulers.newThread()) + .compose(((BaseActivity)mView.getContext()).bindUntilEvent(ActivityEvent.DESTROY)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(BookShelfBean value) { + WebBookModelImpl.getInstance().getChapterList(value, new OnGetChapterListListener() { + @Override + public void success(BookShelfBean bookShelfBean) { + bookShelf = bookShelfBean; + mView.updateView(); + } + + @Override + public void error() { + bookShelf = null; + mView.getBookShelfError(); + } + }); + } + + @Override + public void onError(Throwable e) { + bookShelf = null; + mView.getBookShelfError(); + } + }); + } + + @Override + public void addToBookShelf() { + if (bookShelf != null) { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().insertOrReplaceInTx(bookShelf.getBookInfoBean().getChapterlist()); + DbHelper.getInstance().getmDaoSession().getBookInfoBeanDao().insertOrReplace(bookShelf.getBookInfoBean()); + //网络数据获取成功 存入BookShelf表数据库 + DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().insertOrReplace(bookShelf); + e.onNext(true); + e.onComplete(); + } + }).subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .compose(((BaseActivity)mView.getContext()).bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SimpleObserver() { + @Override + public void onNext(Boolean value) { + if (value) { + RxBus.get().post(RxBusTag.HAD_ADD_BOOK, bookShelf); + } else { + Toast.makeText(MApplication.getInstance(), "放入书架失败!", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + Toast.makeText(MApplication.getInstance(), "放入书架失败!", Toast.LENGTH_SHORT).show(); + } + }); + } + } + + @Override + public void removeFromBookShelf() { + if (bookShelf != null) { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().deleteByKey(bookShelf.getNoteUrl()); + DbHelper.getInstance().getmDaoSession().getBookInfoBeanDao().deleteByKey(bookShelf.getBookInfoBean().getNoteUrl()); + List keys = new ArrayList(); + if(bookShelf.getBookInfoBean().getChapterlist().size()>0){ + for(int i=0;ibindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SimpleObserver() { + @Override + public void onNext(Boolean value) { + if (value) { + RxBus.get().post(RxBusTag.HAD_REMOVE_BOOK, bookShelf); + } else { + Toast.makeText(MApplication.getInstance(), "移出书架失败!", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + Toast.makeText(MApplication.getInstance(), "移出书架失败!", Toast.LENGTH_SHORT).show(); + } + }); + } + } + + @Override + public void attachView(@NonNull IView iView) { + super.attachView(iView); + RxBus.get().register(this); + } + + @Override + public void detachView() { + RxBus.get().unregister(this); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.HAD_ADD_BOOK) + } + ) + public void hadAddBook(BookShelfBean value) { + if ((null != bookShelf && value.getNoteUrl().equals(bookShelf.getNoteUrl())) || (null != searchBook && value.getNoteUrl().equals(searchBook.getNoteUrl()))) { + inBookShelf = true; + if (null != searchBook) { + searchBook.setAdd(inBookShelf); + } + mView.updateView(); + } + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.HAD_REMOVE_BOOK) + } + ) + public void hadRemoveBook(BookShelfBean value) { + if ((null != bookShelf && value.getNoteUrl().equals(bookShelf.getNoteUrl())) || (null != searchBook && value.getNoteUrl().equals(searchBook.getNoteUrl()))) { + inBookShelf = false; + if (null != searchBook) { + searchBook.setAdd(false); + } + mView.updateView(); + } + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.HAD_ADD_BOOK), + } + ) + public void hadBook(BookShelfBean value) { + if ((null != bookShelf && value.getNoteUrl().equals(bookShelf.getNoteUrl())) || (null != searchBook && value.getNoteUrl().equals(searchBook.getNoteUrl()))) { + inBookShelf = true; + if (null != searchBook) { + searchBook.setAdd(true); + } + mView.updateView(); + } + } +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/impl/ChoiceBookPresenterImpl.java b/app/src/main/java/com/monke/monkeybook/presenter/impl/ChoiceBookPresenterImpl.java new file mode 100644 index 0000000000..5f9217d2a2 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/impl/ChoiceBookPresenterImpl.java @@ -0,0 +1,244 @@ +package com.monke.monkeybook.presenter.impl; + +import android.content.Intent; +import android.support.annotation.NonNull; +import com.hwangjr.rxbus.RxBus; +import com.hwangjr.rxbus.annotation.Subscribe; +import com.hwangjr.rxbus.annotation.Tag; +import com.hwangjr.rxbus.thread.EventThread; +import com.monke.basemvplib.IView; +import com.monke.basemvplib.impl.BaseActivity; +import com.monke.basemvplib.impl.BasePresenterImpl; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.common.RxBusTag; +import com.monke.monkeybook.dao.DbHelper; +import com.monke.monkeybook.listener.OnGetChapterListListener; +import com.monke.monkeybook.model.impl.WebBookModelImpl; +import com.monke.monkeybook.presenter.IChoiceBookPresenter; +import com.monke.monkeybook.utils.NetworkUtil; +import com.monke.monkeybook.view.IChoiceBookView; +import com.trello.rxlifecycle2.android.ActivityEvent; +import java.util.ArrayList; +import java.util.List; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +public class ChoiceBookPresenterImpl extends BasePresenterImpl implements IChoiceBookPresenter { + private String url = ""; + private String title; + + private int page = 1; + private long startThisSearchTime; + private List bookShelfs = new ArrayList<>(); //用来比对搜索的书籍是否已经添加进书架 + + public ChoiceBookPresenterImpl(final Intent intent) { + url = intent.getStringExtra("url"); + title = intent.getStringExtra("title"); + Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + List temp = DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().queryBuilder().list(); + if (temp == null) + temp = new ArrayList(); + e.onNext(temp); + } + }).subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver>() { + @Override + public void onNext(List value) { + bookShelfs.addAll(value); + initPage(); + toSearchBooks(null); + mView.startRefreshAnim(); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); + } + + @Override + public int getPage() { + return page; + } + + @Override + public void initPage() { + this.page = 1; + this.startThisSearchTime = System.currentTimeMillis(); + } + + @Override + public void toSearchBooks(String key) { + final long tempTime = startThisSearchTime; + searchBook(tempTime); + } + + private void searchBook(final long searchTime) { + WebBookModelImpl.getInstance().getKindBook(url, page) + .subscribeOn(Schedulers.newThread()) + .compose(((BaseActivity)mView.getContext()).>bindUntilEvent(ActivityEvent.DESTROY)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver>() { + @Override + public void onNext(List value) { + if (searchTime == startThisSearchTime) { + for (SearchBookBean temp : value) { + for (BookShelfBean bookShelfBean : bookShelfs) { + if (temp.getNoteUrl().equals(bookShelfBean.getNoteUrl())) { + temp.setAdd(true); + break; + } + } + } + if (page == 1) { + mView.refreshSearchBook(value); + mView.refreshFinish(value.size()<=0?true:false); + } else { + mView.loadMoreSearchBook(value); + mView.loadMoreFinish(value.size()<=0?true:false); + } + page++; + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + mView.searchBookError(); + } + }); + } + //////////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void addBookToShelf(final SearchBookBean searchBookBean) { + final BookShelfBean bookShelfResult = new BookShelfBean(); + bookShelfResult.setNoteUrl(searchBookBean.getNoteUrl()); + bookShelfResult.setFinalDate(0); + bookShelfResult.setDurChapter(0); + bookShelfResult.setDurChapterPage(0); + bookShelfResult.setTag(searchBookBean.getTag()); + WebBookModelImpl.getInstance().getBookInfo(bookShelfResult) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .compose(((BaseActivity)mView.getContext()).bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SimpleObserver() { + @Override + public void onNext(BookShelfBean value) { + WebBookModelImpl.getInstance().getChapterList(value, new OnGetChapterListListener() { + @Override + public void success(BookShelfBean bookShelfBean) { + saveBookToShelf(bookShelfBean); + } + + @Override + public void error() { + mView.addBookShelfFailed(NetworkUtil.ERROR_CODE_OUTTIME); + } + }); + } + + @Override + public void onError(Throwable e) { + mView.addBookShelfFailed(NetworkUtil.ERROR_CODE_OUTTIME); + } + }); + } + + @Override + public String getTitle() { + return title; + } + + private void saveBookToShelf(final BookShelfBean bookShelfBean){ + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().insertOrReplaceInTx(bookShelfBean.getBookInfoBean().getChapterlist()); + DbHelper.getInstance().getmDaoSession().getBookInfoBeanDao().insertOrReplace(bookShelfBean.getBookInfoBean()); + //网络数据获取成功 存入BookShelf表数据库 + DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().insertOrReplace(bookShelfBean); + e.onNext(bookShelfBean); + e.onComplete(); + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .compose(((BaseActivity)mView.getContext()).bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SimpleObserver() { + @Override + public void onNext(BookShelfBean value) { + //成功 //发送RxBus + RxBus.get().post(RxBusTag.HAD_ADD_BOOK, value); + } + + @Override + public void onError(Throwable e) { + mView.addBookShelfFailed(NetworkUtil.ERROR_CODE_OUTTIME); + } + }); + } + //////////////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void attachView(@NonNull IView iView) { + super.attachView(iView); + RxBus.get().register(this); + } + + @Override + public void detachView() { + RxBus.get().unregister(this); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.HAD_ADD_BOOK) + } + ) + public void hadAddBook(BookShelfBean bookShelfBean) { + bookShelfs.add(bookShelfBean); + List datas = mView.getSearchBookAdapter().getSearchBooks(); + for (int i = 0; i < datas.size(); i++) { + if (datas.get(i).getNoteUrl().equals(bookShelfBean.getNoteUrl())) { + datas.get(i).setAdd(true); + mView.updateSearchItem(i); + break; + } + } + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.HAD_REMOVE_BOOK) + } + ) + public void hadRemoveBook(BookShelfBean bookShelfBean) { + if(bookShelfs!=null){ + for(int i=0;i datas = mView.getSearchBookAdapter().getSearchBooks(); + for (int i = 0; i < datas.size(); i++) { + if (datas.get(i).getNoteUrl().equals(bookShelfBean.getNoteUrl())) { + datas.get(i).setAdd(false); + mView.updateSearchItem(i); + break; + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/presenter/impl/ImportBookPresenterImpl.java b/app/src/main/java/com/monke/monkeybook/presenter/impl/ImportBookPresenterImpl.java new file mode 100644 index 0000000000..569fa8a123 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/impl/ImportBookPresenterImpl.java @@ -0,0 +1,110 @@ +package com.monke.monkeybook.presenter.impl; + +import android.os.Environment; +import com.hwangjr.rxbus.RxBus; +import com.monke.basemvplib.impl.BasePresenterImpl; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.LocBookShelfBean; +import com.monke.monkeybook.common.RxBusTag; +import com.monke.monkeybook.model.impl.ImportBookModelImpl; +import com.monke.monkeybook.presenter.IImportBookPresenter; +import com.monke.monkeybook.view.IImportBookView; +import java.io.File; +import java.util.List; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.ObservableSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + +public class ImportBookPresenterImpl extends BasePresenterImpl implements IImportBookPresenter { + + + public ImportBookPresenterImpl(){ + + } + @Override + public void searchLocationBook(){ + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + if (Environment.getExternalStorageState().equals( + Environment.MEDIA_MOUNTED)){ + searchBook(e,new File(Environment.getExternalStorageDirectory().getAbsolutePath())); + } + e.onComplete(); + } + }).observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(File value) { + mView.addNewBook(value); + } + + @Override + public void onComplete() { + mView.searchFinish(); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); + } + + private void searchBook(ObservableEmitter e, File parentFile) { + if (null != parentFile && parentFile.listFiles().length > 0) { + File[] childFiles = parentFile.listFiles(); + for (int i = 0; i < childFiles.length; i++) { + if (childFiles[i].isFile() && childFiles[i].getName().substring(childFiles[i].getName().lastIndexOf(".") + 1).equalsIgnoreCase("txt") && childFiles[i].length() > 100*1024) { //100kb + e.onNext(childFiles[i]); + continue; + } + if (childFiles[i].isDirectory() && childFiles[i].listFiles().length > 0) { + searchBook(e, childFiles[i]); + } + } + } + } + + @Override + public void importBooks(List books){ + Observable.fromIterable(books).flatMap(new Function>() { + @Override + public ObservableSource apply(File file) throws Exception { + return ImportBookModelImpl.getInstance().importBook(file); + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(LocBookShelfBean value) { + if(value.getNew()){ + RxBus.get().post(RxBusTag.HAD_ADD_BOOK,value.getBookShelfBean()); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + mView.addError(); + } + + @Override + public void onComplete() { + mView.addSuccess(); + } + }); + } + + @Override + public void detachView() { + + } +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/impl/LibraryPresenterImpl.java b/app/src/main/java/com/monke/monkeybook/presenter/impl/LibraryPresenterImpl.java new file mode 100644 index 0000000000..2a86eeb432 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/impl/LibraryPresenterImpl.java @@ -0,0 +1,120 @@ +package com.monke.monkeybook.presenter.impl; + +import android.os.Handler; +import com.monke.basemvplib.impl.BasePresenterImpl; +import com.monke.monkeybook.MApplication; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.LibraryBean; +import com.monke.monkeybook.cache.ACache; +import com.monke.monkeybook.model.impl.GxwztvBookModelImpl; +import com.monke.monkeybook.presenter.ILibraryPresenter; +import com.monke.monkeybook.view.ILibraryView; +import java.util.LinkedHashMap; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.ObservableSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + +public class LibraryPresenterImpl extends BasePresenterImpl implements ILibraryPresenter { + public final static String LIBRARY_CACHE_KEY = "cache_library"; + private ACache mCache; + private Boolean isFirst = true; + + private final LinkedHashMap kinds = new LinkedHashMap<>(); + + public LibraryPresenterImpl() { + kinds.put("东方玄幻","http://www.gxwztv.com/xuanhuanxiaoshuo/"); + kinds.put("西方奇幻","http://www.gxwztv.com/qihuanxiaoshuo/"); + kinds.put("热血修真","http://www.gxwztv.com/xiuzhenxiaoshuo/"); + kinds.put("武侠仙侠","http://www.gxwztv.com/wuxiaxiaoshuo/"); + kinds.put("都市爽文","http://www.gxwztv.com/dushixiaoshuo/"); + kinds.put("言情暧昧","http://www.gxwztv.com/yanqingxiaoshuo/"); + kinds.put("灵异悬疑","http://www.gxwztv.com/lingyixiaoshuo/"); + kinds.put("运动竞技","http://www.gxwztv.com/jingjixiaoshuo/"); + kinds.put("历史架空","http://www.gxwztv.com/lishixiaoshuo/"); + kinds.put("审美","http://www.gxwztv.com/danmeixiaoshuo/"); + kinds.put("科幻迷航","http://www.gxwztv.com/kehuanxiaoshuo/"); + kinds.put("游戏人生","http://www.gxwztv.com/youxixiaoshuo/"); + kinds.put("军事斗争","http://www.gxwztv.com/junshixiaoshuo/"); + kinds.put("商战人生","http://www.gxwztv.com/shangzhanxiaoshuo/"); + kinds.put("校园爱情","http://www.gxwztv.com/xiaoyuanxiaoshuo/"); + kinds.put("官场仕途","http://www.gxwztv.com/guanchangxiaoshuo/"); + kinds.put("娱乐明星","http://www.gxwztv.com/zhichangxiaoshuo/"); + kinds.put("其他","http://www.gxwztv.com/qitaxiaoshuo/"); + + mCache = ACache.get(MApplication.getInstance()); + } + + @Override + public void detachView() { + + } + + @Override + public void getLibraryData() { + if (isFirst) { + isFirst = false; + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + String cache = mCache.getAsString(LIBRARY_CACHE_KEY); + e.onNext(cache); + e.onComplete(); + } + }).flatMap(new Function>() { + @Override + public ObservableSource apply(String s) throws Exception { + return GxwztvBookModelImpl.getInstance().analyLibraryData(s); + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(LibraryBean value) { + //执行刷新界面 + mView.updateUI(value); + getLibraryNewData(); + } + + @Override + public void onError(Throwable e) { + getLibraryNewData(); + } + }); + }else{ + getLibraryNewData(); + } + } + + private void getLibraryNewData() { + GxwztvBookModelImpl.getInstance().getLibraryData(mCache).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(final LibraryBean value) { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + mView.updateUI(value); + mView.finishRefresh(); + } + },1000); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + mView.finishRefresh(); + } + }); + } + + @Override + public LinkedHashMap getKinds() { + return kinds; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/presenter/impl/MainPresenterImpl.java b/app/src/main/java/com/monke/monkeybook/presenter/impl/MainPresenterImpl.java new file mode 100644 index 0000000000..66e0b0ac49 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/impl/MainPresenterImpl.java @@ -0,0 +1,153 @@ +package com.monke.monkeybook.presenter.impl; + +import android.support.annotation.NonNull; +import com.hwangjr.rxbus.RxBus; +import com.hwangjr.rxbus.annotation.Subscribe; +import com.hwangjr.rxbus.annotation.Tag; +import com.hwangjr.rxbus.thread.EventThread; +import com.monke.basemvplib.IView; +import com.monke.basemvplib.impl.BasePresenterImpl; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookInfoBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.common.RxBusTag; +import com.monke.monkeybook.dao.BookInfoBeanDao; +import com.monke.monkeybook.dao.BookShelfBeanDao; +import com.monke.monkeybook.dao.ChapterListBeanDao; +import com.monke.monkeybook.dao.DbHelper; +import com.monke.monkeybook.listener.OnGetChapterListListener; +import com.monke.monkeybook.model.impl.WebBookModelImpl; +import com.monke.monkeybook.presenter.IMainPresenter; +import com.monke.monkeybook.utils.NetworkUtil; +import com.monke.monkeybook.view.IMainView; +import java.util.ArrayList; +import java.util.List; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +public class MainPresenterImpl extends BasePresenterImpl implements IMainPresenter { + + public void queryBookShelf(final Boolean needRefresh) { + if (needRefresh) + mView.activityRefreshView(); + Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + List bookShelfes = DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().queryBuilder().orderDesc(BookShelfBeanDao.Properties.FinalDate).list(); + for (int i = 0; i < bookShelfes.size(); i++) { + List temp = DbHelper.getInstance().getmDaoSession().getBookInfoBeanDao().queryBuilder().where(BookInfoBeanDao.Properties.NoteUrl.eq(bookShelfes.get(i).getNoteUrl())).limit(1).build().list(); + if (temp != null && temp.size() > 0) { + BookInfoBean bookInfoBean = temp.get(0); + bookInfoBean.setChapterlist(DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().queryBuilder().where(ChapterListBeanDao.Properties.NoteUrl.eq(bookShelfes.get(i).getNoteUrl())).orderAsc(ChapterListBeanDao.Properties.DurChapterIndex).build().list()); + bookShelfes.get(i).setBookInfoBean(bookInfoBean); + } else { + DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().delete(bookShelfes.get(i)); + bookShelfes.remove(i); + i--; + } + } + e.onNext(bookShelfes == null ? new ArrayList() : bookShelfes); + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver>() { + @Override + public void onNext(List value) { + if (null != value) { + mView.refreshBookShelf(value); + if (needRefresh) { + startRefreshBook(value); + } else { + mView.refreshFinish(); + } + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + mView.refreshError(NetworkUtil.getErrorTip(NetworkUtil.ERROR_CODE_ANALY)); + } + }); + } + + public void startRefreshBook(List value){ + if (value != null && value.size() > 0){ + mView.setRecyclerMaxProgress(value.size()); + refreshBookShelf(value,0); + }else{ + mView.refreshFinish(); + } + } + + private void refreshBookShelf(final List value, final int index) { + if (index<=value.size()-1) { + WebBookModelImpl.getInstance().getChapterList(value.get(index), new OnGetChapterListListener() { + @Override + public void success(BookShelfBean bookShelfBean) { + saveBookToShelf(value,index); + } + + @Override + public void error() { + mView.refreshError(NetworkUtil.getErrorTip(NetworkUtil.ERROR_CODE_NONET)); + } + }); + } else { + queryBookShelf(false); + } + } + + private void saveBookToShelf(final List datas, final int index){ + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().insertOrReplaceInTx(datas.get(index).getBookInfoBean().getChapterlist()); + e.onNext(datas.get(index)); + e.onComplete(); + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(BookShelfBean value) { + mView.refreshRecyclerViewItemAdd(); + refreshBookShelf(datas,index+1); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + mView.refreshError(NetworkUtil.getErrorTip(NetworkUtil.ERROR_CODE_NONET)); + } + }); + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void attachView(@NonNull IView iView) { + super.attachView(iView); + RxBus.get().register(this); + } + + @Override + public void detachView() { + RxBus.get().unregister(this); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.HAD_ADD_BOOK), + @Tag(RxBusTag.HAD_REMOVE_BOOK), + @Tag(RxBusTag.UPDATE_BOOK_PROGRESS) + } + ) + public void hadddOrRemoveBook(BookShelfBean bookShelfBean) { + queryBookShelf(false); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/impl/ReadBookPresenterImpl.java b/app/src/main/java/com/monke/monkeybook/presenter/impl/ReadBookPresenterImpl.java new file mode 100644 index 0000000000..ef046f2037 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/impl/ReadBookPresenterImpl.java @@ -0,0 +1,438 @@ +package com.monke.monkeybook.presenter.impl; + +import android.Manifest; +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build; +import android.provider.MediaStore; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.widget.Toast; + +import com.hwangjr.rxbus.RxBus; +import com.monke.basemvplib.impl.BaseActivity; +import com.monke.basemvplib.impl.BasePresenterImpl; +import com.monke.monkeybook.BitIntentDataManager; +import com.monke.monkeybook.MApplication; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookContentBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.LocBookShelfBean; +import com.monke.monkeybook.bean.ReadBookContentBean; +import com.monke.monkeybook.common.RxBusTag; +import com.monke.monkeybook.dao.BookContentBeanDao; +import com.monke.monkeybook.dao.BookShelfBeanDao; +import com.monke.monkeybook.dao.DbHelper; +import com.monke.monkeybook.model.impl.ImportBookModelImpl; +import com.monke.monkeybook.model.impl.WebBookModelImpl; +import com.monke.monkeybook.presenter.IBookReadPresenter; +import com.monke.monkeybook.utils.PremissionCheck; +import com.monke.monkeybook.view.IBookReadView; +import com.monke.monkeybook.widget.contentswitchview.BookContentView; +import com.trello.rxlifecycle2.android.ActivityEvent; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + +public class ReadBookPresenterImpl extends BasePresenterImpl implements IBookReadPresenter { + + public final static int OPEN_FROM_OTHER = 0; + public final static int OPEN_FROM_APP = 1; + + private Boolean isAdd = false; //判断是否已经添加进书架 + private int open_from; + private BookShelfBean bookShelf; + + private int pageLineCount = 5; //假设5行一页 + + public ReadBookPresenterImpl() { + + } + + @Override + public void initData(Activity activity) { + Intent intent = activity.getIntent(); + open_from = intent.getIntExtra("from", OPEN_FROM_OTHER); + if (open_from == OPEN_FROM_APP) { + String key = intent.getStringExtra("data_key"); + bookShelf = (BookShelfBean) BitIntentDataManager.getInstance().getData(key); + if (!bookShelf.getTag().equals(BookShelfBean.LOCAL_TAG)) { + mView.showDownloadMenu(); + } + BitIntentDataManager.getInstance().cleanData(key); + checkInShelf(); + } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PremissionCheck.checkPremission(activity, + Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + //申请权限 + activity.requestPermissions( + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0x11); + } else { + openBookFromOther(activity); + } + } + } + + @Override + public void openBookFromOther(Activity activity) { + //APP外部打开 + Uri uri = activity.getIntent().getData(); + mView.showLoadBook(); + getRealFilePath(activity, uri) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.newThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(String value) { + ImportBookModelImpl.getInstance().importBook(new File(value)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.newThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(LocBookShelfBean value) { + if (value.getNew()) + RxBus.get().post(RxBusTag.HAD_ADD_BOOK, value); + bookShelf = value.getBookShelfBean(); + mView.dimissLoadBook(); + checkInShelf(); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + mView.dimissLoadBook(); + mView.loadLocationBookError(); + Toast.makeText(MApplication.getInstance(), "文本打开失败!", Toast.LENGTH_SHORT).show(); + } + }); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + mView.dimissLoadBook(); + mView.loadLocationBookError(); + Toast.makeText(MApplication.getInstance(), "文本打开失败!", Toast.LENGTH_SHORT).show(); + } + }); + } + + @Override + public void detachView() { + } + + @Override + public int getOpen_from() { + return open_from; + } + + @Override + public BookShelfBean getBookShelf() { + return bookShelf; + } + + @Override + public void initContent() { + mView.initContentSuccess(bookShelf.getDurChapter(), bookShelf.getBookInfoBean().getChapterlist().size(), bookShelf.getDurChapterPage()); + } + + @Override + public void loadContent(final BookContentView bookContentView, final long bookTag, final int chapterIndex, int pageIndex) { + if (null != bookShelf && bookShelf.getBookInfoBean().getChapterlist().size() > 0) { + if (null != bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean() && null != bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean().getDurCapterContent()) { + if (bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean().getLineSize() == mView.getPaint().getTextSize() && bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean().getLineContent().size() > 0) { + //已有数据 + int tempCount = (int) Math.ceil(bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean().getLineContent().size() * 1.0 / pageLineCount) - 1; + + if (pageIndex == BookContentView.DURPAGEINDEXBEGIN) { + pageIndex = 0; + } else if (pageIndex == BookContentView.DURPAGEINDEXEND) { + pageIndex = tempCount; + } else { + if (pageIndex >= tempCount) { + pageIndex = tempCount; + } + } + + int start = pageIndex * pageLineCount; + int end = pageIndex == tempCount ? bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean().getLineContent().size() : start + pageLineCount; + if (bookContentView != null && bookTag == bookContentView.getqTag()) { + bookContentView.updateData(bookTag, bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getDurChapterName() + , bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean().getLineContent().subList(start, end) + , chapterIndex + , bookShelf.getBookInfoBean().getChapterlist().size() + , pageIndex + , tempCount + 1); + } + } else { + //有元数据 重新分行 + bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean().setLineSize(mView.getPaint().getTextSize()); + final int finalPageIndex = pageIndex; + SeparateParagraphtoLines(bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean().getDurCapterContent()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .compose(((BaseActivity) mView.getContext()).>bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SimpleObserver>() { + @Override + public void onNext(List value) { + bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean().getLineContent().clear(); + bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getBookContentBean().getLineContent().addAll(value); + loadContent(bookContentView, bookTag, chapterIndex, finalPageIndex); + } + + @Override + public void onError(Throwable e) { + if (bookContentView != null && bookTag == bookContentView.getqTag()) + bookContentView.loadError(); + } + }); + } + } else { + final int finalPageIndex1 = pageIndex; + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + List tempList = DbHelper.getInstance().getmDaoSession().getBookContentBeanDao().queryBuilder().where(BookContentBeanDao.Properties.DurChapterUrl.eq(bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getDurChapterUrl())).build().list(); + e.onNext(new ReadBookContentBean(tempList == null ? new ArrayList() : tempList, finalPageIndex1)); + e.onComplete(); + } + }).observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.newThread()) + .compose(((BaseActivity) mView.getContext()).bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SimpleObserver() { + @Override + public void onNext(ReadBookContentBean tempList) { + if (tempList.getBookContentList() != null && tempList.getBookContentList().size() > 0 && tempList.getBookContentList().get(0).getDurCapterContent() != null) { + bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).setBookContentBean(tempList.getBookContentList().get(0)); + loadContent(bookContentView, bookTag, chapterIndex, tempList.getPageIndex()); + } else { + final int finalPageIndex1 = tempList.getPageIndex(); + WebBookModelImpl.getInstance().getBookContent(bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getDurChapterUrl(), chapterIndex, bookShelf.getTag()).map(new Function() { + @Override + public BookContentBean apply(BookContentBean bookContentBean) throws Exception { + if (bookContentBean.getRight()) { + DbHelper.getInstance().getmDaoSession().getBookContentBeanDao().insertOrReplace(bookContentBean); + bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).setHasCache(true); + DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().update(bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex)); + } + return bookContentBean; + } + }) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.newThread()) + .compose(((BaseActivity) mView.getContext()).bindUntilEvent(ActivityEvent.DESTROY)) + .subscribe(new SimpleObserver() { + @Override + public void onNext(BookContentBean value) { + if (value.getDurChapterUrl() != null && value.getDurChapterUrl().length() > 0) { + bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).setBookContentBean(value); + if (bookTag == bookContentView.getqTag()) + loadContent(bookContentView, bookTag, chapterIndex, finalPageIndex1); + } else { + if (bookContentView != null && bookTag == bookContentView.getqTag()) + bookContentView.loadError(); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + if (bookContentView != null && bookTag == bookContentView.getqTag()) + bookContentView.loadError(); + } + }); + } + } + + @Override + public void onError(Throwable e) { + + } + }); + } + } else { + if (bookContentView != null && bookTag == bookContentView.getqTag()) + bookContentView.loadError(); + } + } + + @Override + public void updateProgress(int chapterIndex, int pageIndex) { + bookShelf.setDurChapter(chapterIndex); + bookShelf.setDurChapterPage(pageIndex); + } + + @Override + public void saveProgress() { + if (bookShelf != null) { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + bookShelf.setFinalDate(System.currentTimeMillis()); + DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().insertOrReplace(bookShelf); + e.onNext(bookShelf); + e.onComplete(); + } + }).subscribeOn(Schedulers.newThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(BookShelfBean value) { + RxBus.get().post(RxBusTag.UPDATE_BOOK_PROGRESS, bookShelf); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); + } + } + + @Override + public String getChapterTitle(int chapterIndex) { + if (bookShelf.getBookInfoBean().getChapterlist().size() == 0) { + return "无章节"; + } else + return bookShelf.getBookInfoBean().getChapterlist().get(chapterIndex).getDurChapterName(); + } + + public Observable> SeparateParagraphtoLines(final String paragraphstr) { + return Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + TextPaint mPaint = (TextPaint) mView.getPaint(); + mPaint.setSubpixelText(true); + Layout tempLayout = new StaticLayout(paragraphstr, mPaint, mView.getContentWidth(), Layout.Alignment.ALIGN_NORMAL, 0, 0, false); + ; + List linesdata = new ArrayList(); + for (int i = 0; i < tempLayout.getLineCount(); i++) { + linesdata.add(paragraphstr.substring(tempLayout.getLineStart(i), tempLayout.getLineEnd(i))); + } + e.onNext(linesdata); + e.onComplete(); + } + }); + } + + @Override + public void setPageLineCount(int pageLineCount) { + this.pageLineCount = pageLineCount; + } + + private void checkInShelf() { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + List temp = DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().queryBuilder().where(BookShelfBeanDao.Properties.NoteUrl.eq(bookShelf.getNoteUrl())).build().list(); + if (temp == null || temp.size() == 0) { + isAdd = false; + } else + isAdd = true; + e.onNext(isAdd); + e.onComplete(); + } + }).subscribeOn(Schedulers.io()) + .compose(((BaseActivity) mView.getContext()).bindUntilEvent(ActivityEvent.DESTROY)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(Boolean value) { + mView.initPop(); + mView.setHpbReadProgressMax(bookShelf.getBookInfoBean().getChapterlist().size()); + mView.startLoadingBook(); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); + } + + public interface OnAddListner { + public void addSuccess(); + } + + @Override + public void addToShelf(final OnAddListner addListner) { + if (bookShelf != null) { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().insertOrReplaceInTx(bookShelf.getBookInfoBean().getChapterlist()); + DbHelper.getInstance().getmDaoSession().getBookInfoBeanDao().insertOrReplace(bookShelf.getBookInfoBean()); + //网络数据获取成功 存入BookShelf表数据库 + DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().insertOrReplace(bookShelf); + RxBus.get().post(RxBusTag.HAD_ADD_BOOK, bookShelf); + isAdd = true; + e.onNext(true); + e.onComplete(); + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(Object value) { + if (addListner != null) + addListner.addSuccess(); + } + + @Override + public void onError(Throwable e) { + + } + }); + } + } + + public Boolean getAdd() { + return isAdd; + } + + public Observable getRealFilePath(final Context context, final Uri uri) { + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + String data = ""; + if (null != uri) { + final String scheme = uri.getScheme(); + if (scheme == null) + data = uri.getPath(); + else if (ContentResolver.SCHEME_FILE.equals(scheme)) { + data = uri.getPath(); + } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { + Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null); + if (null != cursor) { + if (cursor.moveToFirst()) { + int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); + if (index > -1) { + data = cursor.getString(index); + } + } + cursor.close(); + } + + if ((data == null || data.length() <= 0) && uri.getPath() != null && uri.getPath().contains("/storage/emulated/")) { + data = uri.getPath().substring(uri.getPath().indexOf("/storage/emulated/")); + } + } + } + e.onNext(data == null ? "" : data); + e.onComplete(); + } + }); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/presenter/impl/SearchPresenterImpl.java b/app/src/main/java/com/monke/monkeybook/presenter/impl/SearchPresenterImpl.java new file mode 100644 index 0000000000..ef0cb9297c --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/presenter/impl/SearchPresenterImpl.java @@ -0,0 +1,435 @@ +package com.monke.monkeybook.presenter.impl; + +import android.support.annotation.NonNull; + +import com.hwangjr.rxbus.RxBus; +import com.hwangjr.rxbus.annotation.Subscribe; +import com.hwangjr.rxbus.annotation.Tag; +import com.hwangjr.rxbus.thread.EventThread; +import com.monke.basemvplib.IView; +import com.monke.basemvplib.impl.BasePresenterImpl; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.bean.SearchHistoryBean; +import com.monke.monkeybook.common.RxBusTag; +import com.monke.monkeybook.dao.DbHelper; +import com.monke.monkeybook.dao.SearchHistoryBeanDao; +import com.monke.monkeybook.listener.OnGetChapterListListener; +import com.monke.monkeybook.model.impl.EasouBookModelImpl; +import com.monke.monkeybook.model.impl.GxwztvBookModelImpl; +import com.monke.monkeybook.model.impl.LingdiankanshuStationBookModelImpl; +import com.monke.monkeybook.model.impl.WebBookModelImpl; +import com.monke.monkeybook.presenter.ISearchPresenter; +import com.monke.monkeybook.utils.NetworkUtil; +import com.monke.monkeybook.view.ISearchView; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +public class SearchPresenterImpl extends BasePresenterImpl implements ISearchPresenter { + public static final int BOOK = 2; + + private Boolean hasSearch = false; //判断是否搜索过 + + private int page = 1; + private List searchEngine; + private long startThisSearchTime; + private String durSearchKey; + + private List bookShelfs = new ArrayList<>(); //用来比对搜索的书籍是否已经添加进书架 + + private Boolean isInput = false; + + public SearchPresenterImpl() { + Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + List temp = DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().queryBuilder().list(); + if (temp == null) + temp = new ArrayList(); + e.onNext(temp); + e.onComplete(); + } + }).subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver>() { + @Override + public void onNext(List value) { + bookShelfs.addAll(value); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); + + searchEngine = new ArrayList<>(); + + Map gxwztvMap = new HashMap(); + gxwztvMap.put("tag", GxwztvBookModelImpl.TAG); + gxwztvMap.put("hasMore", true); + gxwztvMap.put("hasLoad", false); + searchEngine.add(gxwztvMap); + + Map lingdiankanshu = new HashMap(); + lingdiankanshu.put("tag", LingdiankanshuStationBookModelImpl.TAG); + lingdiankanshu.put("hasMore", true); + lingdiankanshu.put("hasLoad", false); + searchEngine.add(lingdiankanshu); + + Map easou = new HashMap(); + easou.put("tag", EasouBookModelImpl.TAG); + easou.put("hasMore", true); + easou.put("hasLoad", false); + searchEngine.add(easou); + } + + @Override + public Boolean getHasSearch() { + return hasSearch; + } + + @Override + public void setHasSearch(Boolean hasSearch) { + this.hasSearch = hasSearch; + } + + @Override + public void insertSearchHistory() { + final int type = SearchPresenterImpl.BOOK; + final String content = mView.getEdtContent().getText().toString().trim(); + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + List datas = DbHelper.getInstance().getmDaoSession().getSearchHistoryBeanDao() + .queryBuilder() + .where(SearchHistoryBeanDao.Properties.Type.eq(type), SearchHistoryBeanDao.Properties.Content.eq(content)) + .limit(1) + .build().list(); + SearchHistoryBean searchHistoryBean = null; + if (null != datas && datas.size() > 0) { + searchHistoryBean = datas.get(0); + searchHistoryBean.setDate(System.currentTimeMillis()); + DbHelper.getInstance().getmDaoSession().getSearchHistoryBeanDao().update(searchHistoryBean); + } else { + searchHistoryBean = new SearchHistoryBean(type, content, System.currentTimeMillis()); + DbHelper.getInstance().getmDaoSession().getSearchHistoryBeanDao().insert(searchHistoryBean); + } + e.onNext(searchHistoryBean); + } + }).subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(SearchHistoryBean value) { + mView.insertSearchHistorySuccess(value); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); + } + + @Override + public void cleanSearchHistory() { + final int type = SearchPresenterImpl.BOOK; + final String content = mView.getEdtContent().getText().toString().trim(); + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + int a = DbHelper.getInstance().getDb().delete(SearchHistoryBeanDao.TABLENAME, SearchHistoryBeanDao.Properties.Type.columnName + "=? and " + SearchHistoryBeanDao.Properties.Content.columnName + " like ?", new String[]{String.valueOf(type), "%" + content + "%"}); + e.onNext(a); + } + }).subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(Integer value) { + if (value > 0) { + mView.querySearchHistorySuccess(null); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); + } + + @Override + public void querySearchHistory() { + final int type = SearchPresenterImpl.BOOK; + final String content = mView.getEdtContent().getText().toString().trim(); + Observable.create(new ObservableOnSubscribe>() { + @Override + public void subscribe(ObservableEmitter> e) throws Exception { + List datas = DbHelper.getInstance().getmDaoSession().getSearchHistoryBeanDao() + .queryBuilder() + .where(SearchHistoryBeanDao.Properties.Type.eq(type), SearchHistoryBeanDao.Properties.Content.like("%" + content + "%")) + .orderDesc(SearchHistoryBeanDao.Properties.Date) + .limit(20) + .build().list(); + e.onNext(datas); + } + }).subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver>() { + @Override + public void onNext(List value) { + if (null != value) + mView.querySearchHistorySuccess(value); + } + + @Override + public void onError(Throwable e) { + + } + }); + } + + @Override + public int getPage() { + return page; + } + + @Override + public void initPage() { + this.page = 1; + } + + @Override + public void toSearchBooks(String key) { + if (key != null) { + durSearchKey = key; + this.startThisSearchTime = System.currentTimeMillis(); + for (int i = 0; i < searchEngine.size(); i++) { + searchEngine.get(i).put("hasMore", true); + searchEngine.get(i).put("hasLoad", false); + } + } + searchBook(durSearchKey, startThisSearchTime, 0); + } + + private void searchBook(final String content, final long searchTime, final int searchEngineIndex) { + if (searchTime == startThisSearchTime) { + Boolean hasMore = false; + for (Map temp : searchEngine) { + if ((Boolean) temp.get("hasMore")) { + hasMore = true; + break; + } + } + if (hasMore) { + if (searchEngineIndex < searchEngine.size()) { + if ((Boolean) searchEngine.get(searchEngineIndex).get("hasMore") && !(Boolean) searchEngine.get(searchEngineIndex).get("hasLoad")) { + WebBookModelImpl.getInstance().searchOtherBook(content, page, (String) searchEngine.get(searchEngineIndex).get("tag")) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.newThread()) + .subscribe(new SimpleObserver>() { + @Override + public void onNext(List value) { + if (searchTime == startThisSearchTime) { + searchEngine.get(searchEngineIndex).put("hasLoad", true); + if (value.size() == 0) { + searchEngine.get(searchEngineIndex).put("hasMore", false); + } else { + for (SearchBookBean temp : value) { + for (BookShelfBean bookShelfBean : bookShelfs) { + if (temp.getNoteUrl().equals(bookShelfBean.getNoteUrl())) { + temp.setAdd(true); + break; + } + } + } + } + if (page == 1 && searchEngineIndex == 0) { + mView.refreshSearchBook(value); + } else { + if (value != null && value.size() > 0 && !mView.checkIsExist(value.get(0))) + mView.loadMoreSearchBook(value); + else { + searchEngine.get(searchEngineIndex).put("hasMore", false); + } + } + searchBook(content, searchTime, searchEngineIndex + 1); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + if (searchTime == startThisSearchTime) { + searchEngine.get(searchEngineIndex).put("hasLoad", false); + mView.searchBookError(page == 1 && (searchEngineIndex == 0 || (searchEngineIndex > 0 && mView.getSearchBookAdapter().getItemcount() == 0))); + } + } + }); + } else { + searchBook(content, searchTime, searchEngineIndex + 1); + } + } else { + if (page == 1) { + mView.refreshFinish(false); + } else { + mView.loadMoreFinish(false); + } + this.page++; + for (Map item : searchEngine) { + item.put("hasLoad", false); + } + } + } else { + if (page == 1) { + mView.refreshFinish(true); + } else { + mView.loadMoreFinish(true); + } + this.page++; + for (Map item : searchEngine) { + item.put("hasLoad", false); + } + } + } + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void addBookToShelf(final SearchBookBean searchBookBean) { + final BookShelfBean bookShelfResult = new BookShelfBean(); + bookShelfResult.setNoteUrl(searchBookBean.getNoteUrl()); + bookShelfResult.setFinalDate(0); + bookShelfResult.setDurChapter(0); + bookShelfResult.setDurChapterPage(0); + bookShelfResult.setTag(searchBookBean.getTag()); + WebBookModelImpl.getInstance().getBookInfo(bookShelfResult) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(BookShelfBean value) { + WebBookModelImpl.getInstance().getChapterList(value, new OnGetChapterListListener() { + @Override + public void success(BookShelfBean bookShelfBean) { + saveBookToShelf(bookShelfBean); + } + + @Override + public void error() { + mView.addBookShelfFailed(NetworkUtil.ERROR_CODE_OUTTIME); + } + }); + } + + @Override + public void onError(Throwable e) { + mView.addBookShelfFailed(NetworkUtil.ERROR_CODE_OUTTIME); + } + }); + } + + private void saveBookToShelf(final BookShelfBean bookShelfBean) { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().insertOrReplaceInTx(bookShelfBean.getBookInfoBean().getChapterlist()); + DbHelper.getInstance().getmDaoSession().getBookInfoBeanDao().insertOrReplace(bookShelfBean.getBookInfoBean()); + //网络数据获取成功 存入BookShelf表数据库 + DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().insertOrReplace(bookShelfBean); + e.onNext(bookShelfBean); + e.onComplete(); + } + }).subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(BookShelfBean value) { + //成功 //发送RxBus + RxBus.get().post(RxBusTag.HAD_ADD_BOOK, value); + } + + @Override + public void onError(Throwable e) { + mView.addBookShelfFailed(NetworkUtil.ERROR_CODE_OUTTIME); + } + }); + } + //////////////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void attachView(@NonNull IView iView) { + super.attachView(iView); + RxBus.get().register(this); + } + + @Override + public void detachView() { + RxBus.get().unregister(this); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.HAD_ADD_BOOK) + } + ) + public void hadAddBook(BookShelfBean bookShelfBean) { + bookShelfs.add(bookShelfBean); + List datas = mView.getSearchBookAdapter().getSearchBooks(); + for (int i = 0; i < datas.size(); i++) { + if (datas.get(i).getNoteUrl().equals(bookShelfBean.getNoteUrl())) { + datas.get(i).setAdd(true); + mView.updateSearchItem(i); + break; + } + } + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.HAD_REMOVE_BOOK) + } + ) + public void hadRemoveBook(BookShelfBean bookShelfBean) { + if(bookShelfs!=null){ + for(int i=0;i datas = mView.getSearchBookAdapter().getSearchBooks(); + for (int i = 0; i < datas.size(); i++) { + if (datas.get(i).getNoteUrl().equals(bookShelfBean.getNoteUrl())) { + datas.get(i).setAdd(false); + mView.updateSearchItem(i); + break; + } + } + } + + @Override + public Boolean getInput() { + return isInput; + } + + @Override + public void setInput(Boolean input) { + isInput = input; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/service/DownloadService.java b/app/src/main/java/com/monke/monkeybook/service/DownloadService.java new file mode 100644 index 0000000000..23a85b02f7 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/service/DownloadService.java @@ -0,0 +1,448 @@ +package com.monke.monkeybook.service; + +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.support.annotation.Nullable; +import android.support.v4.app.NotificationCompat; +import android.widget.Toast; +import com.hwangjr.rxbus.RxBus; +import com.hwangjr.rxbus.annotation.Subscribe; +import com.hwangjr.rxbus.annotation.Tag; +import com.hwangjr.rxbus.thread.EventThread; +import com.monke.monkeybook.R; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookContentBean; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.ChapterListBean; +import com.monke.monkeybook.bean.DownloadChapterBean; +import com.monke.monkeybook.bean.DownloadChapterListBean; +import com.monke.monkeybook.common.RxBusTag; +import com.monke.monkeybook.dao.BookContentBeanDao; +import com.monke.monkeybook.dao.BookShelfBeanDao; +import com.monke.monkeybook.dao.DbHelper; +import com.monke.monkeybook.dao.DownloadChapterBeanDao; +import com.monke.monkeybook.model.impl.WebBookModelImpl; +import com.monke.monkeybook.view.impl.MainActivity; + +import java.util.List; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.ObservableSource; +import io.reactivex.Observer; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; +import io.reactivex.functions.Function; +import io.reactivex.schedulers.Schedulers; + +public class DownloadService extends Service { + private NotificationManager notifyManager; + private int notifiId = 19931118; + private Boolean isStartDownload = false; + private Boolean isInit = false; + + @Override + public void onCreate() { + super.onCreate(); + + } + + @Override + public void onDestroy() { + super.onDestroy(); + RxBus.get().unregister(this); + isInit = true; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (!isInit) { + isInit = true; + notifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + RxBus.get().register(this); + } + return super.onStartCommand(intent, flags, startId); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + private void addNewTask(final List newData) { + isStartDownload = true; + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().insertOrReplaceInTx(newData); + e.onNext(true); + e.onComplete(); + } + }) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(Boolean value) { + if (!isDownloading) { + toDownload(); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); + } + + private Boolean isDownloading = false; + public static final int reTryTimes = 1; + + private void toDownload() { + isDownloading = true; + if (isStartDownload) { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + List bookShelfBeanList = DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().queryBuilder().orderDesc(BookShelfBeanDao.Properties.FinalDate).list(); + if (bookShelfBeanList != null && bookShelfBeanList.size() > 0) { + for (BookShelfBean bookItem : bookShelfBeanList) { + if (!bookItem.getTag().equals(BookShelfBean.LOCAL_TAG)) { + List downloadChapterList = DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().queryBuilder().where(DownloadChapterBeanDao.Properties.NoteUrl.eq(bookItem.getNoteUrl())).orderAsc(DownloadChapterBeanDao.Properties.DurChapterIndex).limit(1).list(); + if (downloadChapterList != null && downloadChapterList.size() > 0) { + e.onNext(downloadChapterList.get(0)); + e.onComplete(); + return; + } + } + } + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll(); + e.onNext(new DownloadChapterBean()); + } else { + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll(); + e.onNext(new DownloadChapterBean()); + } + e.onComplete(); + } + }) + .subscribeOn(AndroidSchedulers.mainThread()) + .observeOn(Schedulers.io()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(DownloadChapterBean value) { + if (value.getNoteUrl() != null && value.getNoteUrl().length() > 0) { + downloading(value, 0); + } else { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll(); + e.onNext(new Object()); + e.onComplete(); + } + }) + .subscribeOn(AndroidSchedulers.mainThread()) + .observeOn(Schedulers.io()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(Object value) { + isDownloading = false; + finishDownload(); + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + isDownloading = false; + } + }); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + isDownloading = false; + } + }); + } else { + isPause(); + } + } + + private void downloading(final DownloadChapterBean data, final int durTime) { + if (durTime < reTryTimes && isStartDownload) { + isProgress(data); + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + List result = DbHelper.getInstance().getmDaoSession().getBookContentBeanDao().queryBuilder().where(BookContentBeanDao.Properties.DurChapterUrl.eq(data.getDurChapterUrl())).list(); + if (result != null && result.size() > 0) { + e.onNext(result.get(0)); + } else { + e.onNext(new BookContentBean()); + } + e.onComplete(); + } + }).flatMap(new Function>() { + @Override + public ObservableSource apply(final BookContentBean bookContentBean) throws Exception { + if (bookContentBean.getDurChapterUrl() == null || bookContentBean.getDurChapterUrl().length() <= 0) { + return WebBookModelImpl.getInstance().getBookContent(data.getDurChapterUrl(), data.getDurChapterIndex(), data.getTag()).map(new Function() { + @Override + public BookContentBean apply(BookContentBean bookContentBean) throws Exception { + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().delete(data); + if (bookContentBean.getRight()) { + DbHelper.getInstance().getmDaoSession().getBookContentBeanDao().insertOrReplace(bookContentBean); + DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().update(new ChapterListBean(data.getNoteUrl(), data.getDurChapterIndex(), data.getDurChapterUrl(), data.getDurChapterName(), data.getTag(), true)); + } + return bookContentBean; + } + }); + } else { + return Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().delete(data); + e.onNext(bookContentBean); + e.onComplete(); + } + }); + } + } + }) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.newThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(BookContentBean value) { + if(isStartDownload){ + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if(isStartDownload){ + toDownload(); + }else{ + isPause(); + } + } + },800); + }else{ + isPause(); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + int time = durTime + 1; + downloading(data, time); + } + }); + } else { + if (isStartDownload) { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().delete(data); + e.onNext(true); + e.onComplete(); + } + }) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.newThread()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(Boolean value) { + if(isStartDownload){ + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if(isStartDownload){ + toDownload(); + }else{ + isPause(); + } + } + },800); + }else{ + isPause(); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + if(!isStartDownload) + isPause(); + } + }); + } else + isPause(); + } + } + + public void startDownload() { + isStartDownload = true; + toDownload(); + } + + public void pauseDownload() { + isStartDownload = false; + notifyManager.cancelAll(); + } + + public void cancelDownload() { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll(); + e.onNext(new Object()); + e.onComplete(); + } + }) + .subscribeOn(AndroidSchedulers.mainThread()) + .observeOn(Schedulers.io()) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onNext(Object value) { + pauseDownload(); + } + + @Override + public void onError(Throwable e) { + + } + + @Override + public void onComplete() { + + } + }); + } + + private void isPause() { + isDownloading = false; + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + List bookShelfBeanList = DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().queryBuilder().orderDesc(BookShelfBeanDao.Properties.FinalDate).list(); + if (bookShelfBeanList != null && bookShelfBeanList.size() > 0) { + for (BookShelfBean bookItem : bookShelfBeanList) { + if (!bookItem.getTag().equals(BookShelfBean.LOCAL_TAG)) { + List downloadChapterList = DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().queryBuilder().where(DownloadChapterBeanDao.Properties.NoteUrl.eq(bookItem.getNoteUrl())).orderAsc(DownloadChapterBeanDao.Properties.DurChapterIndex).limit(1).list(); + if (downloadChapterList != null && downloadChapterList.size() > 0) { + e.onNext(downloadChapterList.get(0)); + e.onComplete(); + return; + } + } + } + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll(); + e.onNext(new DownloadChapterBean()); + } else { + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll(); + e.onNext(new DownloadChapterBean()); + } + e.onComplete(); + } + }).subscribeOn(AndroidSchedulers.mainThread()) + .observeOn(Schedulers.io()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(DownloadChapterBean value) { + if (value.getNoteUrl() != null && value.getNoteUrl().length() > 0){ + RxBus.get().post(RxBusTag.PAUSE_DOWNLOAD_LISTENER, new Object()); + }else{ + RxBus.get().post(RxBusTag.FINISH_DOWNLOAD_LISTENER, new Object()); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + } + }); + } + + private void isProgress(DownloadChapterBean downloadChapterBean) { + RxBus.get().post(RxBusTag.PROGRESS_DOWNLOAD_LISTENER, downloadChapterBean); + + Intent mainIntent = new Intent(this, MainActivity.class); + PendingIntent mainPendingIntent = PendingIntent.getActivity(this, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT); + //创建 Notification.Builder 对象 + NotificationCompat.Builder builder = new NotificationCompat.Builder(this) + .setSmallIcon(R.mipmap.ic_launcher) + //点击通知后自动清除 + .setAutoCancel(true) + .setContentTitle("正在下载:"+downloadChapterBean.getBookName()) + .setContentText(downloadChapterBean.getDurChapterName()==null?" ":downloadChapterBean.getDurChapterName()) + .setContentIntent(mainPendingIntent); + //发送通知 + notifyManager.notify(notifiId, builder.build()); + } + + private void finishDownload() { + RxBus.get().post(RxBusTag.FINISH_DOWNLOAD_LISTENER, new Object()); + notifyManager.cancelAll(); + new Handler(Looper.getMainLooper()).post(new Runnable() { + @Override + public void run() { + Toast.makeText(getApplicationContext(), "全部离线章节下载完成", Toast.LENGTH_SHORT).show(); + } + }); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.PAUSE_DOWNLOAD) + } + ) + public void pauseTask(Object o) { + pauseDownload(); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.START_DOWNLOAD) + } + ) + public void startTask(Object o) { + startDownload(); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.CANCEL_DOWNLOAD) + } + ) + public void cancelTask(Object o) { + cancelDownload(); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.ADD_DOWNLOAD_TASK) + } + ) + public void addTask(DownloadChapterListBean newData) { + addNewTask(newData.getData()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/utils/BlurTransformation.java b/app/src/main/java/com/monke/monkeybook/utils/BlurTransformation.java new file mode 100644 index 0000000000..0ef4399da6 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/utils/BlurTransformation.java @@ -0,0 +1,95 @@ +package com.monke.monkeybook.utils; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.renderscript.Allocation; +import android.renderscript.Element; +import android.renderscript.RenderScript; +import android.renderscript.ScriptIntrinsicBlur; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; + +public class BlurTransformation extends BitmapTransformation { + private static int MAX_RADIUS = 25; + private static int DEFAULT_DOWN_SAMPLING = 1; + + private Context mContext; + private BitmapPool mBitmapPool; + + private int mRadius; + private int mSampling; + + public BlurTransformation(Context context) { + this(context, Glide.get(context).getBitmapPool(), MAX_RADIUS, DEFAULT_DOWN_SAMPLING); + } + + @Override + protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { + + int width = toTransform.getWidth(); + int height = toTransform.getHeight(); + int scaledWidth = width / mSampling; + int scaledHeight = height / mSampling; + + Bitmap bitmap = mBitmapPool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); + if (bitmap == null) { + bitmap = Bitmap.createBitmap(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888); + } + + Canvas canvas = new Canvas(bitmap); + canvas.scale(1 / (float) mSampling, 1 / (float) mSampling); + Paint paint = new Paint(); + paint.setFlags(Paint.FILTER_BITMAP_FLAG); + canvas.drawBitmap(toTransform, 0, 0, paint); + + RenderScript rs = RenderScript.create(mContext); + Allocation input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE, + Allocation.USAGE_SCRIPT); + Allocation output = Allocation.createTyped(rs, input.getType()); + ScriptIntrinsicBlur blur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); + + blur.setInput(input); + blur.setRadius(mRadius); + blur.forEach(output); + output.copyTo(bitmap); + + rs.destroy(); + + return bitmap; + } + + public BlurTransformation(Context context, BitmapPool pool) { + this(context, pool, MAX_RADIUS, DEFAULT_DOWN_SAMPLING); + } + + public BlurTransformation(Context context, BitmapPool pool, int radius) { + this(context, pool, radius, DEFAULT_DOWN_SAMPLING); + } + + public BlurTransformation(Context context, int radius) { + this(context, Glide.get(context).getBitmapPool(), radius, DEFAULT_DOWN_SAMPLING); + } + + public BlurTransformation(Context context, BitmapPool pool, int radius, int sampling) { + super(context); + mContext = context; + mBitmapPool = pool; + mRadius = radius; + mSampling = sampling; + } + + public BlurTransformation(Context context, int radius, int sampling) { + super(context); + mContext = context; + mBitmapPool = Glide.get(context).getBitmapPool(); + mRadius = radius; + mSampling = sampling; + } + + @Override public String getId() { + return "BlurTransformation(radius=" + mRadius + ", sampling=" + mSampling + ")"; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/utils/DensityUtil.java b/app/src/main/java/com/monke/monkeybook/utils/DensityUtil.java new file mode 100644 index 0000000000..844c6a7344 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/utils/DensityUtil.java @@ -0,0 +1,89 @@ +package com.monke.monkeybook.utils; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Point; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.Display; +import android.view.WindowManager; +import java.lang.reflect.Method; + +public class DensityUtil { + /** + * dp转px + * + * @param context + * @param + * @return + */ + public static int dp2px(Context context, float dpVal) + { + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, + dpVal, context.getResources().getDisplayMetrics()); + } + + /** + * sp转px + * + * @param context + * @param + * @return + */ + public static int sp2px(Context context, float spVal) + { + return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, + spVal, context.getResources().getDisplayMetrics()); + } + + /** + * px转dp + * + * @param context + * @param pxVal + * @return + */ + public static float px2dp(Context context, float pxVal) + { + final float scale = context.getResources().getDisplayMetrics().density; + return (pxVal / scale); + } + + /** + * px转sp + * + * @param + * @param pxVal + * @return + */ + public static float px2sp(Context context, float pxVal) + { + return (pxVal / context.getResources().getDisplayMetrics().scaledDensity); + } + public static Point getDisplayPoint(Context context){ + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = windowManager.getDefaultDisplay(); + DisplayMetrics displayMetrics = new DisplayMetrics(); + @SuppressWarnings("rawtypes") + Class c; + try { + c = Class.forName("android.view.Display"); + @SuppressWarnings("unchecked") + Method method = c.getMethod("getRealMetrics",DisplayMetrics.class); + method.invoke(display, displayMetrics); + return new Point(displayMetrics.widthPixels ,displayMetrics.heightPixels ); + }catch(Exception e){ + e.printStackTrace(); + } + DisplayMetrics dm = new DisplayMetrics(); + ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(dm); + return new Point(dm.widthPixels ,dm.heightPixels); + } + + public static int getWindowWidth(Context context){ + WindowManager wm = (WindowManager) context + .getSystemService(Context.WINDOW_SERVICE); + int width = wm.getDefaultDisplay().getWidth(); + return width; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/utils/NetworkUtil.java b/app/src/main/java/com/monke/monkeybook/utils/NetworkUtil.java new file mode 100644 index 0000000000..66d0613245 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/utils/NetworkUtil.java @@ -0,0 +1,43 @@ +package com.monke.monkeybook.utils; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import com.monke.monkeybook.MApplication; +import com.monke.monkeybook.R; +import java.util.HashMap; +import java.util.Map; + +public class NetworkUtil { + private static final Map errorMap = new HashMap<>(); + + public static final int SUCCESS = 10000; + public static final int ERROR_CODE_NONET = 10001; + public static final int ERROR_CODE_OUTTIME = 10002; + public static final int ERROR_CODE_ANALY = 10003; + + static{ + errorMap.put(ERROR_CODE_NONET, MApplication.getInstance().getString(R.string.net_error_10001)); + errorMap.put(ERROR_CODE_OUTTIME, MApplication.getInstance().getString(R.string.net_error_10002)); + errorMap.put(ERROR_CODE_ANALY, MApplication.getInstance().getString(R.string.net_error_10003)); + } + + public static String getErrorTip(int code) { + return errorMap.get(code); + } + + public static boolean isNetWorkAvailable() { + ConnectivityManager manager = (ConnectivityManager) MApplication.getInstance() + .getSystemService(Context.CONNECTIVITY_SERVICE); + if (manager != null) { + NetworkInfo info = manager.getActiveNetworkInfo(); + if (info != null && info.isConnected()) { + return true; + } else { + return false; + } + } else { + return false; + } + } +} diff --git a/app/src/main/java/com/monke/monkeybook/utils/NumberUtil.java b/app/src/main/java/com/monke/monkeybook/utils/NumberUtil.java new file mode 100644 index 0000000000..8f78a67e0b --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/utils/NumberUtil.java @@ -0,0 +1,62 @@ +package com.monke.monkeybook.utils; + +public class NumberUtil { + + /** + * 中文数字转阿拉伯数字 + */ + private static int chineseNumber2Int(String chineseNumber){ + int result = 0; + int temp = 1;//存放一个单位的数字如:十万 + int count = 0;//判断是否有chArr + char[] cnArr = new char[]{'一','二','三','四','五','六','七','八','九'}; + char[] chArr = new char[]{'十','百','千','万','亿'}; + for (int i = 0; i < chineseNumber.length(); i++) { + boolean b = true;//判断是否是chArr + char c = chineseNumber.charAt(i); + for (int j = 0; j < cnArr.length; j++) {//非单位,即数字 + if (c == cnArr[j]) { + if(0 != count){//添加下一个单位之前,先把上一个单位值添加到结果中 + result += temp; + temp = 1; + count = 0; + } + // 下标+1,就是对应的值 + temp = j + 1; + b = false; + break; + } + } + if(b){//单位{'十','百','千','万','亿'} + for (int j = 0; j < chArr.length; j++) { + if (c == chArr[j]) { + switch (j) { + case 0: + temp *= 10; + break; + case 1: + temp *= 100; + break; + case 2: + temp *= 1000; + break; + case 3: + temp *= 10000; + break; + case 4: + temp *= 100000000; + break; + default: + break; + } + count++; + } + } + } + if (i == chineseNumber.length() - 1) {//遍历到最后一个字符 + result += temp; + } + } + return result; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/utils/PremissionCheck.java b/app/src/main/java/com/monke/monkeybook/utils/PremissionCheck.java new file mode 100644 index 0000000000..8509c2501a --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/utils/PremissionCheck.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 ZED, Inc. + * + * This code contain confidential information from ZED Technologies Co.,Ltd., + * which is intended only for the person or entity whose address is listed above. + * Any use of the information contained herein in any way (including, but not limited to, + * total or partial disclosure, reproduction, or dissemination) + * by persons other than the intended recipient(s) is prohibited + * + */ +package com.monke.monkeybook.utils; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; +import android.support.v4.content.PermissionChecker; + +/** + *

版权所有:2016-深圳市得色科技有限公司

+ *

+ *

类描述:

+ *

创建人:章钦豪

+ *

创建时间:2017/1/16

+ *

修改人:

+ *

修改时间:

+ *

修改备注:

+ * + * @version V1.0 + */ +public class PremissionCheck { + public static Boolean checkPremission(Context context,String permission){ + boolean result = false; + if (getTargetSdkVersion(context) >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + result = context.checkSelfPermission(permission) + == PackageManager.PERMISSION_GRANTED; + } else { + // targetSdkVersion < Android M, we have to use PermissionChecker + result = PermissionChecker.checkSelfPermission(context, permission) + == PermissionChecker.PERMISSION_GRANTED; + } + return result; + } + + private static int getTargetSdkVersion(Context context) { + int version = 0; + try { + final PackageInfo info = context.getPackageManager().getPackageInfo( + context.getPackageName(), 0); + version = info.applicationInfo.targetSdkVersion; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + return version; + } + public static void requestPermissionSetting(Context from) { + try { + Intent localIntent = new Intent(); + localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + if (Build.VERSION.SDK_INT >= 9) { + localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS"); + localIntent.setData(Uri.fromParts("package", from.getPackageName(), null)); + } else if (Build.VERSION.SDK_INT <= 8) { + localIntent.setAction(Intent.ACTION_VIEW); + localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails"); + localIntent.putExtra("com.android.settings.ApplicationPkgName", from.getPackageName()); + } + from.startActivity(localIntent); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/view/IBookDetailView.java b/app/src/main/java/com/monke/monkeybook/view/IBookDetailView.java new file mode 100644 index 0000000000..ced321949d --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/IBookDetailView.java @@ -0,0 +1,9 @@ +package com.monke.monkeybook.view; + +import com.monke.basemvplib.IView; + +public interface IBookDetailView extends IView{ + public void updateView(); + + public void getBookShelfError(); +} diff --git a/app/src/main/java/com/monke/monkeybook/view/IBookReadView.java b/app/src/main/java/com/monke/monkeybook/view/IBookReadView.java new file mode 100644 index 0000000000..0fc4ab44ed --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/IBookReadView.java @@ -0,0 +1,27 @@ +package com.monke.monkeybook.view; + +import android.graphics.Paint; +import com.monke.basemvplib.IView; + +public interface IBookReadView extends IView{ + + public Paint getPaint(); + + public int getContentWidth(); + + public void initContentSuccess(int durChapterIndex, int chapterAll, int durPageIndex); + + public void startLoadingBook(); + + public void setHpbReadProgressMax(int count); + + public void initPop(); + + public void showLoadBook(); + + public void dimissLoadBook(); + + public void loadLocationBookError(); + + public void showDownloadMenu(); +} diff --git a/app/src/main/java/com/monke/monkeybook/view/IChoiceBookView.java b/app/src/main/java/com/monke/monkeybook/view/IChoiceBookView.java new file mode 100644 index 0000000000..78641a1228 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/IChoiceBookView.java @@ -0,0 +1,29 @@ +package com.monke.monkeybook.view; + +import com.monke.basemvplib.IView; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.view.adapter.ChoiceBookAdapter; +import java.util.List; + +public interface IChoiceBookView extends IView{ + + public void refreshSearchBook(List books); + + public void loadMoreSearchBook(List books); + + public void refreshFinish(Boolean isAll); + + public void loadMoreFinish(Boolean isAll); + + public void searchBookError(); + + public void addBookShelfSuccess(List searchBooks); + + public void addBookShelfFailed(int code); + + public ChoiceBookAdapter getSearchBookAdapter(); + + public void updateSearchItem(int index); + + public void startRefreshAnim(); +} diff --git a/app/src/main/java/com/monke/monkeybook/view/IImportBookView.java b/app/src/main/java/com/monke/monkeybook/view/IImportBookView.java new file mode 100644 index 0000000000..1c69df4cb1 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/IImportBookView.java @@ -0,0 +1,15 @@ +package com.monke.monkeybook.view; + +import com.monke.basemvplib.IView; +import java.io.File; + +public interface IImportBookView extends IView{ + + public void addNewBook(File newFile); + + public void searchFinish(); + + public void addSuccess(); + + public void addError(); +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/view/ILibraryView.java b/app/src/main/java/com/monke/monkeybook/view/ILibraryView.java new file mode 100644 index 0000000000..5348d8788a --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/ILibraryView.java @@ -0,0 +1,10 @@ +package com.monke.monkeybook.view; + +import com.monke.basemvplib.IView; +import com.monke.monkeybook.bean.LibraryBean; + +public interface ILibraryView extends IView{ + + public void updateUI(LibraryBean library); + public void finishRefresh(); +} diff --git a/app/src/main/java/com/monke/monkeybook/view/IMainView.java b/app/src/main/java/com/monke/monkeybook/view/IMainView.java new file mode 100644 index 0000000000..6e2656fd5a --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/IMainView.java @@ -0,0 +1,24 @@ +package com.monke.monkeybook.view; + +import com.monke.basemvplib.IView; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.view.adapter.BookShelfAdapter; + +import java.util.List; + +public interface IMainView extends IView{ + + public void refreshBookShelf(List bookShelfBeanList); + + public void activityRefreshView(); + + public void refreshFinish(); + + public void refreshError(String error); + + public List getBookShelfAdapterDatas(); + + public void refreshRecyclerViewItemAdd(); + + public void setRecyclerMaxProgress(int x); +} diff --git a/app/src/main/java/com/monke/monkeybook/view/ISearchView.java b/app/src/main/java/com/monke/monkeybook/view/ISearchView.java new file mode 100644 index 0000000000..67f9aacfd2 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/ISearchView.java @@ -0,0 +1,37 @@ +package com.monke.monkeybook.view; + +import android.widget.EditText; + +import com.monke.basemvplib.IView; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.bean.SearchHistoryBean; +import com.monke.monkeybook.view.adapter.SearchBookAdapter; + +import java.util.List; + +public interface ISearchView extends IView{ + + public void insertSearchHistorySuccess(SearchHistoryBean searchHistoryBean); + + public void querySearchHistorySuccess(List datas); + + public void refreshSearchBook(List books); + + public void loadMoreSearchBook(List books); + + public void refreshFinish(Boolean isAll); + + public void loadMoreFinish(Boolean isAll); + + public void searchBookError(Boolean isRefresh); + + public EditText getEdtContent(); + + public void addBookShelfFailed(int code); + + public SearchBookAdapter getSearchBookAdapter(); + + public void updateSearchItem(int index); + + public Boolean checkIsExist(SearchBookBean searchBookBean); +} diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/BookShelfAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/BookShelfAdapter.java new file mode 100644 index 0000000000..0073beae8f --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/adapter/BookShelfAdapter.java @@ -0,0 +1,421 @@ +package com.monke.monkeybook.view.adapter; + +import android.os.Handler; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.widget.refreshview.RefreshRecyclerViewAdapter; +import com.monke.mprogressbar.MHorProgressBar; +import com.monke.mprogressbar.OnProgressListener; +import java.util.ArrayList; +import java.util.List; +import me.grantland.widget.AutofitTextView; + +public class BookShelfAdapter extends RefreshRecyclerViewAdapter { + private final int TYPE_LASTEST = 1; + private final int TYPE_OTHER = 2; + + private final long DURANIMITEM = 130; //item动画启动间隔 + + private List books; + + private Boolean needAnim = true; + + private OnItemClickListener itemClickListener; + + public interface OnItemClickListener { + public void toSearch(); + + public void onClick(BookShelfBean bookShelfBean, int index); + + public void onLongClick(View view, BookShelfBean bookShelfBean, int index); + } + + public BookShelfAdapter() { + super(false); + books = new ArrayList<>(); + } + + @Override + public int getItemcount() { + if (books.size() == 0) { + return 1; + } else { + if (books.size() % 3 == 0) { + return 1 + books.size() / 3; + } else { + return 1 + (books.size() / 3 + 1); + } + } + } + + public int getRealItemCount() { + return books.size(); + } + + @Override + public int getItemViewtype(int position) { + if (position == 0) { + return TYPE_LASTEST; + } else { + return TYPE_OTHER; + } + } + + @Override + public RecyclerView.ViewHolder onCreateViewholder(ViewGroup parent, int viewType) { + if (viewType == TYPE_LASTEST) { + return new LastestViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_bookshelf_lastest, parent, false)); + } else { + return new OtherViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_bookshelf_other, parent, false)); + } + } + + @Override + public void onBindViewholder(RecyclerView.ViewHolder holder, int position) { + if (holder.getItemViewType() == TYPE_LASTEST) { + bindLastestViewHolder((LastestViewHolder) holder, position); + } else { + bindOtherViewHolder((OtherViewHolder) holder, position - 1); + } + } + + private void bindOtherViewHolder(final OtherViewHolder holder, int index) { + final int index_1 = index * 3; + if (needAnim) { + final Animation animation = AnimationUtils.loadAnimation(holder.flContent_1.getContext(), R.anim.anim_bookshelf_item); + animation.setAnimationListener(new AnimatontStartListener() { + @Override + void onAnimStart(Animation animation) { + needAnim = false; + holder.flContent_1.setVisibility(View.VISIBLE); + } + }); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (null != holder) + holder.flContent_1.startAnimation(animation); + } + }, index_1 * DURANIMITEM); + } else { + holder.flContent_1.setVisibility(View.VISIBLE); + } + Glide.with(holder.ivCover_1.getContext()).load(books.get(index_1).getBookInfoBean().getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(holder.ivCover_1); + holder.tvName_1.setText(books.get(index_1).getBookInfoBean().getName()); + + holder.ibContent_1.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (itemClickListener != null) + itemClickListener.onClick(books.get(index_1), index_1); + } + }); + holder.ibContent_1.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (itemClickListener != null) { + itemClickListener.onLongClick(holder.ivCover_1, books.get(index_1), index_1); + return true; + } else + return false; + } + }); + + final int index_2 = index_1 + 1; + if (index_2 < books.size()) { + if (needAnim) { + final Animation animation = AnimationUtils.loadAnimation(holder.flContent_2.getContext(), R.anim.anim_bookshelf_item); + animation.setAnimationListener(new AnimatontStartListener() { + @Override + void onAnimStart(Animation animation) { + needAnim = false; + holder.flContent_2.setVisibility(View.VISIBLE); + } + }); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (null != holder) + holder.flContent_2.startAnimation(animation); + } + }, index_2 * DURANIMITEM); + } else { + holder.flContent_2.setVisibility(View.VISIBLE); + } + Glide.with(holder.ivCover_2.getContext()).load(books.get(index_2).getBookInfoBean().getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(holder.ivCover_2); + holder.tvName_2.setText(books.get(index_2).getBookInfoBean().getName()); + + holder.ibContent_2.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (itemClickListener != null) + itemClickListener.onClick(books.get(index_2), index_2); + } + }); + holder.ibContent_2.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (itemClickListener != null) { + if (itemClickListener != null) + itemClickListener.onLongClick(holder.ivCover_2, books.get(index_2), index_2); + return true; + } else + return false; + } + }); + + final int index_3 = index_2 + 1; + if (index_3 < books.size()) { + if (needAnim) { + final Animation animation = AnimationUtils.loadAnimation(holder.flContent_3.getContext(), R.anim.anim_bookshelf_item); + animation.setAnimationListener(new AnimatontStartListener() { + @Override + void onAnimStart(Animation animation) { + needAnim = false; + holder.flContent_3.setVisibility(View.VISIBLE); + } + }); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (null != holder) + holder.flContent_3.startAnimation(animation); + } + }, index_3 * DURANIMITEM); + } else { + holder.flContent_3.setVisibility(View.VISIBLE); + } + Glide.with(holder.ivCover_3.getContext()).load(books.get(index_3).getBookInfoBean().getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(holder.ivCover_3); + holder.tvName_3.setText(books.get(index_3).getBookInfoBean().getName()); + + holder.ibContent_3.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (itemClickListener != null) + itemClickListener.onClick(books.get(index_3), index_3); + } + }); + holder.ibContent_3.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (itemClickListener != null) { + if (itemClickListener != null) + itemClickListener.onLongClick(holder.ivCover_3, books.get(index_3), index_3); + return true; + } else + return false; + } + }); + }else{ + holder.flContent_3.setVisibility(View.INVISIBLE); + } + }else{ + holder.flContent_2.setVisibility(View.INVISIBLE); + holder.flContent_3.setVisibility(View.INVISIBLE); + } + } + + private void bindLastestViewHolder(final LastestViewHolder holder, final int index) { + if (books.size() == 0) { + holder.tvWatch.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != itemClickListener) { + itemClickListener.toSearch(); + } + } + }); + holder.ivCover.setImageResource(R.drawable.img_cover_default); + holder.flLastestTip.setVisibility(View.INVISIBLE); + holder.tvName.setText("最近阅读的书在这里"); + holder.tvDurprogress.setText(""); + holder.llDurcursor.setVisibility(View.INVISIBLE); + holder.mpbDurprogress.setVisibility(View.INVISIBLE); + holder.mpbDurprogress.setProgressListener(null); + holder.tvWatch.setText("去选书"); + } else { + Glide.with(holder.ivCover.getContext()).load(books.get(index).getBookInfoBean().getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(holder.ivCover); + + holder.flLastestTip.setVisibility(View.VISIBLE); + + holder.tvName.setText(String.format(holder.tvName.getContext().getString(R.string.tv_book_name), books.get(index).getBookInfoBean().getName())); + + if (null != books.get(index).getBookInfoBean() && null != books.get(index).getBookInfoBean().getChapterlist() && books.get(index).getBookInfoBean().getChapterlist().size() > books.get(index).getDurChapter()) { + holder.tvDurprogress.setText(String.format(holder.tvDurprogress.getContext().getString(R.string.tv_read_durprogress), books.get(index).getBookInfoBean().getChapterlist().get(books.get(index).getDurChapter()).getDurChapterName())); + } + holder.llDurcursor.setVisibility(View.VISIBLE); + holder.mpbDurprogress.setVisibility(View.VISIBLE); + holder.mpbDurprogress.setMaxProgress(books.get(index).getBookInfoBean().getChapterlist().size()); + float speed = books.get(index).getBookInfoBean().getChapterlist().size()*1.0f/100; + + holder.mpbDurprogress.setSpeed(speed<=0?1:speed); + holder.mpbDurprogress.setProgressListener(new OnProgressListener() { + @Override + public void moveStartProgress(float dur) { + + } + + @Override + public void durProgressChange(float dur) { + float rate = dur / holder.mpbDurprogress.getMaxProgress(); + holder.llDurcursor.setPadding((int) (holder.mpbDurprogress.getMeasuredWidth() * rate), 0, 0, 0); + } + + @Override + public void moveStopProgress(float dur) { + + } + + @Override + public void setDurProgress(float dur) { + + } + }); + if (needAnim) { + holder.mpbDurprogress.setDurProgressWithAnim(books.get(index).getDurChapter()); + } else { + holder.mpbDurprogress.setDurProgress(books.get(index).getDurChapter()); + } + holder.tvWatch.setText("继续阅读"); + holder.tvWatch.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != itemClickListener) { + itemClickListener.onClick(books.get(index), index); + } + } + }); + } + } + + public void setItemClickListener(OnItemClickListener itemClickListener) { + this.itemClickListener = itemClickListener; + } + + public Boolean getNeedAnim() { + return needAnim; + } + + public void setNeedAnim(Boolean needAnim) { + this.needAnim = needAnim; + } + + class LastestViewHolder extends RecyclerView.ViewHolder { + ImageView ivCover; + FrameLayout flLastestTip; + AutofitTextView tvName; + AutofitTextView tvDurprogress; + LinearLayout llDurcursor; + MHorProgressBar mpbDurprogress; + TextView tvWatch; + + public LastestViewHolder(View itemView) { + super(itemView); + ivCover = (ImageView) itemView.findViewById(R.id.iv_cover); + flLastestTip = (FrameLayout) itemView.findViewById(R.id.fl_lastest_tip); + tvName = (AutofitTextView) itemView.findViewById(R.id.tv_name); + tvDurprogress = (AutofitTextView) itemView.findViewById(R.id.tv_durprogress); + llDurcursor = (LinearLayout) itemView.findViewById(R.id.ll_durcursor); + mpbDurprogress = (MHorProgressBar) itemView.findViewById(R.id.mpb_durprogress); + tvWatch = (TextView) itemView.findViewById(R.id.tv_watch); + } + } + + class OtherViewHolder extends RecyclerView.ViewHolder { + FrameLayout flContent_1; + ImageView ivCover_1; + AutofitTextView tvName_1; + ImageButton ibContent_1; + + FrameLayout flContent_2; + ImageView ivCover_2; + AutofitTextView tvName_2; + ImageButton ibContent_2; + + FrameLayout flContent_3; + ImageView ivCover_3; + AutofitTextView tvName_3; + ImageButton ibContent_3; + + public OtherViewHolder(View itemView) { + super(itemView); + flContent_1 = (FrameLayout) itemView.findViewById(R.id.fl_content_1); + ivCover_1 = (ImageView) itemView.findViewById(R.id.iv_cover_1); + tvName_1 = (AutofitTextView) itemView.findViewById(R.id.tv_name_1); + ibContent_1 = (ImageButton) itemView.findViewById(R.id.ib_content_1); + + flContent_2 = (FrameLayout) itemView.findViewById(R.id.fl_content_2); + ivCover_2 = (ImageView) itemView.findViewById(R.id.iv_cover_2); + tvName_2 = (AutofitTextView) itemView.findViewById(R.id.tv_name_2); + ibContent_2 = (ImageButton) itemView.findViewById(R.id.ib_content_2); + + flContent_3 = (FrameLayout) itemView.findViewById(R.id.fl_content_3); + ivCover_3 = (ImageView) itemView.findViewById(R.id.iv_cover_3); + tvName_3 = (AutofitTextView) itemView.findViewById(R.id.tv_name_3); + ibContent_3 = (ImageButton) itemView.findViewById(R.id.ib_content_3); + } + } + + abstract class AnimatontStartListener implements Animation.AnimationListener { + + @Override + public void onAnimationStart(Animation animation) { + onAnimStart(animation); + } + + @Override + public void onAnimationEnd(Animation animation) { + + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + + abstract void onAnimStart(Animation animation); + } + + public synchronized void replaceAll(List newDatas) { + books.clear(); + if (null != newDatas && newDatas.size() > 0) { + books.addAll(newDatas); + } + order(); + + notifyDataSetChanged(); + } + + private void order() { + if (books != null && books.size() > 0) { + for (int i = 0; i < books.size(); i++) { + int temp = i; + for (int j = i + 1; j < books.size(); j++) { + if (books.get(temp).getFinalDate() < books.get(j).getFinalDate()) { + temp = j; + } + } + BookShelfBean tempBookShelfBean = books.get(i); + books.set(i, books.get(temp)); + books.set(temp, tempBookShelfBean); + } + } + } + + public List getBooks() { + return books; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/ChapterListAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/ChapterListAdapter.java new file mode 100644 index 0000000000..5bd2b80e46 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/adapter/ChapterListAdapter.java @@ -0,0 +1,93 @@ +package com.monke.monkeybook.view.adapter; + +import android.graphics.Color; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.widget.ChapterListView; + +public class ChapterListAdapter extends RecyclerView.Adapter { + private BookShelfBean bookShelfBean; + private ChapterListView.OnItemClickListener itemClickListener; + private int index = 0; + private Boolean isAsc = true; + + public ChapterListAdapter(BookShelfBean bookShelfBean, @NonNull ChapterListView.OnItemClickListener itemClickListener) { + this.bookShelfBean = bookShelfBean; + this.itemClickListener = itemClickListener; + } + + @Override + public Viewholder onCreateViewHolder(ViewGroup parent, int viewType) { + return new Viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_adapter_chapterlist, parent, false)); + } + + @Override + public void onBindViewHolder(Viewholder holder, final int posiTion) { + if (posiTion == getItemCount() - 1) { + holder.vLine.setVisibility(View.INVISIBLE); + } else + holder.vLine.setVisibility(View.VISIBLE); + + final int position; + if (isAsc) { + position = posiTion; + } else { + position = getItemCount() - 1 - posiTion; + } + holder.tvName.setText(bookShelfBean.getBookInfoBean().getChapterlist().get(position).getDurChapterName()); + holder.flContent.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + setIndex(position); + itemClickListener.itemClick(position); + } + }); + if (position == index) { + holder.flContent.setBackgroundColor(Color.parseColor("#cfcfcf")); + holder.flContent.setClickable(false); + } else { + holder.flContent.setBackgroundResource(R.drawable.bg_ib_pre2); + holder.flContent.setClickable(true); + } + } + + @Override + public int getItemCount() { + if (bookShelfBean == null) + return 0; + else + return bookShelfBean.getBookInfoBean().getChapterlist().size(); + } + + public class Viewholder extends RecyclerView.ViewHolder { + private FrameLayout flContent; + private TextView tvName; + private View vLine; + + public Viewholder(View itemView) { + super(itemView); + flContent = (FrameLayout) itemView.findViewById(R.id.fl_content); + tvName = (TextView) itemView.findViewById(R.id.tv_name); + vLine = itemView.findViewById(R.id.v_line); + } + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + notifyItemChanged(this.index); + this.index = index; + notifyItemChanged(this.index); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/ChoiceBookAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/ChoiceBookAdapter.java new file mode 100644 index 0000000000..f07ce6e6c0 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/adapter/ChoiceBookAdapter.java @@ -0,0 +1,177 @@ +package com.monke.monkeybook.view.adapter; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.widget.refreshview.RefreshRecyclerViewAdapter; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +public class ChoiceBookAdapter extends RefreshRecyclerViewAdapter { + private List searchBooks; + + public interface OnItemClickListener { + public void clickAddShelf(View clickView, int position, SearchBookBean searchBookBean); + + public void clickItem(View animView, int position, SearchBookBean searchBookBean); + } + + private OnItemClickListener itemClickListener; + + public ChoiceBookAdapter() { + super(true); + searchBooks = new ArrayList<>(); + } + + @Override + public RecyclerView.ViewHolder onCreateViewholder(ViewGroup parent, int viewType) { + return new Viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_searchbook_item, parent, false)); + } + + @Override + public void onBindViewholder(final RecyclerView.ViewHolder holder, final int position) { + final int realposition = position; + Glide.with(((Viewholder) holder).ivCover.getContext()) + .load(searchBooks.get(realposition).getCoverUrl()) + .diskCacheStrategy(DiskCacheStrategy.RESULT) + .fitCenter() + .dontAnimate() + .placeholder(R.drawable.img_cover_default) + .into(((Viewholder) holder).ivCover); + ((Viewholder) holder).tvName.setText(searchBooks.get(realposition).getName()); + ((Viewholder) holder).tvAuthor.setText(searchBooks.get(realposition).getAuthor()); + String state = searchBooks.get(position).getState(); + if (state == null || state.length() == 0) { + ((Viewholder) holder).tvState.setVisibility(View.GONE); + } else { + ((Viewholder) holder).tvState.setVisibility(View.VISIBLE); + ((Viewholder) holder).tvState.setText(state); + } + long words = searchBooks.get(realposition).getWords(); + if (words <= 0) { + ((Viewholder) holder).tvWords.setVisibility(View.GONE); + } else { + String wordsS = Long.toString(words) + "字"; + if (words > 10000) { + DecimalFormat df = new DecimalFormat("#.#"); + wordsS = df.format(words * 1.0f / 10000f) + "万字"; + } + ((Viewholder) holder).tvWords.setVisibility(View.VISIBLE); + ((Viewholder) holder).tvWords.setText(wordsS); + } + String kind = searchBooks.get(realposition).getKind(); + if (kind == null || kind.length() <= 0) { + ((Viewholder) holder).tvKind.setVisibility(View.GONE); + } else { + ((Viewholder) holder).tvKind.setVisibility(View.VISIBLE); + ((Viewholder) holder).tvKind.setText(kind); + } + if (searchBooks.get(realposition).getLastChapter() != null && searchBooks.get(realposition).getLastChapter().length() > 0) + ((Viewholder) holder).tvLastest.setText(searchBooks.get(realposition).getLastChapter()); + else if (searchBooks.get(realposition).getDesc() != null && searchBooks.get(realposition).getDesc().length() > 0) { + ((Viewholder) holder).tvLastest.setText(searchBooks.get(realposition).getDesc()); + } else + ((Viewholder) holder).tvLastest.setText(""); + if (searchBooks.get(realposition).getOrigin() != null && searchBooks.get(realposition).getOrigin().length() > 0) { + ((Viewholder) holder).tvOrigin.setVisibility(View.VISIBLE); + ((Viewholder) holder).tvOrigin.setText("来源:" + searchBooks.get(realposition).getOrigin()); + } else { + ((Viewholder) holder).tvOrigin.setVisibility(View.GONE); + } + if (searchBooks.get(realposition).getAdd()) { + ((Viewholder) holder).tvAddShelf.setText("已添加"); + ((Viewholder) holder).tvAddShelf.setEnabled(false); + } else { + ((Viewholder) holder).tvAddShelf.setText("+添加"); + ((Viewholder) holder).tvAddShelf.setEnabled(true); + } + + ((Viewholder) holder).flContent.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (itemClickListener != null) + itemClickListener.clickItem(((Viewholder) holder).ivCover, realposition, searchBooks.get(realposition)); + } + }); + ((Viewholder) holder).tvAddShelf.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (itemClickListener != null) + itemClickListener.clickAddShelf(((Viewholder) holder).tvAddShelf, realposition, searchBooks.get(realposition)); + } + }); + } + + @Override + public int getItemViewtype(int position) { + return 0; + } + + @Override + public int getItemcount() { + return searchBooks.size(); + } + + class Viewholder extends RecyclerView.ViewHolder { + FrameLayout flContent; + ImageView ivCover; + TextView tvName; + TextView tvAuthor; + TextView tvState; + TextView tvWords; + TextView tvKind; + TextView tvLastest; + TextView tvAddShelf; + TextView tvOrigin; + + public Viewholder(View itemView) { + super(itemView); + flContent = (FrameLayout) itemView.findViewById(R.id.fl_content); + ivCover = (ImageView) itemView.findViewById(R.id.iv_cover); + tvName = (TextView) itemView.findViewById(R.id.tv_name); + tvAuthor = (TextView) itemView.findViewById(R.id.tv_author); + tvState = (TextView) itemView.findViewById(R.id.tv_state); + tvWords = (TextView) itemView.findViewById(R.id.tv_words); + tvLastest = (TextView) itemView.findViewById(R.id.tv_lastest); + tvAddShelf = (TextView) itemView.findViewById(R.id.tv_addshelf); + tvKind = (TextView) itemView.findViewById(R.id.tv_kind); + tvOrigin = (TextView) itemView.findViewById(R.id.tv_origin); + } + } + + public void setItemClickListener(OnItemClickListener itemClickListener) { + this.itemClickListener = itemClickListener; + } + + public void addAll(List newData) { + if (newData != null && newData.size() > 0) { + int position = getItemcount(); + if (newData != null && newData.size() > 0) { + searchBooks.addAll(newData); + } + notifyItemInserted(position); + notifyItemRangeChanged(position, newData.size()); + } + } + + public void replaceAll(List newData) { + searchBooks.clear(); + if (newData != null && newData.size() > 0) { + searchBooks.addAll(newData); + } + notifyDataSetChanged(); + } + + public List getSearchBooks() { + return searchBooks; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/ImportBookAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/ImportBookAdapter.java new file mode 100644 index 0000000000..7c55a87ab0 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/adapter/ImportBookAdapter.java @@ -0,0 +1,125 @@ +package com.monke.monkeybook.view.adapter; + +import android.os.Environment; +import android.support.annotation.NonNull; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.TextView; +import com.monke.monkeybook.R; +import com.monke.monkeybook.widget.checkbox.SmoothCheckBox; +import java.io.File; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +public class ImportBookAdapter extends RecyclerView.Adapter{ + private List datas; + private List selectDatas; + + public interface OnCheckBookListener{ + public void checkBook(int count); + } + + private OnCheckBookListener checkBookListener; + public ImportBookAdapter(@NonNull OnCheckBookListener checkBookListener){ + datas = new ArrayList<>(); + selectDatas = new ArrayList<>(); + this.checkBookListener = checkBookListener; + } + + @Override + public Viewholder onCreateViewHolder(ViewGroup parent, int viewType) { + return new Viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_adapter_importbook,parent,false)); + } + + @Override + public void onBindViewHolder(final Viewholder holder, final int position) { + holder.tvNmae.setText(datas.get(position).getName()); + holder.tvSize.setText(convertByte(datas.get(position).length())); + holder.tvLoc.setText(datas.get(position).getAbsolutePath().replace(Environment.getExternalStorageDirectory().getAbsolutePath(),"存储空间")); + + holder.scbSelect.setOnCheckedChangeListener(new SmoothCheckBox.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(SmoothCheckBox checkBox, boolean isChecked) { + if(isChecked){ + selectDatas.add(datas.get(position)); + }else{ + selectDatas.remove(datas.get(position)); + } + checkBookListener.checkBook(selectDatas.size()); + } + }); + if(canCheck){ + holder.scbSelect.setVisibility(View.VISIBLE); + holder.llContent.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + holder.scbSelect.setChecked(!holder.scbSelect.isChecked(),true); + } + }); + }else{ + holder.scbSelect.setVisibility(View.INVISIBLE); + holder.llContent.setOnClickListener(null); + } + } + + public void addData(File newItem){ + int position = datas.size(); + datas.add(newItem); + notifyItemInserted(position); + notifyItemRangeChanged(position, 1); + } + + private Boolean canCheck = false; + public void setCanCheck(Boolean canCheck){ + this.canCheck = canCheck; + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return datas.size(); + } + + class Viewholder extends RecyclerView.ViewHolder { + LinearLayout llContent; + TextView tvNmae; + TextView tvSize; + TextView tvLoc; + SmoothCheckBox scbSelect; + + public Viewholder(View itemView) { + super(itemView); + llContent = (LinearLayout) itemView.findViewById(R.id.ll_content); + tvNmae = (TextView) itemView.findViewById(R.id.tv_name); + tvSize = (TextView) itemView.findViewById(R.id.tv_size); + scbSelect = (SmoothCheckBox) itemView.findViewById(R.id.scb_select); + tvLoc = (TextView) itemView.findViewById(R.id.tv_loc); + } + } + + public static String convertByte(long size) { + DecimalFormat df = new DecimalFormat("###.#"); + float f; + if (size < 1024) { + f = size / 1.0f; + return (df.format(new Float(f).doubleValue()) + "B"); + } else if (size < 1024 * 1024) { + f = (float) ((float) size / (float) 1024); + return (df.format(new Float(f).doubleValue()) + "KB"); + } else if (size < 1024 * 1024 * 1024) { + f = (float) ((float) size / (float) (1024 * 1024)); + return (df.format(new Float(f).doubleValue()) + "MB"); + } else { + f = (float) ((float) size / (float) (1024 * 1024 * 1024)); + return (df.format(new Float(f).doubleValue()) + "GB"); + } + } + + public List getSelectDatas() { + return selectDatas; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/SearchBookAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/SearchBookAdapter.java new file mode 100644 index 0000000000..fe52fdacb0 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/adapter/SearchBookAdapter.java @@ -0,0 +1,180 @@ +package com.monke.monkeybook.view.adapter; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.widget.refreshview.RefreshRecyclerViewAdapter; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +public class SearchBookAdapter extends RefreshRecyclerViewAdapter { + private List searchBooks; + + public interface OnItemClickListener { + public void clickAddShelf(View clickView, int position, SearchBookBean searchBookBean); + + public void clickItem(View animView, int position, SearchBookBean searchBookBean); + } + + private OnItemClickListener itemClickListener; + + public SearchBookAdapter() { + super(true); + searchBooks = new ArrayList<>(); + } + + @Override + public RecyclerView.ViewHolder onCreateViewholder(ViewGroup parent, int viewType) { + return new Viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_searchbook_item, parent, false)); + } + + @Override + public void onBindViewholder(final RecyclerView.ViewHolder holder, final int position) { + Glide.with(((Viewholder) holder).ivCover.getContext()) + .load(searchBooks.get(position).getCoverUrl()) + .diskCacheStrategy(DiskCacheStrategy.RESULT) + .centerCrop() + .dontAnimate() + .placeholder(R.drawable.img_cover_default) + .into(((Viewholder) holder).ivCover); + ((Viewholder) holder).tvName.setText(searchBooks.get(position).getName()); + ((Viewholder) holder).tvAuthor.setText(searchBooks.get(position).getAuthor()); + String state = searchBooks.get(position).getState(); + if (state == null || state.length() == 0) { + ((Viewholder) holder).tvState.setVisibility(View.GONE); + } else { + ((Viewholder) holder).tvState.setVisibility(View.VISIBLE); + ((Viewholder) holder).tvState.setText(state); + } + long words = searchBooks.get(position).getWords(); + if (words <= 0) { + ((Viewholder) holder).tvWords.setVisibility(View.GONE); + } else { + String wordsS = Long.toString(words) + "字"; + if (words > 10000) { + DecimalFormat df = new DecimalFormat("#.#"); + wordsS = df.format(words * 1.0f / 10000f) + "万字"; + } + ((Viewholder) holder).tvWords.setVisibility(View.VISIBLE); + ((Viewholder) holder).tvWords.setText(wordsS); + } + String kind = searchBooks.get(position).getKind(); + if (kind == null || kind.length() <= 0) { + ((Viewholder) holder).tvKind.setVisibility(View.GONE); + } else { + ((Viewholder) holder).tvKind.setVisibility(View.VISIBLE); + ((Viewholder) holder).tvKind.setText(kind); + } + if (searchBooks.get(position).getLastChapter() != null && searchBooks.get(position).getLastChapter().length() > 0) + ((Viewholder) holder).tvLastest.setText(searchBooks.get(position).getLastChapter()); + else if (searchBooks.get(position).getDesc() != null && searchBooks.get(position).getDesc().length() > 0) { + ((Viewholder) holder).tvLastest.setText(searchBooks.get(position).getDesc()); + } else + ((Viewholder) holder).tvLastest.setText(""); + if (searchBooks.get(position).getOrigin() != null && searchBooks.get(position).getOrigin().length() > 0) { + ((Viewholder) holder).tvOrigin.setVisibility(View.VISIBLE); + ((Viewholder) holder).tvOrigin.setText("来源:" + searchBooks.get(position).getOrigin()); + } else { + ((Viewholder) holder).tvOrigin.setVisibility(View.GONE); + } + if (searchBooks.get(position).getAdd()) { + ((Viewholder) holder).tvAddShelf.setText("已添加"); + ((Viewholder) holder).tvAddShelf.setEnabled(false); + } else { + ((Viewholder) holder).tvAddShelf.setText("+添加"); + ((Viewholder) holder).tvAddShelf.setEnabled(true); + } + + ((Viewholder) holder).flContent.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (itemClickListener != null) + itemClickListener.clickItem(((Viewholder) holder).ivCover, position, searchBooks.get(position)); + } + }); + ((Viewholder) holder).tvAddShelf.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (itemClickListener != null) + itemClickListener.clickAddShelf(((Viewholder) holder).tvAddShelf, position, searchBooks.get(position)); + } + }); + } + + @Override + public int getItemViewtype(int position) { + return 0; + } + + @Override + public int getItemcount() { + return searchBooks.size(); + } + + class Viewholder extends RecyclerView.ViewHolder { + FrameLayout flContent; + ImageView ivCover; + TextView tvName; + TextView tvAuthor; + TextView tvState; + TextView tvWords; + TextView tvKind; + TextView tvLastest; + TextView tvAddShelf; + TextView tvOrigin; + + public Viewholder(View itemView) { + super(itemView); + flContent = (FrameLayout) itemView.findViewById(R.id.fl_content); + ivCover = (ImageView) itemView.findViewById(R.id.iv_cover); + tvName = (TextView) itemView.findViewById(R.id.tv_name); + tvAuthor = (TextView) itemView.findViewById(R.id.tv_author); + tvState = (TextView) itemView.findViewById(R.id.tv_state); + tvWords = (TextView) itemView.findViewById(R.id.tv_words); + tvLastest = (TextView) itemView.findViewById(R.id.tv_lastest); + tvAddShelf = (TextView) itemView.findViewById(R.id.tv_addshelf); + tvKind = (TextView) itemView.findViewById(R.id.tv_kind); + tvOrigin = (TextView) itemView.findViewById(R.id.tv_origin); + } + } + + public void setItemClickListener(OnItemClickListener itemClickListener) { + this.itemClickListener = itemClickListener; + } + + public void addAll(List newData) { + if (newData != null && newData.size() > 0) { + int position = getItemcount(); + if (newData != null && newData.size() > 0) { + searchBooks.addAll(newData); + } + notifyItemInserted(position); + notifyItemRangeChanged(position, newData.size()); + } + } + + public void replaceAll(List newData) { + searchBooks.clear(); + if (newData != null && newData.size() > 0) { + searchBooks.addAll(newData); + } + notifyDataSetChanged(); + } + + public List getSearchBooks() { + return searchBooks; + } + + public void setSearchBooks(List searchBooks) { + this.searchBooks = searchBooks; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/view/adapter/SearchHistoryAdapter.java b/app/src/main/java/com/monke/monkeybook/view/adapter/SearchHistoryAdapter.java new file mode 100644 index 0000000000..1419c115e0 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/adapter/SearchHistoryAdapter.java @@ -0,0 +1,53 @@ +package com.monke.monkeybook.view.adapter; + +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.SearchHistoryBean; +import com.monke.monkeybook.widget.flowlayout.FlowLayout; +import com.monke.monkeybook.widget.flowlayout.TagAdapter; +import java.util.ArrayList; + +public class SearchHistoryAdapter extends TagAdapter { + public SearchHistoryAdapter() { + super(new ArrayList()); + } + + public interface OnItemClickListener{ + public void itemClick(SearchHistoryBean searchHistoryBean); + } + private SearchHistoryAdapter.OnItemClickListener onItemClickListener; + + public OnItemClickListener getListener() { + return onItemClickListener; + } + + public void setOnItemClickListener(OnItemClickListener listener) { + this.onItemClickListener = listener; + } + + @Override + public View getView(FlowLayout parent, int position, final SearchHistoryBean searchHistoryBean) { + TextView tv = (TextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_searchhistory_item, + parent, false); + tv.setText(searchHistoryBean.getContent()); + tv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(null != onItemClickListener){ + onItemClickListener.itemClick(searchHistoryBean); + } + } + }); + return tv; + } + + public SearchHistoryBean getItemData(int position){ + return mTagDatas.get(position); + } + + public int getDataSize(){ + return mTagDatas.size(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/view/impl/BookDetailActivity.java b/app/src/main/java/com/monke/monkeybook/view/impl/BookDetailActivity.java new file mode 100644 index 0000000000..5b76b3eebe --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/impl/BookDetailActivity.java @@ -0,0 +1,250 @@ +package com.monke.monkeybook.view.impl; + +import android.content.Intent; +import android.os.Build; +import android.text.method.ScrollingMovementMethod; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.monke.monkeybook.BitIntentDataManager; +import com.monke.monkeybook.R; +import com.monke.monkeybook.base.MBaseActivity; +import com.monke.monkeybook.presenter.IBookDetailPresenter; +import com.monke.monkeybook.presenter.impl.BookDetailPresenterImpl; +import com.monke.monkeybook.presenter.impl.ReadBookPresenterImpl; +import com.monke.monkeybook.utils.BlurTransformation; +import com.monke.monkeybook.view.IBookDetailView; + +public class BookDetailActivity extends MBaseActivity implements IBookDetailView { + + private FrameLayout iflContent; + private ImageView ivBlurCover; + private ImageView ivCover; + private TextView tvName; + private TextView tvAuthor; + private TextView tvOrigin; + private TextView tvChapter; + private TextView tvIntro; + private TextView tvShelf; + private TextView tvRead; + private TextView tvLoading; + + private Animation animHideLoading; + private Animation animShowInfo; + + @Override + protected IBookDetailPresenter initInjector() { + return new BookDetailPresenterImpl(getIntent()); + } + + @Override + protected void onCreateActivity() { + setContentView(R.layout.activity_detail); + } + + @Override + protected void initData() { + animShowInfo = AnimationUtils.loadAnimation(this, android.R.anim.fade_in); + animHideLoading = AnimationUtils.loadAnimation(this, android.R.anim.fade_out); + animHideLoading.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + + } + + @Override + public void onAnimationEnd(Animation animation) { + tvLoading.setVisibility(View.GONE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + } + + + @Override + protected void bindView() { + iflContent = (FrameLayout) findViewById(R.id.ifl_content); + ivBlurCover = (ImageView) findViewById(R.id.iv_blur_cover); + ivCover = (ImageView) findViewById(R.id.iv_cover); + tvName = (TextView) findViewById(R.id.tv_name); + tvAuthor = (TextView) findViewById(R.id.tv_author); + tvOrigin = (TextView) findViewById(R.id.tv_origin); + tvChapter = (TextView) findViewById(R.id.tv_chapter); + tvIntro = (TextView) findViewById(R.id.tv_intro); + tvShelf = (TextView) findViewById(R.id.tv_shelf); + tvRead = (TextView) findViewById(R.id.tv_read); + tvLoading = (TextView) findViewById(R.id.tv_loading); + + tvIntro.setMovementMethod(ScrollingMovementMethod.getInstance()); + initView(); + + updateView(); + } + + @Override + public void updateView() { + if (null != mPresenter.getBookShelf()) { + if (mPresenter.getInBookShelf()) { + if (mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size() > 0) + tvChapter.setText(String.format(getString(R.string.tv_read_durprogress), mPresenter.getBookShelf().getBookInfoBean().getChapterlist().get(mPresenter.getBookShelf().getDurChapter()).getDurChapterName())); + else + tvChapter.setText("无章节"); + tvShelf.setText("移出书架"); + tvRead.setText("继续阅读"); + tvShelf.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //从书架移出 + mPresenter.removeFromBookShelf(); + } + }); + } else { + if (mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size() == 0) { + tvChapter.setText("无章节"); + } else { + tvChapter.setText(String.format(getString(R.string.tv_searchbook_lastest), mPresenter.getBookShelf().getBookInfoBean().getChapterlist().get(mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size() - 1).getDurChapterName())); + } + tvShelf.setText("放入书架"); + tvRead.setText("开始阅读"); + tvShelf.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //放入书架 + mPresenter.addToBookShelf(); + } + }); + } + if (tvIntro.getText().toString().trim().length() == 0) { + tvIntro.setText(mPresenter.getBookShelf().getBookInfoBean().getIntroduce()); + } + if (tvIntro.getVisibility() != View.VISIBLE) { + tvIntro.setVisibility(View.VISIBLE); + tvIntro.startAnimation(animShowInfo); + tvLoading.startAnimation(animHideLoading); + } + if (mPresenter.getBookShelf().getBookInfoBean().getOrigin() != null && mPresenter.getBookShelf().getBookInfoBean().getOrigin().length() > 0) { + tvOrigin.setVisibility(View.VISIBLE); + tvOrigin.setText("来源:" + mPresenter.getBookShelf().getBookInfoBean().getOrigin()); + } else { + tvOrigin.setVisibility(View.GONE); + } + } else { + tvChapter.setText(String.format(getString(R.string.tv_searchbook_lastest), mPresenter.getSearchBook().getLastChapter())); + tvShelf.setText("放入书架"); + tvRead.setText("开始阅读"); + tvRead.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //放入书架 + } + }); + tvIntro.setVisibility(View.INVISIBLE); + tvLoading.setVisibility(View.VISIBLE); + tvLoading.setText("加载中..."); + } + tvLoading.setOnClickListener(null); + } + + @Override + public void getBookShelfError() { + tvLoading.setVisibility(View.VISIBLE); + tvLoading.setText("加载失败,点击重试"); + tvLoading.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + tvLoading.setText("加载中..."); + tvLoading.setOnClickListener(null); + mPresenter.getBookShelfInfo(); + } + }); + } + + @Override + protected void firstRequest() { + super.firstRequest(); + if (mPresenter.getOpenfrom() == BookDetailPresenterImpl.FROM_SEARCH && mPresenter.getBookShelf() == null) { + //网络请求 + mPresenter.getBookShelfInfo(); + } + } + + private void initView() { + String coverUrl; + String name; + String author; + if (mPresenter.getOpenfrom() == BookDetailPresenterImpl.FROM_BOOKSHELF) { + coverUrl = mPresenter.getBookShelf().getBookInfoBean().getCoverUrl(); + name = mPresenter.getBookShelf().getBookInfoBean().getName(); + author = mPresenter.getBookShelf().getBookInfoBean().getAuthor(); + if (mPresenter.getBookShelf().getBookInfoBean().getOrigin() != null && mPresenter.getBookShelf().getBookInfoBean().getOrigin().length() > 0) { + tvOrigin.setVisibility(View.VISIBLE); + tvOrigin.setText("来源:" + mPresenter.getBookShelf().getBookInfoBean().getOrigin()); + } else { + tvOrigin.setVisibility(View.GONE); + } + } else { + coverUrl = mPresenter.getSearchBook().getCoverUrl(); + name = mPresenter.getSearchBook().getName(); + author = mPresenter.getSearchBook().getAuthor(); + if (mPresenter.getSearchBook().getOrigin() != null && mPresenter.getSearchBook().getOrigin().length() > 0) { + tvOrigin.setVisibility(View.VISIBLE); + tvOrigin.setText("来源:" + mPresenter.getSearchBook().getOrigin()); + } else { + tvOrigin.setVisibility(View.GONE); + } + } + + Glide.with(this).load(coverUrl).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(ivCover); + Glide.with(this).load(coverUrl).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().bitmapTransform(new BlurTransformation(this, 6)).into(ivBlurCover); + tvName.setText(name); + tvAuthor.setText(author); + } + + @Override + protected void bindEvent() { + iflContent.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + finishAfterTransition(); + } else { + finish(); + } + } + }); + + tvRead.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //进入阅读 + Intent intent = new Intent(BookDetailActivity.this, ReadBookActivity.class); + intent.putExtra("from", ReadBookPresenterImpl.OPEN_FROM_APP); + String key = String.valueOf(System.currentTimeMillis()); + intent.putExtra("data_key", key); + try { + BitIntentDataManager.getInstance().putData(key, mPresenter.getBookShelf().clone()); + } catch (CloneNotSupportedException e) { + BitIntentDataManager.getInstance().putData(key, mPresenter.getBookShelf()); + e.printStackTrace(); + } + startActivityByAnim(intent, android.R.anim.fade_in, android.R.anim.fade_out); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + finishAfterTransition(); + } else { + finish(); + } + } + }); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/view/impl/ChoiceBookActivity.java b/app/src/main/java/com/monke/monkeybook/view/impl/ChoiceBookActivity.java new file mode 100644 index 0000000000..379ee62a70 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/impl/ChoiceBookActivity.java @@ -0,0 +1,198 @@ +package com.monke.monkeybook.view.impl; + +import android.content.Context; +import android.content.Intent; +import android.support.v7.widget.LinearLayoutManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.TextView; +import android.widget.Toast; +import com.monke.monkeybook.R; +import com.monke.monkeybook.base.MBaseActivity; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.presenter.IChoiceBookPresenter; +import com.monke.monkeybook.presenter.impl.BookDetailPresenterImpl; +import com.monke.monkeybook.presenter.impl.ChoiceBookPresenterImpl; +import com.monke.monkeybook.utils.NetworkUtil; +import com.monke.monkeybook.view.adapter.ChoiceBookAdapter; +import com.monke.monkeybook.view.IChoiceBookView; +import com.monke.monkeybook.widget.refreshview.BaseRefreshListener; +import com.monke.monkeybook.widget.refreshview.OnLoadMoreListener; +import com.monke.monkeybook.widget.refreshview.RefreshRecyclerView; +import java.util.List; + +public class ChoiceBookActivity extends MBaseActivity implements IChoiceBookView { + private ImageButton ivReturn; + private TextView tvTitle; + private RefreshRecyclerView rfRvSearchBooks; + private ChoiceBookAdapter searchBookAdapter; + + public static void startChoiceBookActivity(Context context,String title,String url){ + Intent intent = new Intent(context,ChoiceBookActivity.class); + intent.putExtra("url",url); + intent.putExtra("title",title); + context.startActivity(intent); + } + + @Override + protected IChoiceBookPresenter initInjector() { + return new ChoiceBookPresenterImpl(getIntent()); + } + + @Override + protected void onCreateActivity() { + setContentView(R.layout.activity_bookchoice); + } + + @Override + protected void initData() { + searchBookAdapter = new ChoiceBookAdapter(); + } + + @Override + protected void bindView() { + ivReturn = (ImageButton) findViewById(R.id.iv_return); + tvTitle = (TextView) findViewById(R.id.tv_title); + tvTitle.setText(mPresenter.getTitle()); + rfRvSearchBooks = (RefreshRecyclerView) findViewById(R.id.rfRv_search_books); + rfRvSearchBooks.setRefreshRecyclerViewAdapter(searchBookAdapter, new LinearLayoutManager(this)); + + View viewRefreshError = LayoutInflater.from(this).inflate(R.layout.view_searchbook_refresherror, null); + viewRefreshError.findViewById(R.id.tv_refresh_again).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + searchBookAdapter.replaceAll(null); + //刷新失败 ,重试 + mPresenter.initPage(); + mPresenter.toSearchBooks(null); + startRefreshAnim(); + } + }); + rfRvSearchBooks.setNoDataAndrRefreshErrorView(LayoutInflater.from(this).inflate(R.layout.view_searchbook_nodata, null), + viewRefreshError); + } + + @Override + protected void bindEvent() { + ivReturn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + searchBookAdapter.setItemClickListener(new ChoiceBookAdapter.OnItemClickListener() { + @Override + public void clickAddShelf(View clickView, int position, SearchBookBean searchBookBean) { + mPresenter.addBookToShelf(searchBookBean); + } + + @Override + public void clickItem(View animView, int position, SearchBookBean searchBookBean) { + Intent intent = new Intent(ChoiceBookActivity.this, BookDetailActivity.class); + intent.putExtra("from", BookDetailPresenterImpl.FROM_SEARCH); + intent.putExtra("data", searchBookBean); + startActivityByAnim(intent, animView, "img_cover", android.R.anim.fade_in, android.R.anim.fade_out); + } + }); + + rfRvSearchBooks.setBaseRefreshListener(new BaseRefreshListener() { + @Override + public void startRefresh() { + mPresenter.initPage(); + mPresenter.toSearchBooks(null); + startRefreshAnim(); + } + }); + rfRvSearchBooks.setLoadMoreListener(new OnLoadMoreListener() { + @Override + public void startLoadmore() { + mPresenter.toSearchBooks(null); + } + + @Override + public void loadMoreErrorTryAgain() { + mPresenter.toSearchBooks(null); + } + }); + } + + @Override + public void refreshSearchBook(List books) { + searchBookAdapter.replaceAll(books); + } + + @Override + public void refreshFinish(Boolean isAll) { + rfRvSearchBooks.finishRefresh(isAll, true); + } + + @Override + public void loadMoreFinish(Boolean isAll) { + rfRvSearchBooks.finishLoadMore(isAll, true); + } + + @Override + public void loadMoreSearchBook(final List books) { + searchBookAdapter.addAll(books); + } + + @Override + public void searchBookError() { + if (mPresenter.getPage() > 1) { + rfRvSearchBooks.loadMoreError(); + } else { + //刷新失败 + rfRvSearchBooks.refreshError(); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + @Override + public void addBookShelfSuccess(List datas) { + searchBookAdapter.notifyDataSetChanged(); + } + + @Override + public void addBookShelfFailed(int code) { + Toast.makeText(this, NetworkUtil.getErrorTip(code), Toast.LENGTH_SHORT).show(); + } + + @Override + public ChoiceBookAdapter getSearchBookAdapter() { + return searchBookAdapter; + } + + @Override + public void updateSearchItem(int index) { + int tempIndex = index; + if (tempIndex < searchBookAdapter.getItemcount()) { + int startIndex = ((LinearLayoutManager) rfRvSearchBooks.getRecyclerView().getLayoutManager()).findFirstVisibleItemPosition(); + TextView tvAddShelf = (TextView) ((ViewGroup) rfRvSearchBooks.getRecyclerView()).getChildAt(tempIndex - startIndex).findViewById(R.id.tv_addshelf); + if (tvAddShelf != null) { + if (searchBookAdapter.getSearchBooks().get(index).getAdd()) { + tvAddShelf.setText("已添加"); + tvAddShelf.setEnabled(false); + } else { + tvAddShelf.setText("+添加"); + tvAddShelf.setEnabled(true); + } + } + } + } + + @Override + public void startRefreshAnim() { + rfRvSearchBooks.startRefresh(); + } + + @Override + protected void firstRequest() { + super.firstRequest(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/view/impl/ImportBookActivity.java b/app/src/main/java/com/monke/monkeybook/view/impl/ImportBookActivity.java new file mode 100644 index 0000000000..4df65f1b09 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/impl/ImportBookActivity.java @@ -0,0 +1,220 @@ +package com.monke.monkeybook.view.impl; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.pm.PackageManager; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.KeyEvent; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; +import com.monke.monkeybook.R; +import com.monke.monkeybook.base.MBaseActivity; +import com.monke.monkeybook.presenter.IImportBookPresenter; +import com.monke.monkeybook.presenter.impl.ImportBookPresenterImpl; +import com.monke.monkeybook.utils.PremissionCheck; +import com.monke.monkeybook.view.IImportBookView; +import com.monke.monkeybook.view.adapter.ImportBookAdapter; +import com.monke.monkeybook.widget.modialog.MoProgressHUD; +import com.victor.loading.rotate.RotateLoading; +import java.io.File; + +public class ImportBookActivity extends MBaseActivity implements IImportBookView { + private LinearLayout llContent; + private ImageButton ivReturn; + private TextView tvScan; + + private RotateLoading rlLoading; + private TextView tvCount; + + private TextView tvAddshelf; + + private RecyclerView rcvBooks; + + private ImportBookAdapter importBookAdapter; + + private Animation animIn; + private Animation animOut; + + private MoProgressHUD moProgressHUD; + @Override + protected IImportBookPresenter initInjector() { + return new ImportBookPresenterImpl(); + } + + @Override + protected void onCreateActivity() { + setContentView(R.layout.activity_importbook); + } + + @Override + protected void initData() { + animIn = AnimationUtils.loadAnimation(this, R.anim.anim_act_importbook_in); + animOut = AnimationUtils.loadAnimation(this, R.anim.anim_act_importbook_out); + + importBookAdapter = new ImportBookAdapter(new ImportBookAdapter.OnCheckBookListener() { + @Override + public void checkBook(int count) { + tvAddshelf.setVisibility(count == 0 ? View.INVISIBLE : View.VISIBLE); + } + }); + } + + @Override + protected void bindView() { + moProgressHUD = new MoProgressHUD(this); + + llContent = (LinearLayout) findViewById(R.id.ll_content); + ivReturn = (ImageButton) findViewById(R.id.iv_return); + tvScan = (TextView) findViewById(R.id.tv_scan); + + rlLoading = (RotateLoading) findViewById(R.id.rl_loading); + tvCount = (TextView) findViewById(R.id.tv_count); + + tvAddshelf = (TextView) findViewById(R.id.tv_addshelf); + + rcvBooks = (RecyclerView) findViewById(R.id.rcv_books); + rcvBooks.setAdapter(importBookAdapter); + rcvBooks.setLayoutManager(new LinearLayoutManager(this)); + } + + @Override + protected void bindEvent() { + tvScan.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PremissionCheck.checkPremission(ImportBookActivity.this, + Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + //申请权限 + ImportBookActivity.this.requestPermissions( + new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + 0x11); + } else { + mPresenter.searchLocationBook(); + tvScan.setVisibility(View.INVISIBLE); + rlLoading.start(); + } + } + }); + animOut.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + + } + + @Override + public void onAnimationEnd(Animation animation) { + ImportBookActivity.super.finish(); + overridePendingTransition(0, 0); + isExiting = false; + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + ivReturn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + + tvAddshelf.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //添加书籍 + moProgressHUD.showLoading("放入书架中..."); + mPresenter.importBooks(importBookAdapter.getSelectDatas()); + } + }); + } + + @Override + protected void firstRequest() { + llContent.startAnimation(animIn); + } + + private Boolean isExiting = false; + + @Override + public void finish() { + if (!isExiting) { + if(moProgressHUD.isShow()){ + moProgressHUD.dismiss(); + } + isExiting = true; + llContent.startAnimation(animOut); + } + } + + @Override + public void addNewBook(File newFile) { + importBookAdapter.addData(newFile); + tvCount.setText(String.format(getString(R.string.tv_importbook_count), String.valueOf(importBookAdapter.getItemCount()))); + } + + @Override + public void searchFinish() { + rlLoading.stop(); + rlLoading.setVisibility(View.INVISIBLE); + importBookAdapter.setCanCheck(true); + } + + @Override + public void addSuccess() { + moProgressHUD.dismiss(); + Toast.makeText(this,"添加书籍成功",Toast.LENGTH_SHORT).show(); + } + + @Override + public void addError() { + moProgressHUD.showInfo("放入书架失败!"); + } + + @SuppressLint("NewApi") + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if(requestCode == 0x11){ + if (grantResults != null && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && PremissionCheck.checkPremission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + mPresenter.searchLocationBook(); + tvScan.setVisibility(View.INVISIBLE); + rlLoading.start(); + }else{ + if (!this.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)){ + moProgressHUD.showTwoButton("去系统设置打开SD卡读写权限?", "取消", new View.OnClickListener() { + @Override + public void onClick(View v) { + moProgressHUD.dismiss(); + } + }, "设置", new View.OnClickListener() { + @Override + public void onClick(View v) { + moProgressHUD.dismiss(); + PremissionCheck.requestPermissionSetting(ImportBookActivity.this); + } + }); + }else{ + Toast.makeText(this, "未获取SD卡读取权限", Toast.LENGTH_SHORT).show(); + } + } + } + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + Boolean a = moProgressHUD.onKeyDown(keyCode,event); + if(a) + return a; + return super.onKeyDown(keyCode, event); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/view/impl/LibraryActivity.java b/app/src/main/java/com/monke/monkeybook/view/impl/LibraryActivity.java new file mode 100644 index 0000000000..0360dfd551 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/impl/LibraryActivity.java @@ -0,0 +1,232 @@ +package com.monke.monkeybook.view.impl; + +import android.content.Intent; +import android.view.Gravity; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import com.monke.monkeybook.R; +import com.monke.monkeybook.base.MBaseActivity; +import com.monke.monkeybook.bean.LibraryBean; +import com.monke.monkeybook.bean.LibraryNewBookBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.presenter.ILibraryPresenter; +import com.monke.monkeybook.presenter.impl.BookDetailPresenterImpl; +import com.monke.monkeybook.presenter.impl.LibraryPresenterImpl; +import com.monke.monkeybook.utils.DensityUtil; +import com.monke.monkeybook.view.ILibraryView; +import com.monke.monkeybook.widget.libraryview.LibraryNewBooksView; +import com.monke.monkeybook.widget.libraryview.LibraryKindBookListView; +import com.monke.monkeybook.widget.refreshview.BaseRefreshListener; +import com.monke.monkeybook.widget.refreshview.RefreshProgressBar; +import com.monke.monkeybook.widget.refreshview.RefreshScrollView; +import java.util.Iterator; +import java.util.Map; + +public class LibraryActivity extends MBaseActivity implements ILibraryView { + private RefreshScrollView rscvContent; + private RefreshProgressBar rpbProgress; + + private LinearLayout llContent; + private ImageButton ibReturn; + private FrameLayout flSearch; + + private Animation animIn; + private Animation animOut; + + private LinearLayout kindLl; + + private LibraryNewBooksView lavHotauthor; + private LibraryKindBookListView lkbvKindbooklist; + + @Override + protected ILibraryPresenter initInjector() { + return new LibraryPresenterImpl(); + } + + @Override + protected void onCreateActivity() { + setContentView(R.layout.activity_library); + } + + @Override + protected void firstRequest() { + llContent.startAnimation(animIn); + } + + @Override + protected void initData() { + animIn = AnimationUtils.loadAnimation(this, R.anim.anim_act_importbook_in); + animOut = AnimationUtils.loadAnimation(this, R.anim.anim_act_importbook_out); + } + + @Override + protected void bindView() { + rscvContent = (RefreshScrollView) findViewById(R.id.rscv_content); + rpbProgress = (RefreshProgressBar) findViewById(R.id.rpb_progress); + rscvContent.setRpb(rpbProgress); + + llContent = (LinearLayout) findViewById(R.id.ll_content); + ibReturn = (ImageButton) findViewById(R.id.ib_return); + flSearch = (FrameLayout) findViewById(R.id.fl_search); + + kindLl = (LinearLayout) findViewById(R.id.kind_ll); + initKind(); + + lavHotauthor = (LibraryNewBooksView) findViewById(R.id.lav_hotauthor); + lkbvKindbooklist = (LibraryKindBookListView) findViewById(R.id.lkbv_kindbooklist); + } + + private void initKind() { + int columnCout = 4; + Iterator iterator = mPresenter.getKinds().entrySet().iterator(); + int temp = 0; + LinearLayout.LayoutParams l = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + LinearLayout linearLayout = null; + LinearLayout.LayoutParams tvLp = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + tvLp.weight = 1; + while (iterator.hasNext()) { + final Map.Entry resultTemp = (Map.Entry) iterator.next(); + if (temp % columnCout == 0) { + linearLayout = new LinearLayout(this); + linearLayout.setLayoutParams(l); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); + kindLl.addView(linearLayout); + } + TextView textView = new TextView(this); + textView.setLayoutParams(tvLp); + textView.setText(resultTemp.getKey()); + textView.setGravity(Gravity.CENTER); + textView.setTextSize(14); + textView.setPadding(0, DensityUtil.dp2px(this, 5), 0, DensityUtil.dp2px(this, 5)); + textView.setLines(1); + textView.setTextColor(getResources().getColorStateList(R.color.selector_kind_tv_color)); + textView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + ChoiceBookActivity.startChoiceBookActivity(LibraryActivity.this, resultTemp.getKey(),resultTemp.getValue()); + } + }); + linearLayout.addView(textView); + temp++; + } + int viewCount = mPresenter.getKinds().size() % columnCout == 0?0:(columnCout-mPresenter.getKinds().size() % columnCout); + for(int i=0;i implements IMainView { + private ImageButton ibMoney; + private ImageButton ibLibrary; + private ImageButton ibAdd; + private ImageButton ibDownload; + + private RefreshRecyclerView rfRvShelf; + private BookShelfAdapter bookShelfAdapter; + + private FrameLayout flWarn; + private ImageView ivWarnClose; + + private DownloadListPop downloadListPop; + + @Override + protected IMainPresenter initInjector() { + return new MainPresenterImpl(); + } + + @Override + protected void onCreateActivity() { + setContentView(R.layout.activity_main); + } + + @Override + protected void initData() { + bookShelfAdapter = new BookShelfAdapter(); + } + + @Override + protected void bindView() { + downloadListPop = new DownloadListPop(this); + + rfRvShelf = (RefreshRecyclerView) findViewById(R.id.rf_rv_shelf); + + ibMoney = (ImageButton) findViewById(R.id.ib_money); + ibLibrary = (ImageButton) findViewById(R.id.ib_library); + ibAdd = (ImageButton) findViewById(R.id.ib_add); + ibDownload = (ImageButton) findViewById(R.id.ib_download); + + rfRvShelf.setRefreshRecyclerViewAdapter(bookShelfAdapter, new LinearLayoutManager(this)); + + flWarn = (FrameLayout) findViewById(R.id.fl_warn); + ivWarnClose = (ImageView) findViewById(R.id.iv_warn_close); + } + + @Override + protected void bindEvent() { + bindRvShelfEvent(); + ibDownload.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + downloadListPop.showAsDropDown(ibDownload); + } + }); + ibMoney.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //点击打赏 + } + }); + ibLibrary.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startActivityByAnim(new Intent(MainActivity.this, LibraryActivity.class), 0, 0); + } + }); + ibAdd.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //点击更多 + startActivityByAnim(new Intent(MainActivity.this, ImportBookActivity.class), 0, 0); + } + }); + bookShelfAdapter.setItemClickListener(new BookShelfAdapter.OnItemClickListener() { + @Override + public void toSearch() { + //点击去选书 + startActivityByAnim(new Intent(MainActivity.this, LibraryActivity.class), 0, 0); + } + + @Override + public void onClick(BookShelfBean bookShelfBean, int index) { + Intent intent = new Intent(MainActivity.this, ReadBookActivity.class); + intent.putExtra("from", ReadBookPresenterImpl.OPEN_FROM_APP); + String key = String.valueOf(System.currentTimeMillis()); + intent.putExtra("data_key", key); + try { + BitIntentDataManager.getInstance().putData(key, bookShelfBean.clone()); + } catch (CloneNotSupportedException e) { + BitIntentDataManager.getInstance().putData(key, bookShelfBean); + e.printStackTrace(); + } + startActivityByAnim(intent, android.R.anim.fade_in, android.R.anim.fade_out); + } + + @Override + public void onLongClick(View animView, BookShelfBean bookShelfBean, int index) { + Intent intent = new Intent(MainActivity.this, BookDetailActivity.class); + intent.putExtra("from", BookDetailPresenterImpl.FROM_BOOKSHELF); + String key = String.valueOf(System.currentTimeMillis()); + intent.putExtra("data_key", key); + BitIntentDataManager.getInstance().putData(key, bookShelfBean); + startActivityByAnim(intent, animView, "img_cover", android.R.anim.fade_in, android.R.anim.fade_out); + } + }); + + ivWarnClose.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + flWarn.setVisibility(View.GONE); + } + }); + } + + private void bindRvShelfEvent() { + rfRvShelf.setBaseRefreshListener(new OnRefreshWithProgressListener() { + @Override + public int getMaxProgress() { + return bookShelfAdapter.getBooks().size(); + } + + @Override + public void startRefresh() { + mPresenter.queryBookShelf(true); + } + }); + } + + @Override + protected void firstRequest() { + //通过百度API 判断是否有更新 + try{ + BDAutoUpdateSDK.uiUpdateAction(this, new UICheckUpdateCallback() { + @Override + public void onNoUpdateFound() { + + } + + @Override + public void onCheckComplete() { + + } + }); + }catch (Exception e){ + e.printStackTrace(); + } + mPresenter.queryBookShelf(false); + } + + @Override + public void refreshBookShelf(List bookShelfBeanList) { + bookShelfAdapter.replaceAll(bookShelfBeanList); + } + + @Override + public void activityRefreshView() { + //执行刷新响应 + rfRvShelf.startRefresh(); + } + + @Override + public void refreshFinish() { + rfRvShelf.finishRefresh(false, true); + } + + @Override + public void refreshError(String error) { + refreshFinish(); + Toast.makeText(this, error, Toast.LENGTH_SHORT).show(); + } + + @Override + public List getBookShelfAdapterDatas() { + return bookShelfAdapter.getBooks(); + } + + @Override + public void refreshRecyclerViewItemAdd() { + rfRvShelf.getRpb().setDurProgress(rfRvShelf.getRpb().getDurProgress() + 1); + } + + @Override + public void setRecyclerMaxProgress(int x) { + rfRvShelf.getRpb().setMaxProgress(x); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + exit(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + downloadListPop.onDestroy(); + } + + private long exitTime = 0; + + public void exit() { + if ((System.currentTimeMillis() - exitTime) > 2000) { + Toast.makeText(getApplicationContext(), "再按一次退出程序", + Toast.LENGTH_SHORT).show(); + exitTime = System.currentTimeMillis(); + } else { + finish(); + System.exit(0); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/view/impl/ReadBookActivity.java b/app/src/main/java/com/monke/monkeybook/view/impl/ReadBookActivity.java new file mode 100644 index 0000000000..7484b7fdbc --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/impl/ReadBookActivity.java @@ -0,0 +1,566 @@ +package com.monke.monkeybook.view.impl; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Paint; +import android.os.Build; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.hwangjr.rxbus.RxBus; +import com.monke.basemvplib.AppActivityManager; +import com.monke.monkeybook.R; +import com.monke.monkeybook.base.MBaseActivity; +import com.monke.monkeybook.bean.DownloadChapterBean; +import com.monke.monkeybook.bean.DownloadChapterListBean; +import com.monke.monkeybook.common.RxBusTag; +import com.monke.monkeybook.presenter.IBookReadPresenter; +import com.monke.monkeybook.presenter.impl.ReadBookPresenterImpl; +import com.monke.monkeybook.utils.DensityUtil; +import com.monke.monkeybook.utils.PremissionCheck; +import com.monke.monkeybook.view.IBookReadView; +import com.monke.monkeybook.view.popupwindow.ReadBookMenuMorePop; +import com.monke.monkeybook.widget.ChapterListView; +import com.monke.monkeybook.view.popupwindow.CheckAddShelfPop; +import com.monke.monkeybook.view.popupwindow.FontPop; +import com.monke.monkeybook.view.popupwindow.MoreSettingPop; +import com.monke.monkeybook.view.popupwindow.WindowLightPop; +import com.monke.monkeybook.widget.contentswitchview.BookContentView; +import com.monke.monkeybook.widget.contentswitchview.ContentSwitchView; +import com.monke.monkeybook.widget.modialog.MoProgressHUD; +import com.monke.mprogressbar.MHorProgressBar; +import com.monke.mprogressbar.OnProgressListener; + +import java.util.ArrayList; +import java.util.List; + +import me.grantland.widget.AutofitTextView; + +public class ReadBookActivity extends MBaseActivity implements IBookReadView { + + private FrameLayout flContent; + + private ContentSwitchView csvBook; + + //主菜单 + private FrameLayout flMenu; + private View vMenuBg; + private LinearLayout llMenuTop; + private LinearLayout llMenuBottom; + private ImageButton ivReturn; + private ImageView ivMenuMore; + private AutofitTextView atvTitle; + private TextView tvPre; + private TextView tvNext; + private MHorProgressBar hpbReadProgress; + private LinearLayout llCatalog; + private LinearLayout llLight; + private LinearLayout llFont; + private LinearLayout llSetting; + //主菜单动画 + private Animation menuTopIn; + private Animation menuTopOut; + private Animation menuBottomIn; + private Animation menuBottomOut; + + private CheckAddShelfPop checkAddShelfPop; + private ChapterListView chapterListView; + private WindowLightPop windowLightPop; + private ReadBookMenuMorePop readBookMenuMorePop; + private FontPop fontPop; + private MoreSettingPop moreSettingPop; + + private MoProgressHUD moProgressHUD; + + @Override + protected IBookReadPresenter initInjector() { + return new ReadBookPresenterImpl(); + } + + @Override + protected void onCreateActivity() { + setContentView(R.layout.activity_bookread); + } + + @Override + protected void initData() { + mPresenter.saveProgress(); + menuTopIn = AnimationUtils.loadAnimation(this, R.anim.anim_readbook_top_in); + menuTopIn.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + vMenuBg.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + llMenuTop.startAnimation(menuTopOut); + llMenuBottom.startAnimation(menuBottomOut); + } + }); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + menuBottomIn = AnimationUtils.loadAnimation(this, R.anim.anim_readbook_bottom_in); + + menuTopOut = AnimationUtils.loadAnimation(this, R.anim.anim_readbook_top_out); + menuTopOut.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + vMenuBg.setOnClickListener(null); + } + + @Override + public void onAnimationEnd(Animation animation) { + flMenu.setVisibility(View.INVISIBLE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + menuBottomOut = AnimationUtils.loadAnimation(this, R.anim.anim_readbook_bottom_out); + } + + @Override + protected void bindView() { + moProgressHUD = new MoProgressHUD(this); + + flContent = (FrameLayout) findViewById(R.id.fl_content); + csvBook = (ContentSwitchView) findViewById(R.id.csv_book); + initCsvBook(); + + flMenu = (FrameLayout) findViewById(R.id.fl_menu); + vMenuBg = findViewById(R.id.v_menu_bg); + llMenuTop = (LinearLayout) findViewById(R.id.ll_menu_top); + llMenuBottom = (LinearLayout) findViewById(R.id.ll_menu_bottom); + ivReturn = (ImageButton) findViewById(R.id.iv_return); + ivMenuMore = (ImageView) findViewById(R.id.iv_more); + atvTitle = (AutofitTextView) findViewById(R.id.atv_title); + + tvPre = (TextView) findViewById(R.id.tv_pre); + tvNext = (TextView) findViewById(R.id.tv_next); + hpbReadProgress = (MHorProgressBar) findViewById(R.id.hpb_read_progress); + llCatalog = (LinearLayout) findViewById(R.id.ll_catalog); + llLight = (LinearLayout) findViewById(R.id.ll_light); + llFont = (LinearLayout) findViewById(R.id.ll_font); + llSetting = (LinearLayout) findViewById(R.id.ll_setting); + + chapterListView = (ChapterListView) findViewById(R.id.clp_chapterlist); + } + + @Override + public void setHpbReadProgressMax(int count) { + hpbReadProgress.setMaxProgress(count); + } + + private void initCsvBook() { + csvBook.bookReadInit(new ContentSwitchView.OnBookReadInitListener() { + @Override + public void success() { + mPresenter.initData(ReadBookActivity.this); + } + }); + } + + @Override + public void initPop() { + checkAddShelfPop = new CheckAddShelfPop(this, mPresenter.getBookShelf().getBookInfoBean().getName(), new CheckAddShelfPop.OnItemClickListener() { + @Override + public void clickExit() { + finish(); + } + + @Override + public void clickAddShelf() { + mPresenter.addToShelf(null); + checkAddShelfPop.dismiss(); + } + }); + chapterListView.setData(mPresenter.getBookShelf(), new ChapterListView.OnItemClickListener() { + @Override + public void itemClick(int index) { + csvBook.setInitData(index, mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size(), BookContentView.DURPAGEINDEXBEGIN); + } + }); + + windowLightPop = new WindowLightPop(this); + windowLightPop.initLight(); + + fontPop = new FontPop(this, new FontPop.OnChangeProListener() { + @Override + public void textChange(int index) { + csvBook.changeTextSize(); + } + + @Override + public void bgChange(int index) { + csvBook.changeBg(); + } + }); + + readBookMenuMorePop = new ReadBookMenuMorePop(this); + readBookMenuMorePop.setOnClickDownload(new View.OnClickListener() { + @Override + public void onClick(View v) { + readBookMenuMorePop.dismiss(); + if (flMenu.getVisibility() == View.VISIBLE) { + llMenuTop.startAnimation(menuTopOut); + llMenuBottom.startAnimation(menuBottomOut); + } + //弹出离线下载界面 + int endIndex = mPresenter.getBookShelf().getDurChapter() + 50; + if (endIndex >= mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size()) { + endIndex = mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size() - 1; + } + moProgressHUD.showDownloadList(mPresenter.getBookShelf().getDurChapter(), endIndex, mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size(), new MoProgressHUD.OnClickDownload() { + @Override + public void download(final int start, final int end) { + moProgressHUD.dismiss(); + mPresenter.addToShelf(new ReadBookPresenterImpl.OnAddListner() { + @Override + public void addSuccess() { + List result = new ArrayList(); + for (int i = start; i <= end; i++) { + DownloadChapterBean item = new DownloadChapterBean(); + item.setNoteUrl(mPresenter.getBookShelf().getNoteUrl()); + item.setDurChapterIndex(mPresenter.getBookShelf().getBookInfoBean().getChapterlist().get(i).getDurChapterIndex()); + item.setDurChapterName(mPresenter.getBookShelf().getBookInfoBean().getChapterlist().get(i).getDurChapterName()); + item.setDurChapterUrl(mPresenter.getBookShelf().getBookInfoBean().getChapterlist().get(i).getDurChapterUrl()); + item.setTag(mPresenter.getBookShelf().getTag()); + item.setBookName(mPresenter.getBookShelf().getBookInfoBean().getName()); + item.setCoverUrl(mPresenter.getBookShelf().getBookInfoBean().getCoverUrl()); + result.add(item); + } + RxBus.get().post(RxBusTag.ADD_DOWNLOAD_TASK, new DownloadChapterListBean(result)); + } + }); + + } + }); + } + }); + + moreSettingPop = new MoreSettingPop(this); + } + + @Override + protected void bindEvent() { + hpbReadProgress.setProgressListener(new OnProgressListener() { + @Override + public void moveStartProgress(float dur) { + + } + + @Override + public void durProgressChange(float dur) { + + } + + @Override + public void moveStopProgress(float dur) { + int realDur = (int) Math.ceil(dur); + if (realDur < 1) { + realDur = 1; + } + if ((realDur - 1) != mPresenter.getBookShelf().getDurChapter()) { + csvBook.setInitData(realDur - 1, mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size(), BookContentView.DURPAGEINDEXBEGIN); + } + if (hpbReadProgress.getDurProgress() != realDur) + hpbReadProgress.setDurProgress(realDur); + } + + @Override + public void setDurProgress(float dur) { + if (hpbReadProgress.getMaxProgress() == 1) { + tvPre.setEnabled(false); + tvNext.setEnabled(false); + } else { + if (dur == 1) { + tvPre.setEnabled(false); + tvNext.setEnabled(true); + } else if (dur == hpbReadProgress.getMaxProgress()) { + tvPre.setEnabled(true); + tvNext.setEnabled(false); + } else { + tvPre.setEnabled(true); + tvNext.setEnabled(true); + } + } + } + }); + ivReturn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }); + ivMenuMore.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + readBookMenuMorePop.showAsDropDown(ivMenuMore, 0, DensityUtil.dp2px(ReadBookActivity.this, -3.5f)); + } + }); + csvBook.setLoadDataListener(new ContentSwitchView.LoadDataListener() { + @Override + public void loaddata(BookContentView bookContentView, long qtag, int chapterIndex, int pageIndex) { + mPresenter.loadContent(bookContentView, qtag, chapterIndex, pageIndex); + } + + @Override + public void updateProgress(int chapterIndex, int pageIndex) { + mPresenter.updateProgress(chapterIndex, pageIndex); + + if (mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size() > 0) + atvTitle.setText(mPresenter.getBookShelf().getBookInfoBean().getChapterlist().get(mPresenter.getBookShelf().getDurChapter()).getDurChapterName()); + else + atvTitle.setText("无章节"); + if (hpbReadProgress.getDurProgress() != chapterIndex + 1) + hpbReadProgress.setDurProgress(chapterIndex + 1); + } + + @Override + public String getChapterTitle(int chapterIndex) { + return mPresenter.getChapterTitle(chapterIndex); + } + + @Override + public void initData(int lineCount) { + mPresenter.setPageLineCount(lineCount); + mPresenter.initContent(); + } + + @Override + public void showMenu() { + flMenu.setVisibility(View.VISIBLE); + llMenuTop.startAnimation(menuTopIn); + llMenuBottom.startAnimation(menuBottomIn); + } + }); + + tvPre.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + csvBook.setInitData(mPresenter.getBookShelf().getDurChapter() - 1, mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size(), BookContentView.DURPAGEINDEXBEGIN); + } + }); + tvNext.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + csvBook.setInitData(mPresenter.getBookShelf().getDurChapter() + 1, mPresenter.getBookShelf().getBookInfoBean().getChapterlist().size(), BookContentView.DURPAGEINDEXBEGIN); + } + }); + + llCatalog.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + llMenuTop.startAnimation(menuTopOut); + llMenuBottom.startAnimation(menuBottomOut); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + chapterListView.show(mPresenter.getBookShelf().getDurChapter()); + } + }, menuTopOut.getDuration()); + } + }); + + llLight.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + llMenuTop.startAnimation(menuTopOut); + llMenuBottom.startAnimation(menuBottomOut); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + windowLightPop.showAtLocation(flContent, Gravity.BOTTOM, 0, 0); + } + }, menuTopOut.getDuration()); + } + }); + + llFont.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + llMenuTop.startAnimation(menuTopOut); + llMenuBottom.startAnimation(menuBottomOut); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + fontPop.showAtLocation(flContent, Gravity.BOTTOM, 0, 0); + } + }, menuTopOut.getDuration()); + } + }); + + llSetting.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + llMenuTop.startAnimation(menuTopOut); + llMenuBottom.startAnimation(menuBottomOut); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + moreSettingPop.showAtLocation(flContent, Gravity.BOTTOM, 0, 0); + } + }, menuTopOut.getDuration()); + } + }); + } + + @Override + public Paint getPaint() { + return csvBook.getTextPaint(); + } + + @Override + public int getContentWidth() { + return csvBook.getContentWidth(); + } + + @Override + public void initContentSuccess(int durChapterIndex, int chapterAll, int durPageIndex) { + csvBook.setInitData(durChapterIndex, chapterAll, durPageIndex); + } + + @Override + public void startLoadingBook() { + csvBook.startLoading(); + } + + @Override + protected void onPause() { + super.onPause(); + mPresenter.saveProgress(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + Boolean mo = moProgressHUD.onKeyDown(keyCode, event); + if (mo) + return mo; + else { + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (flMenu.getVisibility() == View.VISIBLE) { + llMenuTop.startAnimation(menuTopOut); + llMenuBottom.startAnimation(menuBottomOut); + return true; + } else if (!mPresenter.getAdd() && checkAddShelfPop != null && !checkAddShelfPop.isShowing()) { + checkAddShelfPop.showAtLocation(flContent, Gravity.CENTER, 0, 0); + return true; + } else { + Boolean temp2 = chapterListView.dimissChapterList(); + if (temp2) + return true; + else { + finish(); + return true; + } + } + } else { + Boolean temp = csvBook.onKeyDown(keyCode, event); + if (temp) + return true; + } + return super.onKeyDown(keyCode, event); + } + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + Boolean temp = csvBook.onKeyUp(keyCode, event); + if (temp) + return true; + return super.onKeyUp(keyCode, event); + } + + @Override + public void showLoadBook() { + moProgressHUD.showLoading("文本导入中..."); + } + + @Override + public void dimissLoadBook() { + moProgressHUD.dismiss(); + } + + @Override + public void loadLocationBookError() { + csvBook.loadError(); + } + + @Override + public void showDownloadMenu() { + ivMenuMore.setVisibility(View.VISIBLE); + } + + private Boolean showCheckPremission = false; + + @SuppressLint("NewApi") + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (requestCode == 0x11) { + if (grantResults != null && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && PremissionCheck.checkPremission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + mPresenter.openBookFromOther(ReadBookActivity.this); + } else { + if (!this.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + showCheckPremission = true; + moProgressHUD.showTwoButton("去系统设置打开SD卡读写权限?", "取消", new View.OnClickListener() { + @Override + public void onClick(View v) { + finish(); + } + }, "设置", new View.OnClickListener() { + @Override + public void onClick(View v) { + PremissionCheck.requestPermissionSetting(ReadBookActivity.this); + } + }); + } else { + Toast.makeText(this, "未获取SD卡读取权限", Toast.LENGTH_SHORT).show(); + } + } + } + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + + @Override + protected void onResume() { + super.onResume(); + if (showCheckPremission && mPresenter.getOpen_from() == ReadBookPresenterImpl.OPEN_FROM_OTHER && !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PremissionCheck.checkPremission(this, + Manifest.permission.WRITE_EXTERNAL_STORAGE))) { + showCheckPremission = true; + mPresenter.openBookFromOther(this); + } + } + + @Override + public void finish() { + if (!AppActivityManager.getInstance().isExist(MainActivity.class)) { + Intent intent = new Intent(this, MainActivity.class); + startActivity(intent); + } + super.finish(); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/view/impl/SearchActivity.java b/app/src/main/java/com/monke/monkeybook/view/impl/SearchActivity.java new file mode 100644 index 0000000000..efc93110cc --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/impl/SearchActivity.java @@ -0,0 +1,526 @@ +package com.monke.monkeybook.view.impl; + +import android.animation.Animator; +import android.content.Context; +import android.content.Intent; +import android.graphics.Rect; +import android.os.Build; +import android.os.Handler; +import android.support.v7.widget.LinearLayoutManager; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewAnimationUtils; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; +import com.daimajia.androidanimations.library.Techniques; +import com.daimajia.androidanimations.library.YoYo; +import com.monke.immerselayout.StatusBarUtils; +import com.monke.monkeybook.R; +import com.monke.monkeybook.base.MBaseActivity; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.bean.SearchHistoryBean; +import com.monke.monkeybook.presenter.ISearchPresenter; +import com.monke.monkeybook.presenter.impl.BookDetailPresenterImpl; +import com.monke.monkeybook.presenter.impl.SearchPresenterImpl; +import com.monke.monkeybook.utils.NetworkUtil; +import com.monke.monkeybook.view.ISearchView; +import com.monke.monkeybook.view.adapter.SearchBookAdapter; +import com.monke.monkeybook.view.adapter.SearchHistoryAdapter; +import com.monke.monkeybook.widget.flowlayout.TagFlowLayout; +import com.monke.monkeybook.widget.refreshview.OnLoadMoreListener; +import com.monke.monkeybook.widget.refreshview.RefreshRecyclerView; +import java.util.List; +import tyrantgit.explosionfield.ExplosionField; + +public class SearchActivity extends MBaseActivity implements ISearchView { + private FrameLayout flSearchContent; + private EditText edtContent; + private TextView tvTosearch; + + private LinearLayout llSearchHistory; + private TextView tvSearchHistoryClean; + private TagFlowLayout tflSearchHistory; + private SearchHistoryAdapter searchHistoryAdapter; + private Animation animHistory; + private Animator animHistory5; + private ExplosionField explosionField; + + private RefreshRecyclerView rfRvSearchBooks; + private SearchBookAdapter searchBookAdapter; + + @Override + protected ISearchPresenter initInjector() { + return new SearchPresenterImpl(); + } + + @Override + protected void onCreateActivity() { + setContentView(R.layout.activity_search); + } + + @Override + protected void initData() { + + explosionField = ExplosionField.attach2Window(this); + searchHistoryAdapter = new SearchHistoryAdapter(); + + searchBookAdapter = new SearchBookAdapter(); + } + + @Override + protected void bindView() { + flSearchContent = (FrameLayout) findViewById(R.id.fl_search_content); + edtContent = (EditText) findViewById(R.id.edt_content); + tvTosearch = (TextView) findViewById(R.id.tv_tosearch); + + llSearchHistory = (LinearLayout) findViewById(R.id.ll_search_history); + tvSearchHistoryClean = (TextView) findViewById(R.id.tv_search_history_clean); + tflSearchHistory = (TagFlowLayout) findViewById(R.id.tfl_search_history); + tflSearchHistory.setAdapter(searchHistoryAdapter); + + rfRvSearchBooks = (RefreshRecyclerView) findViewById(R.id.rfRv_search_books); + rfRvSearchBooks.setRefreshRecyclerViewAdapter(searchBookAdapter, new LinearLayoutManager(this)); + + View viewRefreshError = LayoutInflater.from(this).inflate(R.layout.view_searchbook_refresherror, null); + viewRefreshError.findViewById(R.id.tv_refresh_again).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + //刷新失败 ,重试 + mPresenter.initPage(); + mPresenter.toSearchBooks(null); + rfRvSearchBooks.startRefresh(); + } + }); + rfRvSearchBooks.setNoDataAndrRefreshErrorView(LayoutInflater.from(this).inflate(R.layout.view_searchbook_nodata, null), + viewRefreshError); + + searchBookAdapter.setItemClickListener(new SearchBookAdapter.OnItemClickListener() { + @Override + public void clickAddShelf(View clickView, int position, SearchBookBean searchBookBean) { + mPresenter.addBookToShelf(searchBookBean); + } + + @Override + public void clickItem(View animView, int position, SearchBookBean searchBookBean) { + Intent intent = new Intent(SearchActivity.this, BookDetailActivity.class); + intent.putExtra("from", BookDetailPresenterImpl.FROM_SEARCH); + intent.putExtra("data", searchBookBean); + startActivityByAnim(intent, animView, "img_cover", android.R.anim.fade_in, android.R.anim.fade_out); + } + }); + } + + @Override + protected void bindEvent() { + + tvSearchHistoryClean.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + for (int i = 0; i < tflSearchHistory.getChildCount(); i++) { + explosionField.explode(tflSearchHistory.getChildAt(i)); + } + mPresenter.cleanSearchHistory(); + } + }); + edtContent.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + edtContent.setSelection(edtContent.length()); + checkTvToSearch(); + mPresenter.querySearchHistory(); + } + }); + edtContent.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_SEARCH || (event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) { + toSearch(); + return true; + } else + return false; + } + }); + tvTosearch.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (!mPresenter.getInput()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + finishAfterTransition(); + } else { + finish(); + } + } else { + //搜索 + toSearch(); + } + } + }); + + searchHistoryAdapter.setOnItemClickListener(new SearchHistoryAdapter.OnItemClickListener() { + @Override + public void itemClick(SearchHistoryBean searchHistoryBean) { + edtContent.setText(searchHistoryBean.getContent()); + toSearch(); + } + }); + + bindKeyBoardEvent(); + + rfRvSearchBooks.setLoadMoreListener(new OnLoadMoreListener() { + @Override + public void startLoadmore() { + mPresenter.toSearchBooks(null); + } + + @Override + public void loadMoreErrorTryAgain() { + mPresenter.toSearchBooks(null); + } + }); + } + + @Override + protected void firstRequest() { + super.firstRequest(); + mPresenter.querySearchHistory(); + } + + //开始搜索 + private void toSearch() { + if (edtContent.getText().toString().trim().length() > 0) { + final String key = edtContent.getText().toString().trim(); + mPresenter.setHasSearch(true); + mPresenter.insertSearchHistory(); + closeKeyBoard(); + //执行搜索请求 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + mPresenter.initPage(); + mPresenter.toSearchBooks(key); + rfRvSearchBooks.startRefresh(); + } + }, 300); + } else { + YoYo.with(Techniques.Shake).playOn(flSearchContent); + } + } + + private void bindKeyBoardEvent() { + llSearchHistory.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + Rect r = new Rect(); + llSearchHistory.getWindowVisibleDisplayFrame(r); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) llSearchHistory.getLayoutParams(); + + int height = llSearchHistory.getContext().getResources().getDisplayMetrics().heightPixels; + int diff = height - r.bottom; + if (diff != 0 && Math.abs(diff) != StatusBarUtils.getNavi_height()) { + if (layoutParams.bottomMargin != diff) { + layoutParams.setMargins(0, 0, 0, Math.abs(diff)); + llSearchHistory.setLayoutParams(layoutParams); + //打开输入 + if (llSearchHistory.getVisibility() != View.VISIBLE) + openOrCloseHistory(true); + } + } else { + if (layoutParams.bottomMargin != 0) { + if (!mPresenter.getHasSearch()) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + finishAfterTransition(); + } else { + finish(); + } + } else { + layoutParams.setMargins(0, 0, 0, 0); + llSearchHistory.setLayoutParams(layoutParams); + //关闭输入 + if (llSearchHistory.getVisibility() == View.VISIBLE) + openOrCloseHistory(false); + } + } + } + } + }); + + getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + openKeyBoard(); + } + }, 100); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(this); + } else + getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(this); + } + }); + } + + private void checkTvToSearch() { + if (llSearchHistory.getVisibility() == View.VISIBLE) { + tvTosearch.setText("搜索"); + mPresenter.setInput(true); + } else { + tvTosearch.setText("返回"); + mPresenter.setInput(false); + } + } + + private void openOrCloseHistory(Boolean open) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (null != animHistory5) { + animHistory5.cancel(); + } + if (open) { + animHistory5 = ViewAnimationUtils.createCircularReveal( + llSearchHistory, + 0, 0, 0, + (float) Math.hypot(llSearchHistory.getWidth(), llSearchHistory.getHeight())); + animHistory5.setInterpolator(new AccelerateDecelerateInterpolator()); + animHistory5.setDuration(700); + animHistory5.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + llSearchHistory.setVisibility(View.VISIBLE); + edtContent.setCursorVisible(true); + checkTvToSearch(); + } + + @Override + public void onAnimationEnd(Animator animation) { + if (rfRvSearchBooks.getVisibility() != View.VISIBLE) + rfRvSearchBooks.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + animHistory5.start(); + } else { + animHistory5 = ViewAnimationUtils.createCircularReveal( + llSearchHistory, + 0, 0, (float) Math.hypot(llSearchHistory.getHeight(), llSearchHistory.getHeight()), + 0); + animHistory5.setInterpolator(new AccelerateDecelerateInterpolator()); + animHistory5.setDuration(300); + animHistory5.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + llSearchHistory.setVisibility(View.GONE); + edtContent.setCursorVisible(false); + checkTvToSearch(); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + animHistory5.start(); + } + } else { + if (null != animHistory) { + animHistory.cancel(); + } + if (open) { + animHistory = AnimationUtils.loadAnimation(this, android.R.anim.fade_in); + animHistory.setInterpolator(new AccelerateDecelerateInterpolator()); + animHistory.setDuration(700); + animHistory.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + llSearchHistory.setVisibility(View.VISIBLE); + edtContent.setCursorVisible(true); + checkTvToSearch(); + } + + @Override + public void onAnimationEnd(Animation animation) { + if (rfRvSearchBooks.getVisibility() != View.VISIBLE) + rfRvSearchBooks.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + llSearchHistory.startAnimation(animHistory); + } else { + animHistory = AnimationUtils.loadAnimation(this, android.R.anim.fade_out); + animHistory.setInterpolator(new AccelerateDecelerateInterpolator()); + animHistory.setDuration(300); + animHistory.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + } + + @Override + public void onAnimationEnd(Animation animation) { + llSearchHistory.setVisibility(View.GONE); + edtContent.setCursorVisible(false); + checkTvToSearch(); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + llSearchHistory.startAnimation(animHistory); + } + } + } + + private void closeKeyBoard() { + InputMethodManager imm = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(edtContent.getWindowToken(), 0); + } + + private void openKeyBoard() { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + edtContent.requestFocus(); + imm.showSoftInput(edtContent, InputMethodManager.RESULT_UNCHANGED_SHOWN); + } + + @Override + public void insertSearchHistorySuccess(SearchHistoryBean searchHistoryBean) { + //搜索历史插入或者修改成功 + mPresenter.querySearchHistory(); + } + + @Override + public void querySearchHistorySuccess(List datas) { + searchHistoryAdapter.replaceAll(datas); + if (searchHistoryAdapter.getDataSize() > 0) { + tvSearchHistoryClean.setVisibility(View.VISIBLE); + } else { + tvSearchHistoryClean.setVisibility(View.INVISIBLE); + } + } + + @Override + public void refreshSearchBook(List books) { + searchBookAdapter.replaceAll(books); + } + + @Override + public void refreshFinish(Boolean isAll) { + rfRvSearchBooks.finishRefresh(isAll, true); + } + + @Override + public void loadMoreFinish(Boolean isAll) { + rfRvSearchBooks.finishLoadMore(isAll, true); + } + + @Override + public void searchBookError(Boolean isRefresh) { + if (isRefresh) { + rfRvSearchBooks.refreshError(); + } else { + + rfRvSearchBooks.loadMoreError(); + } + } + + @Override + public void loadMoreSearchBook(final List books) { + searchBookAdapter.addAll(books); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + explosionField.clear(); + } + + @Override + public EditText getEdtContent() { + return edtContent; + } + + @Override + public void addBookShelfFailed(int code) { + Toast.makeText(this, NetworkUtil.getErrorTip(code), Toast.LENGTH_SHORT).show(); + } + + @Override + public SearchBookAdapter getSearchBookAdapter() { + return searchBookAdapter; + } + + @Override + public void updateSearchItem(int index) { + if (index < searchBookAdapter.getItemcount()) { + int startIndex = ((LinearLayoutManager) rfRvSearchBooks.getRecyclerView().getLayoutManager()).findFirstVisibleItemPosition(); + TextView tvAddShelf = (TextView) ((ViewGroup) rfRvSearchBooks.getRecyclerView()).getChildAt(index - startIndex).findViewById(R.id.tv_addshelf); + if (tvAddShelf != null) { + if (searchBookAdapter.getSearchBooks().get(index).getAdd()) { + tvAddShelf.setText("已添加"); + tvAddShelf.setEnabled(false); + } else { + tvAddShelf.setText("+添加"); + tvAddShelf.setEnabled(true); + } + } + } + } + + @Override + public Boolean checkIsExist(SearchBookBean searchBookBean) { + Boolean result = false; + for (int i = 0; i < searchBookAdapter.getItemcount(); i++) { + if(searchBookAdapter.getSearchBooks().get(i).getNoteUrl().equals(searchBookBean.getNoteUrl()) && searchBookAdapter.getSearchBooks().get(i).getTag().equals(searchBookBean.getTag())){ + result = true; + break; + } + } + return result; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/view/impl/WelcomeActivity.java b/app/src/main/java/com/monke/monkeybook/view/impl/WelcomeActivity.java new file mode 100644 index 0000000000..e71cbe1008 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/impl/WelcomeActivity.java @@ -0,0 +1,83 @@ +package com.monke.monkeybook.view.impl; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.content.Intent; +import android.widget.ImageView; +import android.widget.TextView; +import com.monke.basemvplib.IPresenter; +import com.monke.monkeybook.R; +import com.monke.monkeybook.base.MBaseActivity; + +public class WelcomeActivity extends MBaseActivity { + + private ImageView ivBg; + private ImageView ivIcon; + private TextView tvIntro; + + private ValueAnimator welAnimator; + + @Override + protected IPresenter initInjector() { + return null; + } + + @Override + protected void onCreateActivity() { + setContentView(R.layout.activity_welcome); + } + + @Override + protected void initData() { + welAnimator = ValueAnimator.ofFloat(1f, 0f).setDuration(800); + welAnimator.setStartDelay(500); + } + + @Override + protected void bindView() { + ivBg = (ImageView) findViewById(R.id.iv_bg); + ivIcon = (ImageView) findViewById(R.id.iv_icon); + tvIntro = (TextView) findViewById(R.id.tv_intro); + } + + @Override + protected void bindEvent() { + welAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float alpha = (Float) animation.getAnimatedValue(); + ivBg.setAlpha(alpha); + ivIcon.setAlpha(alpha); + tvIntro.setAlpha(1f - alpha); + } + }); + welAnimator.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + startActivityByAnim(new Intent(WelcomeActivity.this, MainActivity.class), android.R.anim.fade_in, android.R.anim.fade_out); + finish(); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + } + + @Override + protected void firstRequest() { + welAnimator.start(); + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/view/popupwindow/CheckAddShelfPop.java b/app/src/main/java/com/monke/monkeybook/view/popupwindow/CheckAddShelfPop.java new file mode 100644 index 0000000000..b60dbf4625 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/popupwindow/CheckAddShelfPop.java @@ -0,0 +1,60 @@ +package com.monke.monkeybook.view.popupwindow; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.PopupWindow; +import android.widget.TextView; +import com.monke.monkeybook.R; + +public class CheckAddShelfPop extends PopupWindow{ + private Context mContext; + private View view; + + public interface OnItemClickListener { + public void clickExit(); + public void clickAddShelf(); + } + private OnItemClickListener itemClick; + private String bookName; + + private TextView tvBookName; + private TextView tvExit; + private TextView tvAddShelf; + public CheckAddShelfPop(Context context,@NonNull String bookName,@NonNull OnItemClickListener itemClick){ + super(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); + mContext = context; + this.bookName = bookName; + this.itemClick = itemClick; + view = LayoutInflater.from(mContext).inflate(R.layout.view_pop_checkaddshelf,null); + this.setContentView(view); + + initView(); + setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.shape_pop_checkaddshelf_bg)); + setFocusable(true); + setTouchable(true); + setAnimationStyle(R.style.anim_pop_checkaddshelf); + } + + private void initView() { + tvBookName = (TextView) view.findViewById(R.id.tv_book_name); + tvBookName.setText(String.format(mContext.getString(R.string.tv_pop_checkaddshelf),bookName)); + tvExit = (TextView) view.findViewById(R.id.tv_exit); + tvExit.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + itemClick.clickExit(); + } + }); + tvAddShelf = (TextView) view.findViewById(R.id.tv_addshelf); + tvAddShelf.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + itemClick.clickAddShelf(); + } + }); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/view/popupwindow/DownloadListPop.java b/app/src/main/java/com/monke/monkeybook/view/popupwindow/DownloadListPop.java new file mode 100644 index 0000000000..3f41425139 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/popupwindow/DownloadListPop.java @@ -0,0 +1,178 @@ +package com.monke.monkeybook.view.popupwindow; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.PopupWindow; +import android.widget.TextView; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.hwangjr.rxbus.RxBus; +import com.hwangjr.rxbus.annotation.Subscribe; +import com.hwangjr.rxbus.annotation.Tag; +import com.hwangjr.rxbus.thread.EventThread; +import com.monke.monkeybook.R; +import com.monke.monkeybook.base.observer.SimpleObserver; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.bean.DownloadChapterBean; +import com.monke.monkeybook.common.RxBusTag; +import com.monke.monkeybook.dao.BookShelfBeanDao; +import com.monke.monkeybook.dao.DbHelper; +import com.monke.monkeybook.dao.DownloadChapterBeanDao; +import java.util.List; +import io.reactivex.Observable; +import io.reactivex.ObservableEmitter; +import io.reactivex.ObservableOnSubscribe; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.schedulers.Schedulers; + +public class DownloadListPop extends PopupWindow { + private Context mContext; + private View view; + + private TextView tvNone; + private LinearLayout llDownload; + + private ImageView ivCover; + private TextView tvName; + private TextView tvChapterName; + private TextView tvCancel; + private TextView tvDownload; + + public DownloadListPop(Context context) { + super(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + mContext = context; + view = LayoutInflater.from(mContext).inflate(R.layout.view_pop_downloadlist, null); + this.setContentView(view); + bindView(); + bindEvent(); + initWait(); + setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.shape_pop_checkaddshelf_bg)); + setFocusable(true); + setTouchable(true); + setAnimationStyle(R.style.anim_pop_checkaddshelf); + RxBus.get().register(DownloadListPop.this); + } + + private void bindEvent() { + tvCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + RxBus.get().post(RxBusTag.CANCEL_DOWNLOAD, new Object()); + tvNone.setVisibility(View.VISIBLE); + } + }); + tvDownload.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (tvDownload.getText().equals("开始下载")) { + RxBus.get().post(RxBusTag.START_DOWNLOAD, new Object()); + } else { + RxBus.get().post(RxBusTag.PAUSE_DOWNLOAD, new Object()); + } + } + }); + } + + private void bindView() { + tvNone = (TextView) view.findViewById(R.id.tv_none); + llDownload = (LinearLayout) view.findViewById(R.id.ll_download); + ivCover = (ImageView) view.findViewById(R.id.iv_cover); + tvName = (TextView) view.findViewById(R.id.tv_name); + tvChapterName = (TextView) view.findViewById(R.id.tv_chapter_name); + tvCancel = (TextView) view.findViewById(R.id.tv_cancel); + tvDownload = (TextView) view.findViewById(R.id.tv_download); + } + + private void initWait() { + Observable.create(new ObservableOnSubscribe() { + @Override + public void subscribe(ObservableEmitter e) throws Exception { + List bookShelfBeanList = DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().queryBuilder().orderDesc(BookShelfBeanDao.Properties.FinalDate).list(); + if (bookShelfBeanList != null && bookShelfBeanList.size() > 0) { + for (BookShelfBean bookItem : bookShelfBeanList) { + if (!bookItem.getTag().equals(BookShelfBean.LOCAL_TAG)) { + List downloadChapterList = DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().queryBuilder().where(DownloadChapterBeanDao.Properties.NoteUrl.eq(bookItem.getNoteUrl())).orderAsc(DownloadChapterBeanDao.Properties.DurChapterIndex).limit(1).list(); + if (downloadChapterList != null && downloadChapterList.size() > 0) { + e.onNext(downloadChapterList.get(0)); + e.onComplete(); + return; + } + } + } + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll(); + e.onNext(new DownloadChapterBean()); + } else { + DbHelper.getInstance().getmDaoSession().getDownloadChapterBeanDao().deleteAll(); + e.onNext(new DownloadChapterBean()); + } + e.onComplete(); + } + }) + .subscribeOn(AndroidSchedulers.mainThread()) + .observeOn(Schedulers.io()) + .subscribe(new SimpleObserver() { + @Override + public void onNext(DownloadChapterBean value) { + if (value.getNoteUrl() != null && value.getNoteUrl().length() > 0) { + llDownload.setVisibility(View.GONE); + tvNone.setVisibility(View.GONE); + tvDownload.setText("开始下载"); + } else { + tvNone.setVisibility(View.VISIBLE); + } + } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + tvNone.setVisibility(View.VISIBLE); + } + }); + } + + public void onDestroy() { + RxBus.get().unregister(DownloadListPop.this); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.PAUSE_DOWNLOAD_LISTENER) + } + ) + public void pauseTask(Object o) { + tvNone.setVisibility(View.GONE); + llDownload.setVisibility(View.GONE); + tvDownload.setText("开始下载"); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.FINISH_DOWNLOAD_LISTENER) + } + ) + public void finishTask(Object o) { + tvNone.setVisibility(View.VISIBLE); + } + + @Subscribe( + thread = EventThread.MAIN_THREAD, + tags = { + @Tag(RxBusTag.PROGRESS_DOWNLOAD_LISTENER) + } + ) + public void progressTask(DownloadChapterBean downloadChapterBean) { + tvNone.setVisibility(View.GONE); + llDownload.setVisibility(View.VISIBLE); + tvDownload.setText("暂停下载"); + Glide.with(mContext).load(downloadChapterBean.getCoverUrl()).dontAnimate().diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().placeholder(R.drawable.img_cover_default).into(ivCover); + tvName.setText(downloadChapterBean.getBookName()); + tvChapterName.setText(downloadChapterBean.getDurChapterName()); + } + +} diff --git a/app/src/main/java/com/monke/monkeybook/view/popupwindow/FontPop.java b/app/src/main/java/com/monke/monkeybook/view/popupwindow/FontPop.java new file mode 100644 index 0000000000..0dcfaf1f35 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/popupwindow/FontPop.java @@ -0,0 +1,168 @@ +package com.monke.monkeybook.view.popupwindow; + +import android.content.Context; +import android.graphics.Color; +import android.support.annotation.NonNull; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.PopupWindow; +import android.widget.TextView; + +import com.monke.monkeybook.R; +import com.monke.monkeybook.ReadBookControl; + +import de.hdodenhof.circleimageview.CircleImageView; + +public class FontPop extends PopupWindow{ + private Context mContext; + private View view; + private FrameLayout flSmaller; + private FrameLayout flBigger; + private TextView tvTextSizedDefault; + private TextView tvTextSize; + private CircleImageView civBgWhite; + private CircleImageView civBgYellow; + private CircleImageView civBgGreen; + private CircleImageView civBgBlack; + + private ReadBookControl readBookControl; + + public interface OnChangeProListener{ + public void textChange(int index); + + public void bgChange(int index); + } + private OnChangeProListener changeProListener; + + public FontPop(Context context,@NonNull OnChangeProListener changeProListener){ + super(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + this.mContext = context; + this.changeProListener = changeProListener; + + view = LayoutInflater.from(mContext).inflate(R.layout.view_pop_font, null); + this.setContentView(view); + initData(); + bindView(); + bindEvent(); + + setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.shape_pop_checkaddshelf_bg)); + setFocusable(true); + setTouchable(true); + setAnimationStyle(R.style.anim_pop_windowlight); + } + + private void bindEvent() { + flSmaller.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + updateText(readBookControl.getTextKindIndex()-1); + changeProListener.textChange(readBookControl.getTextKindIndex()); + } + }); + flBigger.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + updateText(readBookControl.getTextKindIndex()+1); + changeProListener.textChange(readBookControl.getTextKindIndex()); + } + }); + tvTextSizedDefault.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + updateText(ReadBookControl.DEFAULT_TEXT); + changeProListener.textChange(readBookControl.getTextKindIndex()); + } + }); + + civBgWhite.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + updateBg(0); + changeProListener.bgChange(readBookControl.getTextDrawableIndex()); + } + }); + civBgYellow.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + updateBg(1); + changeProListener.bgChange(readBookControl.getTextDrawableIndex()); + } + }); + civBgGreen.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + updateBg(2); + changeProListener.bgChange(readBookControl.getTextDrawableIndex()); + } + }); + civBgBlack.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + updateBg(3); + changeProListener.bgChange(readBookControl.getTextDrawableIndex()); + } + }); + } + + private void bindView() { + flSmaller = (FrameLayout) view.findViewById(R.id.fl_smaller); + flBigger = (FrameLayout) view.findViewById(R.id.fl_bigger); + tvTextSizedDefault = (TextView) view.findViewById(R.id.tv_textsize_default); + tvTextSize = (TextView) view.findViewById(R.id.tv_dur_textsize); + updateText(readBookControl.getTextKindIndex()); + + civBgWhite = (CircleImageView) view.findViewById(R.id.civ_bg_white); + civBgYellow = (CircleImageView) view.findViewById(R.id.civ_bg_yellow); + civBgGreen = (CircleImageView) view.findViewById(R.id.civ_bg_green); + civBgBlack = (CircleImageView) view.findViewById(R.id.civ_bg_black); + updateBg(readBookControl.getTextDrawableIndex()); + } + + private void updateText(int textKindIndex) { + if(textKindIndex==0){ + flSmaller.setEnabled(false); + flBigger.setEnabled(true); + }else if(textKindIndex == readBookControl.getTextKind().size()-1){ + flSmaller.setEnabled(true); + flBigger.setEnabled(false); + }else{flSmaller.setEnabled(true); + flBigger.setEnabled(true); + + } + if(textKindIndex == ReadBookControl.DEFAULT_TEXT){ + tvTextSizedDefault.setEnabled(false); + }else{ + tvTextSizedDefault.setEnabled(true); + } + tvTextSize.setText(String.valueOf(readBookControl.getTextKind().get(textKindIndex).get("textSize"))); + readBookControl.setTextKindIndex(textKindIndex); + } + + private void updateBg(int index) { + civBgWhite.setBorderColor(Color.parseColor("#00000000")); + civBgYellow.setBorderColor(Color.parseColor("#00000000")); + civBgGreen.setBorderColor(Color.parseColor("#00000000")); + civBgBlack.setBorderColor(Color.parseColor("#00000000")); + switch (index){ + case 0: + civBgWhite.setBorderColor(Color.parseColor("#F3B63F")); + break; + case 1: + civBgYellow.setBorderColor(Color.parseColor("#F3B63F")); + break; + case 2: + civBgGreen.setBorderColor(Color.parseColor("#F3B63F")); + break; + default: + civBgBlack.setBorderColor(Color.parseColor("#F3B63F")); + break; + } + readBookControl.setTextDrawableIndex(index); + } + + private void initData() { + readBookControl = ReadBookControl.getInstance(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/view/popupwindow/MoreSettingPop.java b/app/src/main/java/com/monke/monkeybook/view/popupwindow/MoreSettingPop.java new file mode 100644 index 0000000000..603d080c82 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/popupwindow/MoreSettingPop.java @@ -0,0 +1,69 @@ +package com.monke.monkeybook.view.popupwindow; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CompoundButton; +import android.widget.PopupWindow; + +import com.kyleduo.switchbutton.SwitchButton; +import com.monke.monkeybook.R; +import com.monke.monkeybook.ReadBookControl; + +public class MoreSettingPop extends PopupWindow{ + private Context mContext; + private View view; + + private SwitchButton sbKey; + private SwitchButton sbClick; + + private ReadBookControl readBookControl; + + public MoreSettingPop(Context context){ + super(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + mContext = context; + + view = LayoutInflater.from(mContext).inflate(R.layout.view_pop_moresetting,null); + this.setContentView(view); + initData(); + bindView(); + bindEvent(); + + setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.shape_pop_checkaddshelf_bg)); + setFocusable(true); + setTouchable(true); + setAnimationStyle(R.style.anim_pop_windowlight); + } + + private void bindEvent() { + sbKey.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + readBookControl.setCanKeyTurn(isChecked); + } + }); + sbClick.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + readBookControl.setCanClickTurn(isChecked); + } + }); + } + + private void bindView() { + sbKey = (SwitchButton) view.findViewById(R.id.sb_key); + sbClick = (SwitchButton) view.findViewById(R.id.sb_click); + + if(readBookControl.getCanKeyTurn()) + sbKey.setCheckedImmediatelyNoEvent(true); + else sbKey.setCheckedImmediatelyNoEvent(false); + if(readBookControl.getCanClickTurn()) + sbClick.setCheckedImmediatelyNoEvent(true); + else sbClick.setCheckedImmediatelyNoEvent(false); + } + + private void initData() { + readBookControl = ReadBookControl.getInstance(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/view/popupwindow/ReadBookMenuMorePop.java b/app/src/main/java/com/monke/monkeybook/view/popupwindow/ReadBookMenuMorePop.java new file mode 100644 index 0000000000..ece3530873 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/popupwindow/ReadBookMenuMorePop.java @@ -0,0 +1,38 @@ +package com.monke.monkeybook.view.popupwindow; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.PopupWindow; +import com.monke.monkeybook.R; + +public class ReadBookMenuMorePop extends PopupWindow{ + private Context mContext; + private View view; + + private LinearLayout llDownload; + + public ReadBookMenuMorePop(Context context){ + super(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); + this.mContext = context; + view = LayoutInflater.from(mContext).inflate(R.layout.view_pop_menumore,null); + this.setContentView(view); + + initView(); + + setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.shape_pop_checkaddshelf_bg)); + setFocusable(true); + setTouchable(true); + setAnimationStyle(R.style.anim_pop_windowmenumore); + } + + private void initView() { + llDownload = (LinearLayout) view.findViewById(R.id.ll_download); + } + + public void setOnClickDownload(View.OnClickListener clickDownload){ + llDownload.setOnClickListener(clickDownload); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/view/popupwindow/WindowLightPop.java b/app/src/main/java/com/monke/monkeybook/view/popupwindow/WindowLightPop.java new file mode 100644 index 0000000000..5fd042be2c --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/view/popupwindow/WindowLightPop.java @@ -0,0 +1,168 @@ +package com.monke.monkeybook.view.popupwindow; + +import android.app.Activity; +import android.content.ContentResolver; +import android.content.Context; +import android.content.SharedPreferences; +import android.provider.Settings; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.widget.LinearLayout; +import android.widget.PopupWindow; +import com.monke.monkeybook.R; +import com.monke.monkeybook.widget.checkbox.SmoothCheckBox; +import com.monke.mprogressbar.MHorProgressBar; +import com.monke.mprogressbar.OnProgressListener; + +public class WindowLightPop extends PopupWindow { + private Context mContext; + private View view; + + private MHorProgressBar hpbLight; + private LinearLayout llFollowSys; + private SmoothCheckBox scbFollowSys; + + private Boolean isFollowSys; + private int light; + + public WindowLightPop(Context context) { + super(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + this.mContext = context; + + view = LayoutInflater.from(mContext).inflate(R.layout.view_pop_windowlight, null); + this.setContentView(view); + initData(); + initView(); + bindEvent(); + + setBackgroundDrawable(mContext.getResources().getDrawable(R.drawable.shape_pop_checkaddshelf_bg)); + setFocusable(true); + setTouchable(true); + setAnimationStyle(R.style.anim_pop_windowlight); + } + + private void initData() { + isFollowSys = getIsFollowSys(); + light = getLight(); + } + + private void initView() { + hpbLight = (MHorProgressBar) view.findViewById(R.id.hpb_light); + llFollowSys = (LinearLayout) view.findViewById(R.id.ll_follow_sys); + scbFollowSys = (SmoothCheckBox) view.findViewById(R.id.scb_follow_sys); + } + + private void bindEvent() { + llFollowSys.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (scbFollowSys.isChecked()) { + scbFollowSys.setChecked(false, true); + } else { + scbFollowSys.setChecked(true, true); + } + } + }); + scbFollowSys.setOnCheckedChangeListener(new SmoothCheckBox.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(SmoothCheckBox checkBox, boolean isChecked) { + isFollowSys = isChecked; + if (isChecked) { + //跟随系统 + hpbLight.setCanTouch(false); + setScreenBrightness(); + } else { + //不跟随系统 + hpbLight.setCanTouch(true); + hpbLight.setDurProgress(light); + } + } + }); + hpbLight.setProgressListener(new OnProgressListener() { + @Override + public void moveStartProgress(float dur) { + + } + + @Override + public void durProgressChange(float dur) { + if (!isFollowSys) { + light = (int) dur; + setScreenBrightness((int) dur); + } + } + + @Override + public void moveStopProgress(float dur) { + + } + + @Override + public void setDurProgress(float dur) { + + } + }); + } + + public void setScreenBrightness(int value) { + WindowManager.LayoutParams params = ((Activity) mContext).getWindow().getAttributes(); + params.screenBrightness = value * 1.0f / 255f; + ((Activity) mContext).getWindow().setAttributes(params); + } + public void setScreenBrightness() { + WindowManager.LayoutParams params = ((Activity) mContext).getWindow().getAttributes(); + params.screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE; + ((Activity) mContext).getWindow().setAttributes(params); + } + + public int getScreenBrightness() { + int value = 0; + ContentResolver cr = mContext.getContentResolver(); + try { + value = Settings.System.getInt(cr, Settings.System.SCREEN_BRIGHTNESS); + } catch (Settings.SettingNotFoundException e) { + e.printStackTrace(); + } + return value; + } + + private void saveLight() { + SharedPreferences preference = mContext.getSharedPreferences("CONFIG", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = preference.edit(); + editor.putInt("light", light); + editor.putBoolean("isfollowsys", isFollowSys); + editor.commit(); + } + + private int getLight() { + SharedPreferences preference = mContext.getSharedPreferences("CONFIG", Context.MODE_PRIVATE); + return preference.getInt("light", getScreenBrightness()); + } + + private Boolean getIsFollowSys() { + SharedPreferences preference = mContext.getSharedPreferences("CONFIG", Context.MODE_PRIVATE); + return preference.getBoolean("isfollowsys", true); + } + + @Override + public void dismiss() { + saveLight(); + super.dismiss(); + } + + @Override + public void showAtLocation(View parent, int gravity, int x, int y) { + super.showAtLocation(parent, gravity, x, y); + initData(); + hpbLight.setDurProgress(light); + scbFollowSys.setChecked(isFollowSys); + } + + public void initLight(){ + if(!isFollowSys){ + setScreenBrightness(light); + } + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/ChapterListView.java b/app/src/main/java/com/monke/monkeybook/widget/ChapterListView.java new file mode 100644 index 0000000000..c6e8840b3b --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/ChapterListView.java @@ -0,0 +1,164 @@ +package com.monke.monkeybook.widget; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.support.annotation.AttrRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.annotation.StyleRes; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.BookShelfBean; +import com.monke.monkeybook.view.adapter.ChapterListAdapter; + +public class ChapterListView extends FrameLayout{ + private TextView tvName; + private TextView tvListCount; + private RecyclerView rvList; + private RecyclerViewBar rvbSlider; + + private FrameLayout flBg; + private LinearLayout llContent; + + private ChapterListAdapter chapterListAdapter; + + private Animation animIn; + private Animation animOut; + + public ChapterListView(@NonNull Context context) { + this(context,null); + } + + public ChapterListView(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs,0); + } + + public ChapterListView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public ChapterListView(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + private void init() { + setVisibility(INVISIBLE); + LayoutInflater.from(getContext()).inflate(R.layout.view_chapterlist,this,true); + initData(); + initView(); + } + + private void initData() { + animIn = AnimationUtils.loadAnimation(getContext(),R.anim.anim_pop_chapterlist_in); + animIn.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + flBg.setOnClickListener(null); + } + + @Override + public void onAnimationEnd(Animation animation) { + flBg.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + dimissChapterList(); + } + }); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + animOut = AnimationUtils.loadAnimation(getContext(),R.anim.anim_pop_chapterlist_out); + animOut.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + flBg.setOnClickListener(null); + } + + @Override + public void onAnimationEnd(Animation animation) { + llContent.setVisibility(INVISIBLE); + setVisibility(INVISIBLE); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + } + + public void show(int durChapter) { + chapterListAdapter.setIndex(durChapter); + ((LinearLayoutManager) rvList.getLayoutManager()).scrollToPositionWithOffset(durChapter,0); + if(getVisibility()!=VISIBLE){ + setVisibility(VISIBLE); + animOut.cancel(); + animIn.cancel(); + llContent.setVisibility(VISIBLE); + llContent.startAnimation(animIn); + } + } + + public interface OnItemClickListener{ + public void itemClick(int index); + } + private OnItemClickListener itemClickListener; + private BookShelfBean bookShelfBean; + + private void initView() { + flBg = (FrameLayout) findViewById(R.id.fl_bg); + llContent = (LinearLayout) findViewById(R.id.ll_content); + tvName = (TextView) findViewById(R.id.tv_name); + tvListCount = (TextView) findViewById(R.id.tv_listcount); + rvList = (RecyclerView) findViewById(R.id.rv_list); + rvList.setLayoutManager(new LinearLayoutManager(getContext())); + rvList.setItemAnimator(null); + rvbSlider = (RecyclerViewBar) findViewById(R.id.rvb_slider); + } + + public void setData(BookShelfBean bookShelfBean,OnItemClickListener clickListener) { + this.itemClickListener = clickListener; + this.bookShelfBean = bookShelfBean; + tvName.setText(bookShelfBean.getBookInfoBean().getName()); + tvListCount.setText("共"+bookShelfBean.getBookInfoBean().getChapterlist().size()+"章"); + chapterListAdapter = new ChapterListAdapter(bookShelfBean, new OnItemClickListener() { + @Override + public void itemClick(int index) { + if(itemClickListener!=null){ + itemClickListener.itemClick(index); + rvbSlider.scrollToPositionWithOffset(index); + } + } + }); + rvList.setAdapter(chapterListAdapter); + rvbSlider.setRecyclerView(rvList); + } + + public Boolean dimissChapterList(){ + if(getVisibility()!=VISIBLE){ + return false; + }else{ + animOut.cancel(); + animIn.cancel(); + llContent.startAnimation(animOut); + return true; + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/widget/MTextView.java b/app/src/main/java/com/monke/monkeybook/widget/MTextView.java new file mode 100644 index 0000000000..87dbb6b638 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/MTextView.java @@ -0,0 +1,33 @@ +package com.monke.monkeybook.widget; + +import android.content.Context; +import android.graphics.Canvas; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.util.AttributeSet; + +/** + * Created by ZQH on 2017/4/10. + */ + +public class MTextView extends android.support.v7.widget.AppCompatTextView { + + public MTextView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, + int bottom) { + super.onLayout(changed, left, top, right, bottom); + } + + @Override + protected void onDraw(Canvas canvas) { + TextPaint paint = getPaint(); + paint.setColor(getTextColors().getDefaultColor()); + Layout layout = new StaticLayout(getText(), paint, canvas.getWidth(), Layout.Alignment.ALIGN_NORMAL, getLineSpacingMultiplier(), getLineSpacingExtra(), false); + layout.draw(canvas); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/widget/RecyclerViewBar.java b/app/src/main/java/com/monke/monkeybook/widget/RecyclerViewBar.java new file mode 100644 index 0000000000..0aa746da64 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/RecyclerViewBar.java @@ -0,0 +1,241 @@ +package com.monke.monkeybook.widget; + +import android.animation.Animator; +import android.animation.ObjectAnimator; +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Rect; +import android.os.Build; +import android.os.CountDownTimer; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.monke.monkeybook.R; +import com.monke.monkeybook.utils.DensityUtil; + +public class RecyclerViewBar extends LinearLayout { + public static long SLIDE_ANIM_TIME = 800; + + private ImageView ivSlider; + private int sliderHeight = DensityUtil.dp2px(getContext(), 35f); + + private RecyclerView recyclerView; + + private Animator slideIn; + private Animator slideOut; + + public RecyclerViewBar(Context context) { + this(context, null); + } + + public RecyclerViewBar(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public RecyclerViewBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(attrs); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public RecyclerViewBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(attrs); + } + + private void init(AttributeSet attrs) { + setOrientation(VERTICAL); + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.RecyclerViewBar); + sliderHeight = a.getDimensionPixelSize(R.styleable.RecyclerViewBar_slider_height, sliderHeight); + int paddingLeft = a.getDimensionPixelSize(R.styleable.RecyclerViewBar_slider_paddingLeft, 0); + int paddingRight = a.getDimensionPixelSize(R.styleable.RecyclerViewBar_slider_paddingRight, 0); + ivSlider = new ImageView(getContext()); + ivSlider.setPadding(paddingLeft, 0, paddingRight, 0); + ivSlider.setAlpha(0f); + ivSlider.setClickable(true); + addView(ivSlider); + LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, sliderHeight); + ivSlider.setLayoutParams(layoutParams); + ivSlider.setImageResource(R.drawable.icon_slider); + ivSlider.setScaleType(ImageView.ScaleType.FIT_XY); + + initIvSlider(); + + RecyclerViewBar.this.getViewTreeObserver().addOnGlobalLayoutListener(layoutInitListener); + } + + private float finalY = -10000; + + private void initIvSlider() { + ivSlider.setOnTouchListener(new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + finalY = event.getY(); + return true; + case MotionEvent.ACTION_MOVE: + if (finalY >= 0) { + float tempY = event.getY(); + float durY = tempY - finalY; + updateSlider(durY); + + showSlide(); + } else { + finalY = event.getY(); + } + return true; + case MotionEvent.ACTION_UP: + if (finalY >= 0) { + finalY = -10000; + timeCountDown.cancel(); + timeCountDown.start(); + return true; + } + break; + default: + if (finalY >= 0) { + finalY = -10000; + return true; + } + break; + } + return false; + } + }); + } + + private void updateSlider(float durY) { + LayoutParams l = (LayoutParams) ivSlider.getLayoutParams(); + float finalMarginTop = l.topMargin + durY; + if (finalMarginTop < 0) { + finalMarginTop = 0; + } else if (finalMarginTop > getHeight() - sliderHeight) { + finalMarginTop = getHeight() - sliderHeight; + } + if (recyclerView != null) { + int position = Math.round(finalMarginTop / (getHeight() - sliderHeight) * (recyclerView.getAdapter().getItemCount() - 1)); + ((LinearLayoutManager) recyclerView.getLayoutManager()).scrollToPositionWithOffset(position, 0); + } + + l.topMargin = Math.round(finalMarginTop); + ivSlider.setLayoutParams(l); + } + + public void setRecyclerView(RecyclerView recyclerView) { + this.recyclerView = recyclerView; + if (this.recyclerView != null) { + this.recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState != 0) { + showSlide(); + } else { + timeCountDown.cancel(); + timeCountDown.start(); + } + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + scrollToPositionWithOffset(((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition()); + } + }); + } + } + + public void scrollToPositionWithOffset(int position) { + if (recyclerView != null && position < recyclerView.getAdapter().getItemCount()) { + float temp = position * 1.0f / recyclerView.getAdapter().getItemCount(); + LayoutParams l = (LayoutParams) ivSlider.getLayoutParams(); + l.topMargin = Math.round(((getHeight() - sliderHeight) * temp)); + ivSlider.setLayoutParams(l); + } + } + + private void showSlide() { + if (ivSlider.getAlpha() < 1) { + if (slideOut != null && slideOut.isRunning()) { + slideOut.cancel(); + } + if (slideIn == null) { + slideIn = ObjectAnimator.ofFloat(ivSlider, "alpha", ivSlider.getAlpha(), 1f); + slideIn.setDuration((long) (SLIDE_ANIM_TIME * (1f - ivSlider.getAlpha()))); + } + if (!slideIn.isRunning()) { + slideIn.start(); + } + } + } + + private void hideSlide() { + if (ivSlider.getAlpha() > 0) { + if (slideIn != null && slideIn.isRunning()) { + slideIn.cancel(); + } + if (slideOut == null) { + slideOut = ObjectAnimator.ofFloat(ivSlider, "alpha", ivSlider.getAlpha(), 0f); + slideOut.setDuration((long) (SLIDE_ANIM_TIME * ivSlider.getAlpha())); + } + if (!slideOut.isRunning()) { + slideOut.start(); + } + } + } + + private TimeCountDown timeCountDown = new TimeCountDown(); + + class TimeCountDown extends CountDownTimer { + + public TimeCountDown() { + this(1000, 1000); + } + + public TimeCountDown(long millisInFuture, long countDownInterval) { + super(millisInFuture, countDownInterval); + } + + @Override + public void onTick(long millisUntilFinished) { + + } + + @Override + public void onFinish() { + hideSlide(); + } + } + + private int height = 0; + private ViewTreeObserver.OnGlobalLayoutListener layoutInitListener = new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if(getHeight()>0){ + if (height == 0) { + height = getHeight(); + } else { + int diff = height - getHeight(); + if (diff != 0) { + LayoutParams l = (LayoutParams) ivSlider.getLayoutParams(); + l.topMargin = (int) ((l.topMargin*1.0f/(height-sliderHeight))*(getHeight()-sliderHeight)); + ivSlider.setLayoutParams(l); + height = getHeight(); + } + } + } + } + }; +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/widget/checkbox/SmoothCheckBox.java b/app/src/main/java/com/monke/monkeybook/widget/checkbox/SmoothCheckBox.java new file mode 100644 index 0000000000..c7ffa5a2f2 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/checkbox/SmoothCheckBox.java @@ -0,0 +1,402 @@ +package com.monke.monkeybook.widget.checkbox; + +import android.animation.ValueAnimator; +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Point; +import android.os.Build; +import android.os.Bundle; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.LinearInterpolator; +import android.widget.Checkable; +import com.monke.monkeybook.R; +import com.monke.monkeybook.utils.DensityUtil; + +public class SmoothCheckBox extends View implements Checkable { + private static final String KEY_INSTANCE_STATE = "InstanceState"; + + private static final int COLOR_TICK = Color.WHITE; + private static final int COLOR_UNCHECKED = Color.WHITE; + private static final int COLOR_CHECKED = Color.parseColor("#FB4846"); + private static final int COLOR_FLOOR_UNCHECKED = Color.parseColor("#DFDFDF"); + + private static final int DEF_DRAW_SIZE = 25; + private static final int DEF_ANIM_DURATION = 300; + + private Paint mPaint, mTickPaint, mFloorPaint; + private Point[] mTickPoints; + private Point mCenterPoint; + private Path mTickPath; + + + private float mLeftLineDistance, mRightLineDistance, mDrewDistance; + private float mScaleVal = 1.0f, mFloorScale = 1.0f; + private int mWidth, mAnimDuration, mStrokeWidth; + private int mCheckedColor, mUnCheckedColor, mFloorColor, mFloorUnCheckedColor; + + private boolean mChecked; + private boolean mTickDrawing; + private OnCheckedChangeListener mListener; + + public SmoothCheckBox(Context context) { + this(context, null); + } + + public SmoothCheckBox(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SmoothCheckBox(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(attrs); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public SmoothCheckBox(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(attrs); + } + + private void init(AttributeSet attrs) { + + TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.SmoothCheckBox); + int tickColor = ta.getColor(R.styleable.SmoothCheckBox_color_tick, COLOR_TICK); + mAnimDuration = ta.getInt(R.styleable.SmoothCheckBox_duration, DEF_ANIM_DURATION); + mFloorColor = ta.getColor(R.styleable.SmoothCheckBox_color_unchecked_stroke, COLOR_FLOOR_UNCHECKED); + mCheckedColor = ta.getColor(R.styleable.SmoothCheckBox_color_checked, COLOR_CHECKED); + mUnCheckedColor = ta.getColor(R.styleable.SmoothCheckBox_color_unchecked, COLOR_UNCHECKED); + mStrokeWidth = ta.getDimensionPixelSize(R.styleable.SmoothCheckBox_stroke_width, DensityUtil.dp2px(getContext(), 0)); + ta.recycle(); + + mFloorUnCheckedColor = mFloorColor; + mTickPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTickPaint.setStyle(Paint.Style.STROKE); + mTickPaint.setStrokeCap(Paint.Cap.ROUND); + mTickPaint.setColor(tickColor); + + mFloorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mFloorPaint.setStyle(Paint.Style.FILL); + mFloorPaint.setColor(mFloorColor); + + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setStyle(Paint.Style.FILL); + mPaint.setColor(mCheckedColor); + + mTickPath = new Path(); + mCenterPoint = new Point(); + mTickPoints = new Point[3]; + mTickPoints[0] = new Point(); + mTickPoints[1] = new Point(); + mTickPoints[2] = new Point(); + + setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + toggle(); + mTickDrawing = false; + mDrewDistance = 0; + if (isChecked()) { + startCheckedAnimation(); + } else { + startUnCheckedAnimation(); + } + } + }); + } + + @Override + protected Parcelable onSaveInstanceState() { + Bundle bundle = new Bundle(); + bundle.putParcelable(KEY_INSTANCE_STATE, super.onSaveInstanceState()); + bundle.putBoolean(KEY_INSTANCE_STATE, isChecked()); + return bundle; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) { + if (state instanceof Bundle) { + Bundle bundle = (Bundle) state; + boolean isChecked = bundle.getBoolean(KEY_INSTANCE_STATE); + setChecked(isChecked); + super.onRestoreInstanceState(bundle.getParcelable(KEY_INSTANCE_STATE)); + return; + } + super.onRestoreInstanceState(state); + } + + @Override + public boolean isChecked() { + return mChecked; + } + + @Override + public void toggle() { + this.setChecked(!isChecked()); + } + + @Override + public void setChecked(boolean checked) { + mChecked = checked; + reset(); + invalidate(); + if (mListener != null) { + mListener.onCheckedChanged(SmoothCheckBox.this, mChecked); + } + } + + /** + * checked with animation + * @param checked checked + * @param animate change with animation + */ + public void setChecked(boolean checked, boolean animate) { + if (animate) { + mTickDrawing = false; + mChecked = checked; + mDrewDistance = 0f; + if (checked) { + startCheckedAnimation(); + } else { + startUnCheckedAnimation(); + } + if (mListener != null) { + mListener.onCheckedChanged(SmoothCheckBox.this, mChecked); + } + + } else { + this.setChecked(checked); + } + } + + private void reset() { + mTickDrawing = true; + mFloorScale = 1.0f; + mScaleVal = isChecked() ? 0f : 1.0f; + mFloorColor = isChecked() ? mCheckedColor : mFloorUnCheckedColor; + mDrewDistance = isChecked() ? (mLeftLineDistance + mRightLineDistance) : 0; + } + + private int measureSize(int measureSpec) { + int defSize = DensityUtil.dp2px(getContext(), DEF_DRAW_SIZE); + int specSize = MeasureSpec.getSize(measureSpec); + int specMode = MeasureSpec.getMode(measureSpec); + + int result = 0; + switch (specMode) { + case MeasureSpec.UNSPECIFIED: + case MeasureSpec.AT_MOST: + result = Math.min(defSize, specSize); + break; + case MeasureSpec.EXACTLY: + result = specSize; + break; + } + return result; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + setMeasuredDimension(measureSize(widthMeasureSpec), measureSize(heightMeasureSpec)); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + mWidth = getMeasuredWidth(); + mStrokeWidth = (mStrokeWidth == 0 ? getMeasuredWidth() / 10 : mStrokeWidth); + mStrokeWidth = mStrokeWidth > getMeasuredWidth() / 5 ? getMeasuredWidth() / 5 : mStrokeWidth; + mStrokeWidth = (mStrokeWidth < 3) ? 3 : mStrokeWidth; + mCenterPoint.x = mWidth / 2; + mCenterPoint.y = getMeasuredHeight() / 2; + + mTickPoints[0].x = Math.round((float) getMeasuredWidth() / 30 * 7); + mTickPoints[0].y = Math.round((float) getMeasuredHeight() / 30 * 14); + mTickPoints[1].x = Math.round((float) getMeasuredWidth() / 30 * 13); + mTickPoints[1].y = Math.round((float) getMeasuredHeight() / 30 * 20); + mTickPoints[2].x = Math.round((float) getMeasuredWidth() / 30 * 22); + mTickPoints[2].y = Math.round((float) getMeasuredHeight() / 30 * 10); + + mLeftLineDistance = (float) Math.sqrt(Math.pow(mTickPoints[1].x - mTickPoints[0].x, 2) + + Math.pow(mTickPoints[1].y - mTickPoints[0].y, 2)); + mRightLineDistance = (float) Math.sqrt(Math.pow(mTickPoints[2].x - mTickPoints[1].x, 2) + + Math.pow(mTickPoints[2].y - mTickPoints[1].y, 2)); + mTickPaint.setStrokeWidth(mStrokeWidth); + } + + @Override + protected void onDraw(Canvas canvas) { + drawBorder(canvas); + drawCenter(canvas); + drawTick(canvas); + } + + private void drawCenter(Canvas canvas) { + mPaint.setColor(mUnCheckedColor); + float radius = (mCenterPoint.x - mStrokeWidth) * mScaleVal; + canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, radius, mPaint); + } + + private void drawBorder(Canvas canvas) { + mFloorPaint.setColor(mFloorColor); + int radius = mCenterPoint.x; + canvas.drawCircle(mCenterPoint.x, mCenterPoint.y, radius * mFloorScale, mFloorPaint); + } + + private void drawTick(Canvas canvas) { + if (mTickDrawing && isChecked()) { + drawTickPath(canvas); + } + } + + private void drawTickPath(Canvas canvas) { + mTickPath.reset(); + // draw left of the tick + if (mDrewDistance < mLeftLineDistance) { + float step = (mWidth / 20.0f) < 3 ? 3 : (mWidth / 20.0f); + mDrewDistance += step; + float stopX = mTickPoints[0].x + (mTickPoints[1].x - mTickPoints[0].x) * mDrewDistance / mLeftLineDistance; + float stopY = mTickPoints[0].y + (mTickPoints[1].y - mTickPoints[0].y) * mDrewDistance / mLeftLineDistance; + + mTickPath.moveTo(mTickPoints[0].x, mTickPoints[0].y); + mTickPath.lineTo(stopX, stopY); + canvas.drawPath(mTickPath, mTickPaint); + + if (mDrewDistance > mLeftLineDistance) { + mDrewDistance = mLeftLineDistance; + } + } else { + + mTickPath.moveTo(mTickPoints[0].x, mTickPoints[0].y); + mTickPath.lineTo(mTickPoints[1].x, mTickPoints[1].y); + canvas.drawPath(mTickPath, mTickPaint); + + // draw right of the tick + if (mDrewDistance < mLeftLineDistance + mRightLineDistance) { + float stopX = mTickPoints[1].x + (mTickPoints[2].x - mTickPoints[1].x) * (mDrewDistance - mLeftLineDistance) / mRightLineDistance; + float stopY = mTickPoints[1].y - (mTickPoints[1].y - mTickPoints[2].y) * (mDrewDistance - mLeftLineDistance) / mRightLineDistance; + + mTickPath.reset(); + mTickPath.moveTo(mTickPoints[1].x, mTickPoints[1].y); + mTickPath.lineTo(stopX, stopY); + canvas.drawPath(mTickPath, mTickPaint); + + float step = (mWidth / 20) < 3 ? 3 : (mWidth / 20); + mDrewDistance += step; + } else { + mTickPath.reset(); + mTickPath.moveTo(mTickPoints[1].x, mTickPoints[1].y); + mTickPath.lineTo(mTickPoints[2].x, mTickPoints[2].y); + canvas.drawPath(mTickPath, mTickPaint); + } + } + + // invalidate + if (mDrewDistance < mLeftLineDistance + mRightLineDistance) { + postDelayed(new Runnable() { + @Override + public void run() { + postInvalidate(); + } + }, 10); + } + } + + private void startCheckedAnimation() { + ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0f); + animator.setDuration(mAnimDuration / 3 * 2); + animator.setInterpolator(new LinearInterpolator()); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mScaleVal = (float) animation.getAnimatedValue(); + mFloorColor = getGradientColor(mUnCheckedColor, mCheckedColor, 1 - mScaleVal); + postInvalidate(); + } + }); + animator.start(); + + ValueAnimator floorAnimator = ValueAnimator.ofFloat(1.0f, 0.8f, 1.0f); + floorAnimator.setDuration(mAnimDuration); + floorAnimator.setInterpolator(new LinearInterpolator()); + floorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mFloorScale = (float) animation.getAnimatedValue(); + postInvalidate(); + } + }); + floorAnimator.start(); + + drawTickDelayed(); + } + + private void startUnCheckedAnimation() { + ValueAnimator animator = ValueAnimator.ofFloat(0f, 1.0f); + animator.setDuration(mAnimDuration); + animator.setInterpolator(new LinearInterpolator()); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mScaleVal = (float) animation.getAnimatedValue(); + mFloorColor = getGradientColor(mCheckedColor, mFloorUnCheckedColor, mScaleVal); + postInvalidate(); + } + }); + animator.start(); + + ValueAnimator floorAnimator = ValueAnimator.ofFloat(1.0f, 0.8f, 1.0f); + floorAnimator.setDuration(mAnimDuration); + floorAnimator.setInterpolator(new LinearInterpolator()); + floorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mFloorScale = (float) animation.getAnimatedValue(); + postInvalidate(); + } + }); + floorAnimator.start(); + } + + private void drawTickDelayed() { + postDelayed(new Runnable() { + @Override + public void run() { + mTickDrawing = true; + postInvalidate(); + } + }, mAnimDuration); + } + + private static int getGradientColor(int startColor, int endColor, float percent) { + int startA = Color.alpha(startColor); + int startR = Color.red(startColor); + int startG = Color.green(startColor); + int startB = Color.blue(startColor); + + int endA = Color.alpha(endColor); + int endR = Color.red(endColor); + int endG = Color.green(endColor); + int endB = Color.blue(endColor); + + int currentA = (int) (startA * (1 - percent) + endA * percent); + int currentR = (int) (startR * (1 - percent) + endR * percent); + int currentG = (int) (startG * (1 - percent) + endG * percent); + int currentB = (int) (startB * (1 - percent) + endB * percent); + return Color.argb(currentA, currentR, currentG, currentB); + } + + public void setOnCheckedChangeListener(OnCheckedChangeListener l) { + this.mListener = l; + } + + public interface OnCheckedChangeListener { + void onCheckedChanged(SmoothCheckBox checkBox, boolean isChecked); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/widget/contentswitchview/BookContentView.java b/app/src/main/java/com/monke/monkeybook/widget/contentswitchview/BookContentView.java new file mode 100644 index 0000000000..91354603b0 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/contentswitchview/BookContentView.java @@ -0,0 +1,259 @@ +package com.monke.monkeybook.widget.contentswitchview; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Paint; +import android.os.Build; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.monke.monkeybook.R; +import com.monke.monkeybook.ReadBookControl; +import com.monke.monkeybook.widget.MTextView; + +import java.util.List; + +public class BookContentView extends FrameLayout { + public long qTag = System.currentTimeMillis(); + + public static final int DURPAGEINDEXBEGIN = -1; + public static final int DURPAGEINDEXEND = -2; + + private View view; + private ImageView ivBg; + private TextView tvTitle; + private LinearLayout llContent; + private MTextView tvContent; + private View vBottom; + private TextView tvPage; + + private TextView tvLoading; + private LinearLayout llError; + private TextView tvErrorInfo; + private TextView tvLoadAgain; + + private String title; + private String content; + private int durChapterIndex; + private int chapterAll; + private int durPageIndex; //如果durPageIndex = -1 则是从头开始 -2则是从尾开始 + private int pageAll; + + private ContentSwitchView.LoadDataListener loadDataListener; + + private SetDataListener setDataListener; + + public interface SetDataListener { + public void setDataFinish(BookContentView bookContentView, int durChapterIndex, int chapterAll, int durPageIndex, int pageAll, int fromPageIndex); + } + + public BookContentView(Context context) { + this(context, null); + } + + public BookContentView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public BookContentView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public BookContentView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + private void init() { + view = LayoutInflater.from(getContext()).inflate(R.layout.adapter_content_switch_item, this, false); + addView(view); + ivBg = (ImageView) view.findViewById(R.id.iv_bg); + tvTitle = (TextView) view.findViewById(R.id.tv_title); + llContent = (LinearLayout) view.findViewById(R.id.ll_content); + tvContent = (com.monke.monkeybook.widget.MTextView) view.findViewById(R.id.tv_content); + vBottom = view.findViewById(R.id.v_bottom); + tvPage = (TextView) view.findViewById(R.id.tv_page); + + tvLoading = (TextView) view.findViewById(R.id.tv_loading); + llError = (LinearLayout) view.findViewById(R.id.ll_error); + tvErrorInfo = (TextView) view.findViewById(R.id.tv_error_info); + tvLoadAgain = (TextView) view.findViewById(R.id.tv_load_again); + + tvLoadAgain.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (loadDataListener != null) + loading(); + } + }); + } + + public void loading() { + llError.setVisibility(GONE); + tvLoading.setVisibility(VISIBLE); + llContent.setVisibility(INVISIBLE); + qTag = System.currentTimeMillis(); + //执行请求操作 + if (loadDataListener != null) { + loadDataListener.loaddata(this, qTag, durChapterIndex, durPageIndex); + } + } + + public void finishLoading() { + llError.setVisibility(GONE); + llContent.setVisibility(VISIBLE); + tvLoading.setVisibility(GONE); + } + + public void setNoData(String contentLines) { + this.content = contentLines; + + tvPage.setText((this.durPageIndex + 1) + "/" + this.pageAll); + + finishLoading(); + } + + public void updateData(long tag, String title, List contentLines, int durChapterIndex, int chapterAll, int durPageIndex, int durPageAll) { + if (tag == qTag) { + if (setDataListener != null) { + setDataListener.setDataFinish(this, durChapterIndex, chapterAll, durPageIndex, durPageAll, this.durPageIndex); + } + if (contentLines == null) { + this.content = ""; + } else { + StringBuilder s = new StringBuilder(); + for (int i = 0; i < contentLines.size(); i++) { + s.append(contentLines.get(i)); + } + this.content = s.toString(); + } + this.title = title; + this.durChapterIndex = durChapterIndex; + this.chapterAll = chapterAll; + this.durPageIndex = durPageIndex; + this.pageAll = durPageAll; + + tvTitle.setText(this.title); + tvContent.setText(this.content); + tvPage.setText((this.durPageIndex + 1) + "/" + this.pageAll); + + finishLoading(); + } + } + + public void loadData(String title, int durChapterIndex, int chapterAll, int durPageIndex) { + this.title = title; + this.durChapterIndex = durChapterIndex; + this.chapterAll = chapterAll; + this.durPageIndex = durPageIndex; + tvTitle.setText(title); + tvPage.setText(""); + + loading(); + } + + public ContentSwitchView.LoadDataListener getLoadDataListener() { + return loadDataListener; + } + + public void setLoadDataListener(ContentSwitchView.LoadDataListener loadDataListener, SetDataListener setDataListener) { + this.loadDataListener = loadDataListener; + this.setDataListener = setDataListener; + } + + public void setLoadDataListener(ContentSwitchView.LoadDataListener loadDataListener) { + this.loadDataListener = loadDataListener; + } + + public void loadError() { + llError.setVisibility(VISIBLE); + tvLoading.setVisibility(GONE); + llContent.setVisibility(INVISIBLE); + } + + public int getPageAll() { + return pageAll; + } + + public void setPageAll(int pageAll) { + this.pageAll = pageAll; + } + + public int getDurPageIndex() { + return durPageIndex; + } + + public void setDurPageIndex(int durPageIndex) { + this.durPageIndex = durPageIndex; + } + + public int getDurChapterIndex() { + return durChapterIndex; + } + + public void setDurChapterIndex(int durChapterIndex) { + this.durChapterIndex = durChapterIndex; + } + + public int getChapterAll() { + return chapterAll; + } + + public void setChapterAll(int chapterAll) { + this.chapterAll = chapterAll; + } + + public SetDataListener getSetDataListener() { + return setDataListener; + } + + public void setSetDataListener(SetDataListener setDataListener) { + this.setDataListener = setDataListener; + } + + public long getqTag() { + return qTag; + } + + public void setqTag(long qTag) { + this.qTag = qTag; + } + + public TextView getTvContent() { + return tvContent; + } + + public int getLineCount(int height) { + float ascent = tvContent.getPaint().ascent(); + float descent = tvContent.getPaint().descent(); + float textHeight = descent - ascent; + return (int) ((height * 1.0f - tvContent.getLineSpacingExtra()) / (textHeight + tvContent.getLineSpacingExtra())); + } + + public void setReadBookControl(ReadBookControl readBookControl) { + setTextKind(readBookControl); + setBg(readBookControl); + } + + public void setBg(ReadBookControl readBookControl) { + ivBg.setImageResource(readBookControl.getTextBackground()); + tvTitle.setTextColor(readBookControl.getTextColor()); + tvContent.setTextColor(readBookControl.getTextColor()); + tvPage.setTextColor(readBookControl.getTextColor()); + vBottom.setBackgroundColor(readBookControl.getTextColor()); + tvLoading.setTextColor(readBookControl.getTextColor()); + tvErrorInfo.setTextColor(readBookControl.getTextColor()); + } + + public void setTextKind(ReadBookControl readBookControl) { + tvContent.setTextSize(readBookControl.getTextSize()); + tvContent.setLineSpacing(readBookControl.getTextExtra(), 1); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/contentswitchview/ContentSwitchView.java b/app/src/main/java/com/monke/monkeybook/widget/contentswitchview/ContentSwitchView.java new file mode 100644 index 0000000000..6feefcc8fb --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/contentswitchview/ContentSwitchView.java @@ -0,0 +1,518 @@ +package com.monke.monkeybook.widget.contentswitchview; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Paint; +import android.os.Build; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewTreeObserver; +import android.widget.FrameLayout; +import android.widget.Toast; +import com.monke.monkeybook.ReadBookControl; +import com.monke.monkeybook.utils.DensityUtil; +import java.util.ArrayList; +import java.util.List; + +public class ContentSwitchView extends FrameLayout implements BookContentView.SetDataListener { + private final long animDuration = 300; + public final static int NONE = -1; + public final static int PREANDNEXT = 0; + public final static int ONLYPRE = 1; + public final static int ONLYNEXT = 2; + private int state = NONE; //0是有上一页 也有下一页 ; 2是只有下一页 ;1是只有上一页;-1是没有上一页 也没有下一页; + + private int scrollX; + private Boolean isMoving = false; + + private BookContentView durPageView; + private List viewContents; + + public interface OnBookReadInitListener{ + public void success(); + } + private OnBookReadInitListener bookReadInitListener; + + public ContentSwitchView(Context context) { + super(context); + init(); + } + + public ContentSwitchView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public ContentSwitchView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public ContentSwitchView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + private ReadBookControl readBookControl; + + private void init() { + readBookControl = ReadBookControl.getInstance(); + + scrollX = DensityUtil.dp2px(getContext(), 30f); + durPageView = new BookContentView(getContext()); + durPageView.setReadBookControl(readBookControl); + + viewContents = new ArrayList<>(); + viewContents.add(durPageView); + + addView(durPageView); + } + + + public void bookReadInit(OnBookReadInitListener bookReadInitListener){ + this.bookReadInitListener = bookReadInitListener; + durPageView.getTvContent().getViewTreeObserver().addOnGlobalLayoutListener(layoutInitListener); + } + public void startLoading(){ + int height = durPageView.getTvContent().getHeight(); + if (height > 0) { + if (loadDataListener != null && durHeight != height) { + durHeight = height; + loadDataListener.initData(durPageView.getLineCount(height)); + } + } + durPageView.getTvContent().getViewTreeObserver().addOnGlobalLayoutListener(layoutListener); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + private float startX = -1; + + @Override + public boolean onTouchEvent(MotionEvent event) { + int action = event.getAction(); + if (!isMoving) { + switch (action) { + case MotionEvent.ACTION_DOWN: + startX = event.getX(); + break; + case MotionEvent.ACTION_MOVE: + if(viewContents.size() > 1){ + if (startX == -1) + startX = event.getX(); + int durX = (int) (event.getX() - startX); + if (durX > 0 && (state == PREANDNEXT || state == ONLYPRE)) { + int tempX = durX - getWidth(); + if (tempX < -getWidth()) + tempX = -getWidth(); + else if (tempX > 0) + tempX = 0; + viewContents.get(0).layout(tempX, viewContents.get(0).getTop(), tempX + getWidth(), viewContents.get(0).getBottom()); + } else if (durX < 0 && (state == PREANDNEXT || state == ONLYNEXT)) { + int tempX = durX; + if (tempX > 0) + tempX = 0; + else if (tempX < -getWidth()) + tempX = -getWidth(); + int tempIndex = (state == PREANDNEXT ? 1 : 0); + viewContents.get(tempIndex).layout(tempX, viewContents.get(tempIndex).getTop(), tempX + getWidth(), viewContents.get(tempIndex).getBottom()); + } + } + break; + case MotionEvent.ACTION_UP: + if(startX == -1) + startX = event.getX(); + if (event.getX() - startX > 0) { + if (state == PREANDNEXT || state == ONLYPRE) { + if (event.getX() - startX > scrollX) { + //向前翻页成功 + initMoveSuccessAnim(viewContents.get(0), 0); + } else { + initMoveFailAnim(viewContents.get(0), -getWidth()); + } + } else { + //没有上一页 + noPre(); + } + } else if (event.getX() - startX < 0) { + if (state == PREANDNEXT || state == ONLYNEXT) { + int tempIndex = (state == PREANDNEXT ? 1 : 0); + if (startX - event.getX() > scrollX) { + //向后翻页成功 + initMoveSuccessAnim(viewContents.get(tempIndex), -getWidth()); + } else { + initMoveFailAnim(viewContents.get(tempIndex), 0); + } + } else { + //没有下一页 + noNext(); + } + } else { + //点击事件 + if (readBookControl.getCanClickTurn() && event.getX() <= getWidth() / 3) { + //点击向前翻页 + if (state == PREANDNEXT || state == ONLYPRE) { + initMoveSuccessAnim(viewContents.get(0), 0); + } else { + noPre(); + } + } else if (readBookControl.getCanClickTurn() && event.getX() >= getWidth() / 3 * 2) { + //点击向后翻页 + if (state == PREANDNEXT || state == ONLYNEXT) { + int tempIndex = (state == PREANDNEXT ? 1 : 0); + initMoveSuccessAnim(viewContents.get(tempIndex), -getWidth()); + } else { + noNext(); + } + } else { + //点击中间部位 + if (loadDataListener != null) + loadDataListener.showMenu(); + } + } + startX = -1; + break; + default: + break; + } + } + return super.onTouchEvent(event); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (viewContents.size() > 0) { + if (state == NONE && viewContents.size() >= 1) { + viewContents.get(0).layout(0, top, getWidth(), bottom); + } else if (state == PREANDNEXT && viewContents.size() >= 3) { + viewContents.get(0).layout(-getWidth(), top, 0, bottom); + viewContents.get(1).layout(0, top, getWidth(), bottom); + viewContents.get(2).layout(0, top, getWidth(), bottom); + } else if (state == ONLYPRE && viewContents.size() >= 2) { + viewContents.get(0).layout(-getWidth(), top, 0, bottom); + viewContents.get(1).layout(0, top, getWidth(), bottom); + } else if (viewContents.size() >= 2) { + viewContents.get(0).layout(0, top, getWidth(), bottom); + viewContents.get(1).layout(0, top, getWidth(), bottom); + } + } else { + super.onLayout(changed, left, top, right, bottom); + } + } + + private void initMoveSuccessAnim(final View view, final int orderX) { + if (null != view) { + long temp = Math.abs(view.getLeft() - orderX) / (getWidth() / animDuration); + ValueAnimator tempAnim = ValueAnimator.ofInt(view.getLeft(), orderX).setDuration(temp); + tempAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + if (null != view) { + int value = (int) animation.getAnimatedValue(); + view.layout(value, view.getTop(), value + getWidth(), view.getBottom()); + } + } + }); + tempAnim.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + isMoving = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + isMoving = false; + if (orderX == 0) { + //翻向前一页 + durPageView = viewContents.get(0); + if (state == PREANDNEXT) { + ContentSwitchView.this.removeView(viewContents.get(viewContents.size() - 1)); + viewContents.remove(viewContents.size() - 1); + } + state = ONLYNEXT; + if(durPageView.getDurChapterIndex()-1>=0 || durPageView.getDurPageIndex()-1>=0){ + addPrePage(durPageView.getDurChapterIndex(), durPageView.getChapterAll(), durPageView.getDurPageIndex(), durPageView.getPageAll()); + if (state == NONE) + state = ONLYPRE; + else state = PREANDNEXT; + } + } else { + //翻向后一夜 + if (state == ONLYNEXT) { + durPageView = viewContents.get(1); + } else { + durPageView = viewContents.get(2); + ContentSwitchView.this.removeView(viewContents.get(0)); + viewContents.remove(0); + } + state = ONLYPRE; + if(durPageView.getDurChapterIndex()+1 <=durPageView.getChapterAll()-1 || durPageView.getDurPageIndex()+1 <= durPageView.getPageAll()-1){ + addNextPage(durPageView.getDurChapterIndex(), durPageView.getChapterAll(), durPageView.getDurPageIndex(), durPageView.getPageAll()); + if (state == NONE) + state = ONLYNEXT; + else state = PREANDNEXT; + } + } + if (loadDataListener != null) + loadDataListener.updateProgress(durPageView.getDurChapterIndex(), durPageView.getDurPageIndex()); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + tempAnim.start(); + } + } + + private void initMoveFailAnim(final View view, int orderX) { + if (null != view) { + long temp = Math.abs(view.getLeft() - orderX) / (getWidth() / animDuration); + ValueAnimator tempAnim = ValueAnimator.ofInt(view.getLeft(), orderX).setDuration(temp); + tempAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + if (null != view) { + int value = (int) animation.getAnimatedValue(); + view.layout(value, view.getTop(), value + getWidth(), view.getBottom()); + } + } + }); + tempAnim.start(); + } + } + + public void setInitData(int durChapterIndex, int chapterAll, int durPageIndex) { + updateOtherPage(durChapterIndex, chapterAll, durPageIndex, -1); + durPageView.setLoadDataListener(loadDataListener, this); + durPageView.loadData(null != loadDataListener ? loadDataListener.getChapterTitle(durChapterIndex) : "", durChapterIndex, chapterAll, durPageIndex); + + if (loadDataListener != null) + loadDataListener.updateProgress(durPageView.getDurChapterIndex(), durPageView.getDurPageIndex()); + } + + private void updateOtherPage(int durChapterIndex, int chapterAll, int durPageIndex, int pageAll) { + if (chapterAll > 1 || pageAll > 1) { + if ((durChapterIndex == 0 && pageAll == -1) || (durChapterIndex == 0 && durPageIndex == 0 && pageAll != -1)) { + //ONLYNEXT + addNextPage(durChapterIndex, chapterAll, durPageIndex, pageAll); + if (state == ONLYPRE || state == PREANDNEXT) { + this.removeView(viewContents.get(0)); + viewContents.remove(0); + } + state = ONLYNEXT; + } else if ((durChapterIndex == chapterAll - 1 && pageAll == -1) || (durChapterIndex == chapterAll - 1 && durPageIndex == pageAll - 1 && pageAll != -1)) { + //ONLYPRE + addPrePage(durChapterIndex, chapterAll, durPageIndex, pageAll); + if (state == ONLYNEXT || state == PREANDNEXT) { + this.removeView(viewContents.get(2)); + viewContents.remove(2); + } + state = ONLYPRE; + } else { + //PREANDNEXT + addNextPage(durChapterIndex, chapterAll, durPageIndex, pageAll); + addPrePage(durChapterIndex, chapterAll, durPageIndex, pageAll); + state = PREANDNEXT; + } + } else { + //NONE + if (state == ONLYPRE) { + this.removeView(viewContents.get(0)); + viewContents.remove(0); + } else if (state == ONLYNEXT) { + this.removeView(viewContents.get(1)); + viewContents.remove(1); + } else if (state == PREANDNEXT) { + this.removeView(viewContents.get(0)); + this.removeView(viewContents.get(2)); + viewContents.remove(2); + viewContents.remove(0); + } + state = NONE; + } + } + + private void addNextPage(int durChapterIndex, int chapterAll, int durPageIndex, int pageAll) { + if (state == ONLYNEXT || state == PREANDNEXT) { + int temp = (state == ONLYNEXT ? 1 : 2); + if (pageAll > 0 && durPageIndex >= 0 && durPageIndex < pageAll - 1) + viewContents.get(temp).loadData(null != loadDataListener ? loadDataListener.getChapterTitle(durChapterIndex) : "", durChapterIndex, chapterAll, durPageIndex + 1); + else + viewContents.get(temp).loadData(null != loadDataListener ? loadDataListener.getChapterTitle(durChapterIndex + 1) : "", durChapterIndex + 1, chapterAll, BookContentView.DURPAGEINDEXBEGIN); + } else if (state == ONLYPRE || state == NONE) { + BookContentView next = new BookContentView(getContext()); + next.setReadBookControl(readBookControl); + next.setLoadDataListener(loadDataListener, this); + if (pageAll > 0 && durPageIndex >= 0 && durPageIndex < pageAll - 1) + next.loadData(null != loadDataListener ? loadDataListener.getChapterTitle(durChapterIndex) : "", durChapterIndex, chapterAll, durPageIndex + 1); + else + next.loadData(null != loadDataListener ? loadDataListener.getChapterTitle(durChapterIndex + 1) : "", durChapterIndex + 1, chapterAll, BookContentView.DURPAGEINDEXBEGIN); + viewContents.add(next); + this.addView(next, 0); + } + } + + private void addPrePage(int durChapterIndex, int chapterAll, int durPageIndex, int pageAll) { + if (state == ONLYNEXT || state == NONE) { + BookContentView pre = new BookContentView(getContext()); + pre.setReadBookControl(readBookControl); + pre.setLoadDataListener(loadDataListener, this); + if (pageAll > 0 && durPageIndex >= 0 && durPageIndex > 0) + pre.loadData(null != loadDataListener ? loadDataListener.getChapterTitle(durChapterIndex) : "", durChapterIndex, chapterAll, durPageIndex - 1); + else + pre.loadData(null != loadDataListener ? loadDataListener.getChapterTitle(durChapterIndex - 1) : "", durChapterIndex - 1, chapterAll, BookContentView.DURPAGEINDEXEND); + viewContents.add(0, pre); + this.addView(pre); + } else if (state == ONLYPRE || state == PREANDNEXT) { + if (pageAll > 0 && durPageIndex >= 0 && durPageIndex > 0) + viewContents.get(0).loadData(null != loadDataListener ? loadDataListener.getChapterTitle(durChapterIndex) : "", durChapterIndex, chapterAll, durPageIndex - 1); + else + viewContents.get(0).loadData(null != loadDataListener ? loadDataListener.getChapterTitle(durChapterIndex - 1) : "", durChapterIndex - 1, chapterAll, BookContentView.DURPAGEINDEXEND); + } + } + + + @Override + public void setDataFinish(BookContentView bookContentView, int durChapterIndex, int chapterAll, int durPageIndex, int pageAll, int fromPageIndex) { + if (null != getDurContentView() && bookContentView == getDurContentView() && chapterAll > 0 && pageAll > 0) { + updateOtherPage(durChapterIndex, chapterAll, durPageIndex, pageAll); + } + } + + public interface LoadDataListener { + public void loaddata(BookContentView bookContentView, long tag, int chapterIndex, int pageIndex); + + public void updateProgress(int chapterIndex, int pageIndex); + + public String getChapterTitle(int chapterIndex); + + public void initData(int lineCount); + + public void showMenu(); + } + + private LoadDataListener loadDataListener; + + public LoadDataListener getLoadDataListener() { + return loadDataListener; + } + + public void setLoadDataListener(LoadDataListener loadDataListener) { + this.loadDataListener = loadDataListener; + } + + public BookContentView getDurContentView() { + return durPageView; + } + + private void noPre() { + Toast.makeText(getContext(), "没有上一页", Toast.LENGTH_SHORT).show(); + } + + private void noNext() { + Toast.makeText(getContext(), "没有下一页", Toast.LENGTH_SHORT).show(); + } + + private ViewTreeObserver.OnGlobalLayoutListener layoutInitListener = new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + if(bookReadInitListener !=null){ + bookReadInitListener.success(); + } + durPageView.getTvContent().getViewTreeObserver().removeOnGlobalLayoutListener(layoutInitListener); + } + }; + private ViewTreeObserver.OnGlobalLayoutListener layoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + int height = durPageView.getTvContent().getHeight(); + if (height > 0) { + if (loadDataListener != null && durHeight != height) { + durHeight = height; + loadDataListener.initData(durPageView.getLineCount(height)); + } + } + } + }; + + private int durHeight = 0; + + public Paint getTextPaint() { + return durPageView.getTvContent().getPaint(); + } + + public int getContentWidth(){ + return durPageView.getTvContent().getWidth(); + } + + public void changeBg(){ + for(BookContentView item : viewContents){ + item.setBg(readBookControl); + } + } + + public void changeTextSize(){ + for(BookContentView item : viewContents){ + item.setTextKind(readBookControl); + } + loadDataListener.initData(durPageView.getLineCount(durHeight)); + } + + public boolean onKeyDown(int keyCode, KeyEvent event){ + if(readBookControl.getCanKeyTurn() && keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){ + if (state == PREANDNEXT || state == ONLYNEXT) { + int tempIndex = (state == PREANDNEXT ? 1 : 0); + initMoveSuccessAnim(viewContents.get(tempIndex), -getWidth()); + } else { + noNext(); + } + return true; + }else if(readBookControl.getCanKeyTurn() && keyCode == KeyEvent.KEYCODE_VOLUME_UP){ + if (state == PREANDNEXT || state == ONLYPRE) { + initMoveSuccessAnim(viewContents.get(0), 0); + } else { + noPre(); + } + return true; + } + return false; + } + + public boolean onKeyUp(int keyCode, KeyEvent event){ + if(readBookControl.getCanKeyTurn() && keyCode == KeyEvent.KEYCODE_VOLUME_DOWN){ + return true; + }else if(readBookControl.getCanKeyTurn() && keyCode == KeyEvent.KEYCODE_VOLUME_UP){ + return true; + } + return false; + } + + public OnBookReadInitListener getBookReadInitListener() { + return bookReadInitListener; + } + + public void setBookReadInitListener(OnBookReadInitListener bookReadInitListener) { + this.bookReadInitListener = bookReadInitListener; + } + + public void loadError(){ + if(durPageView != null){ + durPageView.loadError(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/widget/flowlayout/FlowLayout.java b/app/src/main/java/com/monke/monkeybook/widget/flowlayout/FlowLayout.java new file mode 100644 index 0000000000..fe57a59607 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/flowlayout/FlowLayout.java @@ -0,0 +1,221 @@ +package com.monke.monkeybook.widget.flowlayout; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import com.monke.monkeybook.R; +import java.util.ArrayList; +import java.util.List; + +public class FlowLayout extends ViewGroup +{ + private static final String TAG = "FlowLayout"; + private static final int LEFT = -1; + private static final int CENTER = 0; + private static final int RIGHT = 1; + + protected List> mAllViews = new ArrayList>(); + protected List mLineHeight = new ArrayList(); + protected List mLineWidth = new ArrayList(); + private int mGravity; + private List lineViews = new ArrayList<>(); + + public FlowLayout(Context context, AttributeSet attrs, int defStyle) + { + super(context, attrs, defStyle); + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TagFlowLayout); + mGravity = ta.getInt(R.styleable.TagFlowLayout_gravity,LEFT); + ta.recycle(); + } + + public FlowLayout(Context context, AttributeSet attrs) + { + this(context, attrs, 0); + } + + public FlowLayout(Context context) + { + this(context, null); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) + { + int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); + int modeWidth = MeasureSpec.getMode(widthMeasureSpec); + int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); + int modeHeight = MeasureSpec.getMode(heightMeasureSpec); + + // wrap_content + int width = 0; + int height = 0; + + int lineWidth = 0; + int lineHeight = 0; + + int cCount = getChildCount(); + + for (int i = 0; i < cCount; i++) + { + View child = getChildAt(i); + if (child.getVisibility() == View.GONE) + { + if (i == cCount - 1) + { + width = Math.max(lineWidth, width); + height += lineHeight; + } + continue; + } + measureChild(child, widthMeasureSpec, heightMeasureSpec); + MarginLayoutParams lp = (MarginLayoutParams) child + .getLayoutParams(); + + int childWidth = child.getMeasuredWidth() + lp.leftMargin + + lp.rightMargin; + int childHeight = child.getMeasuredHeight() + lp.topMargin + + lp.bottomMargin; + + if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight()) + { + width = Math.max(width, lineWidth); + lineWidth = childWidth; + height += lineHeight; + lineHeight = childHeight; + } else + { + lineWidth += childWidth; + lineHeight = Math.max(lineHeight, childHeight); + } + if (i == cCount - 1) + { + width = Math.max(lineWidth, width); + height += lineHeight; + } + } + setMeasuredDimension( + // + modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width + getPaddingLeft() + getPaddingRight(), + modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height + getPaddingTop() + getPaddingBottom()// + ); + + } + + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) + { + mAllViews.clear(); + mLineHeight.clear(); + mLineWidth.clear(); + lineViews.clear(); + + int width = getWidth(); + + int lineWidth = 0; + int lineHeight = 0; + + int cCount = getChildCount(); + + for (int i = 0; i < cCount; i++) + { + View child = getChildAt(i); + if (child.getVisibility() == View.GONE) continue; + MarginLayoutParams lp = (MarginLayoutParams) child + .getLayoutParams(); + + int childWidth = child.getMeasuredWidth(); + int childHeight = child.getMeasuredHeight(); + + if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width - getPaddingLeft() - getPaddingRight()) + { + mLineHeight.add(lineHeight); + mAllViews.add(lineViews); + mLineWidth.add(lineWidth); + + lineWidth = 0; + lineHeight = childHeight + lp.topMargin + lp.bottomMargin; + lineViews = new ArrayList(); + } + lineWidth += childWidth + lp.leftMargin + lp.rightMargin; + lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + + lp.bottomMargin); + lineViews.add(child); + + } + mLineHeight.add(lineHeight); + mLineWidth.add(lineWidth); + mAllViews.add(lineViews); + + + + int left = getPaddingLeft(); + int top = getPaddingTop(); + + int lineNum = mAllViews.size(); + + for (int i = 0; i < lineNum; i++) + { + lineViews = mAllViews.get(i); + lineHeight = mLineHeight.get(i); + + // set gravity + int currentLineWidth = this.mLineWidth.get(i); + switch (this.mGravity){ + case LEFT: + left = getPaddingLeft(); + break; + case CENTER: + left = (width - currentLineWidth)/2+getPaddingLeft(); + break; + case RIGHT: + left = width - currentLineWidth + getPaddingLeft(); + break; + } + + for (int j = 0; j < lineViews.size(); j++) + { + View child = lineViews.get(j); + if (child.getVisibility() == View.GONE) + { + continue; + } + + MarginLayoutParams lp = (MarginLayoutParams) child + .getLayoutParams(); + + int lc = left + lp.leftMargin; + int tc = top + lp.topMargin; + int rc = lc + child.getMeasuredWidth(); + int bc = tc + child.getMeasuredHeight(); + + child.layout(lc, tc, rc, bc); + + left += child.getMeasuredWidth() + lp.leftMargin + + lp.rightMargin; + } + top += lineHeight; + } + + } + + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) + { + return new MarginLayoutParams(getContext(), attrs); + } + + @Override + protected LayoutParams generateDefaultLayoutParams() + { + return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + } + + @Override + protected LayoutParams generateLayoutParams(LayoutParams p) + { + return new MarginLayoutParams(p); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/flowlayout/TagAdapter.java b/app/src/main/java/com/monke/monkeybook/widget/flowlayout/TagAdapter.java new file mode 100644 index 0000000000..b9f7a58f11 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/flowlayout/TagAdapter.java @@ -0,0 +1,82 @@ +package com.monke.monkeybook.widget.flowlayout; + +import android.view.View; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public abstract class TagAdapter { + protected List mTagDatas; + private OnDataChangedListener mOnDataChangedListener; + protected HashSet mCheckedPosList = new HashSet(); + + public TagAdapter(){ + + } + + public TagAdapter(List datas) { + mTagDatas = datas; + } + + public TagAdapter(T[] datas) { + mTagDatas = new ArrayList(Arrays.asList(datas)); + } + + interface OnDataChangedListener { + void onChanged(); + } + + void setOnDataChangedListener(OnDataChangedListener listener) { + mOnDataChangedListener = listener; + } + + public void setSelectedList(int... poses) { + Set set = new HashSet<>(); + for (int pos : poses) { + set.add(pos); + } + setSelectedList(set); + } + + public void setSelectedList(Set set) { + mCheckedPosList.clear(); + if (set != null) + mCheckedPosList.addAll(set); + notifyDataChanged(); + } + + public synchronized void replaceAll(List newDatas){ + mTagDatas.clear(); + if(newDatas != null) + mTagDatas.addAll(newDatas); + notifyDataChanged(); + } + + HashSet getPreCheckedList() { + return mCheckedPosList; + } + + + public int getCount() { + return mTagDatas == null ? 0 : mTagDatas.size(); + } + + public void notifyDataChanged() { + mOnDataChangedListener.onChanged(); + } + + public T getItem(int position) { + return mTagDatas.get(position); + } + + public abstract View getView(FlowLayout parent, int position, T t); + + public boolean setSelected(int position, T t) { + return false; + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/widget/flowlayout/TagFlowLayout.java b/app/src/main/java/com/monke/monkeybook/widget/flowlayout/TagFlowLayout.java new file mode 100644 index 0000000000..2e2cc275ff --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/flowlayout/TagFlowLayout.java @@ -0,0 +1,340 @@ +package com.monke.monkeybook.widget.flowlayout; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Rect; +import android.os.Bundle; +import android.os.Parcelable; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; + +import com.monke.monkeybook.R; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +public class TagFlowLayout extends FlowLayout implements TagAdapter.OnDataChangedListener +{ + private TagAdapter mTagAdapter; + private boolean mAutoSelectEffect = true; + private int mSelectedMax = -1;//-1为不限制数量 + private static final String TAG = "TagFlowLayout"; + private MotionEvent mMotionEvent; + + private Set mSelectedView = new HashSet(); + + + public TagFlowLayout(Context context, AttributeSet attrs, int defStyle) + { + super(context, attrs, defStyle); + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TagFlowLayout); + mAutoSelectEffect = ta.getBoolean(R.styleable.TagFlowLayout_auto_select_effect, true); + mSelectedMax = ta.getInt(R.styleable.TagFlowLayout_max_select, -1); + ta.recycle(); + + if (mAutoSelectEffect) + { + setClickable(true); + } + } + + public TagFlowLayout(Context context, AttributeSet attrs) + { + this(context, attrs, 0); + } + + public TagFlowLayout(Context context) + { + this(context, null); + } + + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) + { + int cCount = getChildCount(); + + for (int i = 0; i < cCount; i++) + { + TagView tagView = (TagView) getChildAt(i); + if (tagView.getVisibility() == View.GONE) continue; + if (tagView.getTagView().getVisibility() == View.GONE) + { + tagView.setVisibility(View.GONE); + } + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + public interface OnSelectListener + { + void onSelected(Set selectPosSet); + } + + private OnSelectListener mOnSelectListener; + + public void setOnSelectListener(OnSelectListener onSelectListener) + { + mOnSelectListener = onSelectListener; + if (mOnSelectListener != null) setClickable(true); + } + + public interface OnTagClickListener + { + boolean onTagClick(View view, int position, FlowLayout parent); + } + + private OnTagClickListener mOnTagClickListener; + + public void setOnTagClickListener(OnTagClickListener onTagClickListener) + { + mOnTagClickListener = onTagClickListener; + if (onTagClickListener != null) setClickable(true); + } + + + public void setAdapter(TagAdapter adapter) + { + mTagAdapter = adapter; + mTagAdapter.setOnDataChangedListener(this); + mSelectedView.clear(); + changeAdapter(); + + } + + private void changeAdapter() + { + removeAllViews(); + TagAdapter adapter = mTagAdapter; + TagView tagViewContainer = null; + HashSet preCheckedList = mTagAdapter.getPreCheckedList(); + for (int i = 0; i < adapter.getCount(); i++) + { + View tagView = adapter.getView(this, i, adapter.getItem(i)); + + tagViewContainer = new TagView(getContext()); +// ViewGroup.MarginLayoutParams clp = (ViewGroup.MarginLayoutParams) tagView.getLayoutParams(); +// ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(clp); +// lp.width = ViewGroup.LayoutParams.WRAP_CONTENT; +// lp.height = ViewGroup.LayoutParams.WRAP_CONTENT; +// lp.topMargin = clp.topMargin; +// lp.bottomMargin = clp.bottomMargin; +// lp.leftMargin = clp.leftMargin; +// lp.rightMargin = clp.rightMargin; + tagView.setDuplicateParentStateEnabled(true); + if (tagView.getLayoutParams() != null) + { + tagViewContainer.setLayoutParams(tagView.getLayoutParams()); + } else + { + MarginLayoutParams lp = new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + lp.setMargins(dip2px(getContext(), 5), + dip2px(getContext(), 5), + dip2px(getContext(), 5), + dip2px(getContext(), 5)); + tagViewContainer.setLayoutParams(lp); + } + tagViewContainer.addView(tagView); + addView(tagViewContainer); + + + if (preCheckedList.contains(i)) + { + tagViewContainer.setChecked(true); + } + + if (mTagAdapter.setSelected(i, adapter.getItem(i))) + { + mSelectedView.add(i); + tagViewContainer.setChecked(true); + } + } + mSelectedView.addAll(preCheckedList); + + } + + + @Override + public boolean onTouchEvent(MotionEvent event) + { + if (event.getAction() == MotionEvent.ACTION_UP) + { + mMotionEvent = MotionEvent.obtain(event); + } + return super.onTouchEvent(event); + } + + @Override + public boolean performClick() + { + if (mMotionEvent == null) return super.performClick(); + + int x = (int) mMotionEvent.getX(); + int y = (int) mMotionEvent.getY(); + mMotionEvent = null; + + TagView child = findChild(x, y); + int pos = findPosByView(child); + if (child != null) + { + doSelect(child, pos); + if (mOnTagClickListener != null) + { + return mOnTagClickListener.onTagClick(child.getTagView(), pos, this); + } + } + return true; + } + + + public void setMaxSelectCount(int count) + { + if (mSelectedView.size() > count) + { + Log.w(TAG, "you has already select more than " + count + " views , so it will be clean ."); + mSelectedView.clear(); + } + mSelectedMax = count; + } + + public Set getSelectedList() + { + return new HashSet(mSelectedView); + } + + private void doSelect(TagView child, int position) + { + if (mAutoSelectEffect) + { + if (!child.isChecked()) + { + //处理max_select=1的情况 + if (mSelectedMax == 1 && mSelectedView.size() == 1) + { + Iterator iterator = mSelectedView.iterator(); + Integer preIndex = iterator.next(); + TagView pre = (TagView) getChildAt(preIndex); + pre.setChecked(false); + child.setChecked(true); + mSelectedView.remove(preIndex); + mSelectedView.add(position); + } else + { + if (mSelectedMax > 0 && mSelectedView.size() >= mSelectedMax) + return; + child.setChecked(true); + mSelectedView.add(position); + } + } else + { + child.setChecked(false); + mSelectedView.remove(position); + } + if (mOnSelectListener != null) + { + mOnSelectListener.onSelected(new HashSet(mSelectedView)); + } + } + } + + public TagAdapter getAdapter() + { + return mTagAdapter; + } + + + private static final String KEY_CHOOSE_POS = "key_choose_pos"; + private static final String KEY_DEFAULT = "key_default"; + + + @Override + protected Parcelable onSaveInstanceState() + { + Bundle bundle = new Bundle(); + bundle.putParcelable(KEY_DEFAULT, super.onSaveInstanceState()); + + String selectPos = ""; + if (mSelectedView.size() > 0) + { + for (int key : mSelectedView) + { + selectPos += key + "|"; + } + selectPos = selectPos.substring(0, selectPos.length() - 1); + } + bundle.putString(KEY_CHOOSE_POS, selectPos); + return bundle; + } + + @Override + protected void onRestoreInstanceState(Parcelable state) + { + if (state instanceof Bundle) + { + Bundle bundle = (Bundle) state; + String mSelectPos = bundle.getString(KEY_CHOOSE_POS); + if (!TextUtils.isEmpty(mSelectPos)) + { + String[] split = mSelectPos.split("\\|"); + for (String pos : split) + { + int index = Integer.parseInt(pos); + mSelectedView.add(index); + + TagView tagView = (TagView) getChildAt(index); + if (tagView != null) + tagView.setChecked(true); + } + + } + super.onRestoreInstanceState(bundle.getParcelable(KEY_DEFAULT)); + return; + } + super.onRestoreInstanceState(state); + } + + private int findPosByView(View child) + { + final int cCount = getChildCount(); + for (int i = 0; i < cCount; i++) + { + View v = getChildAt(i); + if (v == child) return i; + } + return -1; + } + + private TagView findChild(int x, int y) + { + final int cCount = getChildCount(); + for (int i = 0; i < cCount; i++) + { + TagView v = (TagView) getChildAt(i); + if (v.getVisibility() == View.GONE) continue; + Rect outRect = new Rect(); + v.getHitRect(outRect); + if (outRect.contains(x, y)) + { + return v; + } + } + return null; + } + + @Override + public void onChanged() + { + mSelectedView.clear(); + changeAdapter(); + } + + public static int dip2px(Context context, float dpValue) + { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/flowlayout/TagView.java b/app/src/main/java/com/monke/monkeybook/widget/flowlayout/TagView.java new file mode 100644 index 0000000000..7590749437 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/flowlayout/TagView.java @@ -0,0 +1,68 @@ +package com.monke.monkeybook.widget.flowlayout; + +import android.content.Context; +import android.view.View; +import android.widget.Checkable; +import android.widget.FrameLayout; + +public class TagView extends FrameLayout implements Checkable +{ + private boolean isChecked; + private static final int[] CHECK_STATE = new int[]{android.R.attr.state_checked}; + + public TagView(Context context) + { + super(context); + } + + public View getTagView() + { + return getChildAt(0); + } + + @Override + public int[] onCreateDrawableState(int extraSpace) + { + int[] states = super.onCreateDrawableState(extraSpace + 1); + if (isChecked()) + { + mergeDrawableStates(states, CHECK_STATE); + } + return states; + } + + + /** + * Change the checked state of the view + * + * @param checked The new checked state + */ + @Override + public void setChecked(boolean checked) + { + if (this.isChecked != checked) + { + this.isChecked = checked; + refreshDrawableState(); + } + } + + /** + * @return The current checked state of the view + */ + @Override + public boolean isChecked() + { + return isChecked; + } + + /** + * Change the checked state of the view to the inverse of its current state + */ + @Override + public void toggle() + { + setChecked(!isChecked); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryKindBookAdapter.java b/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryKindBookAdapter.java new file mode 100644 index 0000000000..5a4aed34a4 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryKindBookAdapter.java @@ -0,0 +1,80 @@ +package com.monke.monkeybook.widget.libraryview; + +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.ImageView; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.SearchBookBean; +import java.util.ArrayList; +import java.util.List; +import me.grantland.widget.AutofitTextView; + +public class LibraryKindBookAdapter extends RecyclerView.Adapter{ + private LibraryKindBookListView.OnItemListener itemListener; + + private List datas = new ArrayList<>(); + + public LibraryKindBookAdapter(){ + + } + + @Override + public Viewholder onCreateViewHolder(ViewGroup parent, int i) { + return new Viewholder(LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_library_kindbook, parent, false)); + } + + @Override + public void onBindViewHolder(final Viewholder holder, final int position) { + Glide.with(holder.ivCover.getContext()) + .load(datas.get(position).getCoverUrl()) + .diskCacheStrategy(DiskCacheStrategy.RESULT) + .fitCenter() + .dontAnimate() + .placeholder(R.drawable.img_cover_default) + .into(holder.ivCover); + holder.tvName.setText(datas.get(position).getName()); + holder.tvAuthor.setText(datas.get(position).getAuthor()); + holder.ibContent.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (itemListener != null) + itemListener.onClickBook(holder.ivCover,datas.get(position)); + } + }); + } + + @Override + public int getItemCount() { + return datas.size(); + } + + class Viewholder extends RecyclerView.ViewHolder { + ImageView ivCover; + AutofitTextView tvName; + AutofitTextView tvAuthor; + ImageButton ibContent; + public Viewholder(View itemView) { + super(itemView); + ivCover= (ImageView) itemView.findViewById(R.id.iv_cover); + tvName = (AutofitTextView) itemView.findViewById(R.id.tv_name); + tvAuthor = (AutofitTextView) itemView.findViewById(R.id.tv_author); + ibContent = (ImageButton) itemView.findViewById(R.id.ib_content); + } + } + + public void setItemListener(LibraryKindBookListView.OnItemListener itemListener) { + this.itemListener = itemListener; + } + + public void updateDataAll(List newDatas){ + datas.clear(); + if(newDatas!=null && newDatas.size()>0) + datas.addAll(newDatas); + notifyDataSetChanged(); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryKindBookListView.java b/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryKindBookListView.java new file mode 100644 index 0000000000..2f0a93e71e --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryKindBookListView.java @@ -0,0 +1,72 @@ +package com.monke.monkeybook.widget.libraryview; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; + +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.LibraryKindBookListBean; +import com.monke.monkeybook.bean.SearchBookBean; +import com.monke.monkeybook.utils.DensityUtil; + +import java.util.List; + +public class LibraryKindBookListView extends LinearLayout{ + public interface OnItemListener{ + public void onClickMore(String title,String url); + public void onClickBook(ImageView animView,SearchBookBean searchBookBean); + } + public LibraryKindBookListView(Context context) { + super(context); + init(); + } + + public LibraryKindBookListView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(); + } + + public LibraryKindBookListView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @SuppressLint("NewApi") + public LibraryKindBookListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + private void init(){ + setOrientation(VERTICAL); + setVisibility(GONE); + LayoutInflater.from(getContext()).inflate(R.layout.view_library_hotauthor, this, true); + } + + public void updateData(List datas, OnItemListener itemListener){ + removeAllViews(); + if(datas!=null && datas.size()>0){ + setVisibility(VISIBLE); + for(int i=0;i0){ + LinearLayout.LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT,DensityUtil.dp2px(getContext(),1f)); + layoutParams.setMargins(0,DensityUtil.dp2px(getContext(),5),0,0); + View view = new View(getContext()); + view.setBackgroundColor(getContext().getResources().getColor(R.color.bg_library)); + view.setLayoutParams(layoutParams); + addView(view); + } + LibraryKindBookView itemView = new LibraryKindBookView(getContext()); + itemView.updateData(datas.get(i),itemListener); + addView(itemView); + } + }else{ + setVisibility(GONE); + } + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryKindBookView.java b/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryKindBookView.java new file mode 100644 index 0000000000..31fa5b45f1 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryKindBookView.java @@ -0,0 +1,82 @@ +package com.monke.monkeybook.widget.libraryview; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.LibraryKindBookListBean; + +public class LibraryKindBookView extends LinearLayout{ + private TextView tvKindName; + private TextView tvMore; + private RecyclerView rvBookLIst; + private LibraryKindBookAdapter libraryKindBookAdapter; + public LibraryKindBookView(Context context) { + super(context); + init(); + } + + public LibraryKindBookView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(); + } + + public LibraryKindBookView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @SuppressLint("NewApi") + public LibraryKindBookView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + private void init() { + LayoutInflater.from(getContext()).inflate(R.layout.view_library_kindbook, this, true); + tvKindName = (TextView) findViewById(R.id.tv_kindname); + tvMore = (TextView) findViewById(R.id.tv_more); + rvBookLIst = (RecyclerView) findViewById(R.id.rv_booklist); + libraryKindBookAdapter = new LibraryKindBookAdapter(); + rvBookLIst.setAdapter(libraryKindBookAdapter); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext()); + linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + rvBookLIst.setLayoutManager(linearLayoutManager); + + setVisibility(GONE); + } + + + public void updateData(final LibraryKindBookListBean data, final LibraryKindBookListView.OnItemListener itemListener){ + updateData(data,itemListener,data.getKindUrl()==null?false:true); + } + public void updateData(final LibraryKindBookListBean data, final LibraryKindBookListView.OnItemListener itemListener,Boolean hasMore){ + if(data.getBooks()==null || data.getBooks().size()==0){ + setVisibility(GONE); + }else + setVisibility(VISIBLE); + tvKindName.setText(data.getKindName()); + if(hasMore){ + tvMore.setVisibility(VISIBLE); + tvMore.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if(itemListener!=null) + itemListener.onClickMore(data.getKindName(),data.getKindUrl()); + } + }); + }else{ + tvMore.setVisibility(GONE); + tvMore.setOnClickListener(null); + } + libraryKindBookAdapter.setItemListener(itemListener); + libraryKindBookAdapter.updateDataAll(data.getBooks()); + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryNewBooksAdapter.java b/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryNewBooksAdapter.java new file mode 100644 index 0000000000..343bb90091 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryNewBooksAdapter.java @@ -0,0 +1,46 @@ +package com.monke.monkeybook.widget.libraryview; + +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.LibraryNewBookBean; +import com.monke.monkeybook.widget.flowlayout.FlowLayout; +import com.monke.monkeybook.widget.flowlayout.TagAdapter; +import java.util.ArrayList; + +public class LibraryNewBooksAdapter extends TagAdapter { + private LibraryNewBooksView.OnClickAuthorListener clickNewBookListener; + + public LibraryNewBooksAdapter() { + super(new ArrayList()); + } + + @Override + public View getView(FlowLayout parent, int position, final LibraryNewBookBean libraryNewBookBean) { + TextView tv = (TextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_library_hotauthor_item, + parent, false); + tv.setText(libraryNewBookBean.getName()); + tv.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(null != clickNewBookListener){ + clickNewBookListener.clickNewBook(libraryNewBookBean); + } + } + }); + return tv; + } + + public LibraryNewBookBean getItemData(int position){ + return mTagDatas.get(position); + } + + public int getDataSize(){ + return mTagDatas.size(); + } + + public void setClickNewBookListener(LibraryNewBooksView.OnClickAuthorListener clickNewBookListener) { + this.clickNewBookListener = clickNewBookListener; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryNewBooksView.java b/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryNewBooksView.java new file mode 100644 index 0000000000..3b7cec38c1 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/libraryview/LibraryNewBooksView.java @@ -0,0 +1,61 @@ +package com.monke.monkeybook.widget.libraryview; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.LinearLayout; +import com.monke.monkeybook.R; +import com.monke.monkeybook.bean.LibraryNewBookBean; +import com.monke.monkeybook.widget.flowlayout.TagFlowLayout; +import java.util.List; + +public class LibraryNewBooksView extends LinearLayout { + private TagFlowLayout tflBooks; + private LibraryNewBooksAdapter libraryNewBooksAdapter; + + public interface OnClickAuthorListener { + public void clickNewBook(LibraryNewBookBean libraryNewBookBean); + } + + public LibraryNewBooksView(Context context) { + super(context); + init(); + } + + public LibraryNewBooksView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(); + } + + public LibraryNewBooksView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + @SuppressLint("NewApi") + public LibraryNewBooksView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + private void init() { + LayoutInflater.from(getContext()).inflate(R.layout.view_library_hotauthor, this, true); + setOrientation(VERTICAL); + setVisibility(GONE); + libraryNewBooksAdapter = new LibraryNewBooksAdapter(); + tflBooks = (TagFlowLayout) findViewById(R.id.tfl_author); + tflBooks.setAdapter(libraryNewBooksAdapter); + } + + public void updateData(List datas, OnClickAuthorListener clickAuthorListener) { + if (datas != null && datas.size() > 0) { + setVisibility(VISIBLE); + libraryNewBooksAdapter.setClickNewBookListener(clickAuthorListener); + libraryNewBooksAdapter.replaceAll(datas); + } else { + setVisibility(GONE); + } + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/modialog/MoProgressHUD.java b/app/src/main/java/com/monke/monkeybook/widget/modialog/MoProgressHUD.java new file mode 100644 index 0000000000..3861eaeb5e --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/modialog/MoProgressHUD.java @@ -0,0 +1,299 @@ +package com.monke.monkeybook.widget.modialog; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.media.MediaMetadataRetriever; +import android.os.Handler; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; +import android.view.inputmethod.InputMethodManager; +import android.widget.FrameLayout; + +import com.monke.monkeybook.R; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +/** + * Created by ZQH on 2016/7/24. + */ +public class MoProgressHUD { + private Boolean isFinishing = false; + + private Context context; + private ViewGroup decorView;//activity的根View + private ViewGroup rootView;// mSharedView 的 根View + private MoProgressView mSharedView; + + + private Animation inAnim; + private Animation outAnim; + + private Boolean canBack = false; + + public MoProgressHUD(Context context) { + this.context = context; + initViews(); + initCenter(); + initAnimation(); + } + + private void initAnimation() { + inAnim = getInAnimation(); + outAnim = getOutAnimation(); + } + private void initFromTopRight(){ + inAnim = AnimationUtils.loadAnimation(context,R.anim.moprogress_in_top_right); + outAnim = AnimationUtils.loadAnimation(context,R.anim.moprogress_out_top_right); + } + private void initFromBottomRight(){ + inAnim = AnimationUtils.loadAnimation(context,R.anim.moprogress_in_bottom_right); + outAnim = AnimationUtils.loadAnimation(context,R.anim.moprogress_out_bottom_right); + } + + private void initFromBottomAnimation() { + inAnim = AnimationUtils.loadAnimation(context, R.anim.moprogress_bottom_in); + outAnim = AnimationUtils.loadAnimation(context, R.anim.moprogress_bottom_out); + } + + private void initCenter() { + mSharedView.setGravity(Gravity.CENTER); + if(mSharedView != null){ + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mSharedView.getLayoutParams(); + if(layoutParams!=null){ + layoutParams.setMargins(0, 0, 0, 0); + mSharedView.setLayoutParams(layoutParams); + } + mSharedView.setPadding(0,0,0,0); + } + } + + private void initBottom() { + mSharedView.setGravity(Gravity.BOTTOM); + if(mSharedView != null){ + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mSharedView.getLayoutParams(); + if(layoutParams!=null){ + layoutParams.setMargins(0, 0, 0, 0); + mSharedView.setLayoutParams(layoutParams); + } + mSharedView.setPadding(0,0,0,0); + } + } + + private void initMarRightTop() { + mSharedView.setGravity(Gravity.RIGHT | Gravity.TOP); + if(mSharedView != null){ + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mSharedView.getLayoutParams(); + if(layoutParams!=null){ + layoutParams.setMargins(0, 0, 0, 0); + mSharedView.setLayoutParams(layoutParams); + } + mSharedView.setPadding(0, 0, 0, 0); + } + } + + private void initViews() { + decorView = (ViewGroup) ((Activity) context).getWindow().getDecorView().findViewById(android.R.id.content); + rootView = new FrameLayout(context); + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT + ); + rootView.setLayoutParams(layoutParams); + rootView.setClickable(true); + + mSharedView = new MoProgressView(context); + + } + + public Animation getInAnimation() { + return AnimationUtils.loadAnimation(context, R.anim.moprogress_in); + } + + public Animation getOutAnimation() { + return AnimationUtils.loadAnimation(context, R.anim.moprogress_out); + } + + public boolean isShowing() { + return rootView.getParent() != null; + } + + private void onAttached() { + decorView.addView(rootView); + if (mSharedView.getParent() != null) + ((ViewGroup) mSharedView.getParent()).removeView(mSharedView); + rootView.addView(mSharedView); + + isFinishing = false; + } + + public void dismiss() { + //消失动画 + if (mSharedView != null && rootView != null && mSharedView.getParent() != null) { + if (!isFinishing) { + new Handler().post(new Runnable() { + @Override + public void run() { + outAnim.setAnimationListener(outAnimListener); + mSharedView.getChildAt(0).startAnimation(outAnim); + } + }); + } + } + } + + public Boolean isShow() { + if (mSharedView != null && mSharedView.getParent() != null) return true; + return false; + } + + Animation.AnimationListener outAnimListener = new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + isFinishing = true; + } + + @Override + public void onAnimationEnd(Animation animation) { + dismissImmediately(); + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }; + + public void dismissImmediately() { + if (mSharedView != null && rootView != null && mSharedView.getParent() != null) { + new Handler().post(new Runnable() { + @Override + public void run() { + rootView.removeView(mSharedView); + decorView.removeView(rootView); + } + }); + } + isFinishing = false; + } + + //转圈的载入 + public void showLoading() { + showLoading(null); + } + + //同上 + public void showLoading(String msg) { + initCenter(); + initAnimation(); + canBack = false; + rootView.setBackgroundColor(Color.parseColor("#00000000")); + rootView.setOnClickListener(null); + if (!isShowing()) { + onAttached(); + } + mSharedView.showLoading(msg); + mSharedView.getChildAt(0).startAnimation(inAnim); + } + + //单个按钮的提示信息 + public void showInfo(String msg) { + initCenter(); + initAnimation(); + canBack = true; + rootView.setBackgroundColor(Color.parseColor("#00000000")); + rootView.setOnClickListener(null); + mSharedView.showInfo(msg, new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + if (!isShowing()) { + onAttached(); + } + mSharedView.getChildAt(0).startAnimation(inAnim); + } + + //单个按钮的提示信息 + public void showInfo(String msg, String btnText, View.OnClickListener listener) { + initCenter(); + initAnimation(); + canBack = true; + rootView.setBackgroundColor(Color.parseColor("#CC000000")); + rootView.setOnClickListener(null); + mSharedView.showInfo(msg, btnText, listener); + if (!isShowing()) { + onAttached(); + } + mSharedView.getChildAt(0).startAnimation(inAnim); + } + + //////////////////////两个不同等级的按钮////////////////////// + public void showTwoButton(String msg, String b_f, View.OnClickListener c_f, String b_s, View.OnClickListener c_s) { + initCenter(); + initAnimation(); + canBack = true; + rootView.setBackgroundColor(Color.parseColor("#CC000000")); + rootView.setOnClickListener(null); + mSharedView.showTwoButton(msg, b_f, c_f, b_s, c_s); + if (!isShowing()) { + onAttached(); + } + mSharedView.getChildAt(0).startAnimation(inAnim); + } + ////////////////////离线章节选择//////////////////////////// + public interface OnClickDownload{ + public void download(int start,int end); + } + public void showDownloadList(int startIndex, int endIndex,int all, OnClickDownload clickDownload){ + initCenter(); + initAnimation(); + canBack = true; + rootView.setBackgroundColor(Color.parseColor("#00000000")); + rootView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + mSharedView.showDownloadList(startIndex, endIndex, all, clickDownload, new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); + if (!isShowing()) { + onAttached(); + } + mSharedView.getChildAt(0).startAnimation(inAnim); + } + ////////////////////////////////////////////////////////// + + public Boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (isShowing() && canBack) { + dismiss(); + return true; + } + } + return false; + } + + public Boolean getCanBack() { + return canBack; + } + + public Boolean onPressBack() { + if (isShowing() && canBack) { + dismiss(); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/widget/modialog/MoProgressView.java b/app/src/main/java/com/monke/monkeybook/widget/modialog/MoProgressView.java new file mode 100644 index 0000000000..41206ec92e --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/modialog/MoProgressView.java @@ -0,0 +1,179 @@ +package com.monke.monkeybook.widget.modialog; + +import android.content.Context; +import android.content.Intent; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.monke.monkeybook.R; +import com.victor.loading.rotate.RotateLoading; + +/** + * Created by ZQH on 2016/7/24. + */ +public class MoProgressView extends LinearLayout { + private Context context; + + public MoProgressView(Context context) { + this(context, null); + } + + public MoProgressView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public MoProgressView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + this.context = context; + setOrientation(VERTICAL); + } + + //转圈的载入 + public void showLoading(String text) { + removeAllViews(); + LayoutInflater.from(getContext()).inflate(R.layout.moprogress_dialog_loading, this, true); + TextView msgTv = (TextView) findViewById(R.id.msg_tv); + if (text != null && text.length() > 0) { + msgTv.setText(text); + } + + RotateLoading rlLoading = (RotateLoading) findViewById(R.id.rl_loading); + rlLoading.start(); + } + + //单个按钮的信息提示框 + public void showInfo(String msg, final OnClickListener listener) { + removeAllViews(); + LayoutInflater.from(getContext()).inflate(R.layout.moprogress_dialog_infor, this, true); + TextView msgTv = (TextView) findViewById(R.id.msg_tv); + msgTv.setText(msg); + TextView tvClose = (TextView) findViewById(R.id.tv_close); + tvClose.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + listener.onClick(v); + } + }); + } + + //单个按钮的信息提示框 + public void showInfo(String msg, String btnText, final OnClickListener listener) { + removeAllViews(); + LayoutInflater.from(getContext()).inflate(R.layout.moprogress_dialog_infor, this, true); + TextView msgTv = (TextView) findViewById(R.id.msg_tv); + msgTv.setText(msg); + TextView tvClose = (TextView) findViewById(R.id.tv_close); + tvClose.setText(btnText); + tvClose.setOnClickListener(listener); + } + //////////////////////两个不同等级的按钮////////////////////// + public void showTwoButton(String msg, String b_f, OnClickListener c_f, String b_s, OnClickListener c_s) { + removeAllViews(); + LayoutInflater.from(getContext()).inflate(R.layout.moprogress_dialog_two, this, true); + TextView tvMsg = (TextView) findViewById(R.id.tv_msg); + TextView tvCancel = (TextView) findViewById(R.id.tv_cancel); + TextView tvDone = (TextView) findViewById(R.id.tv_done); + tvMsg.setText(msg); + tvCancel.setText(b_f); + tvCancel.setOnClickListener(c_f); + tvDone.setText(b_s); + tvDone.setOnClickListener(c_s); + } + + ////////////////////离线章节选择//////////////////////////// + public void showDownloadList(int startIndex, int endIndex, final int all, final MoProgressHUD.OnClickDownload clickDownload, OnClickListener cancel){ + removeAllViews(); + LayoutInflater.from(getContext()).inflate(R.layout.moprogress_dialog_downloadchoice, this, true); + final EditText edtStart = (EditText) findViewById(R.id.edt_start); + final EditText edtEnd = (EditText) findViewById(R.id.edt_end); + TextView tvCancel = (TextView) findViewById(R.id.tv_cancel); + tvCancel.setOnClickListener(cancel); + TextView tvDownload = (TextView) findViewById(R.id.tv_download); + edtStart.setText(String.valueOf(startIndex+1)); + edtEnd.setText(String.valueOf(endIndex+1)); + edtStart.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if(edtStart.getText().length()>0){ + try{ + int temp = Integer.parseInt(edtStart.getText().toString().trim()); + if(temp>all){ + edtStart.setText(String.valueOf(all)); + edtStart.setSelection(edtStart.getText().length()); + Toast.makeText(context,"超过总章节",Toast.LENGTH_SHORT).show(); + }else if(temp<=0){ + edtStart.setText(String.valueOf(1)); + edtStart.setSelection(edtStart.getText().length()); + } + }catch (Exception e){ + e.printStackTrace(); + } + } + } + }); + edtEnd.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if(edtEnd.getText().length()>0){ + try{ + int temp = Integer.parseInt(edtEnd.getText().toString().trim()); + if(temp>all){ + edtEnd.setText(String.valueOf(all)); + edtEnd.setSelection(edtEnd.getText().length()); + Toast.makeText(context,"超过总章节",Toast.LENGTH_SHORT).show(); + }else if(temp<=0){ + edtEnd.setText(String.valueOf(1)); + edtEnd.setSelection(edtEnd.getText().length()); + } + }catch (Exception e){ + e.printStackTrace(); + } + } + } + }); + tvDownload.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if(edtStart.getText().length()>0 && edtEnd.getText().length()>0){ + if(Integer.parseInt(edtStart.getText().toString())>Integer.parseInt(edtEnd.getText().toString())){ + Toast.makeText(context,"输入错误",Toast.LENGTH_SHORT).show(); + }else{ + if(clickDownload!=null){ + clickDownload.download(Integer.parseInt(edtStart.getText().toString())-1,Integer.parseInt(edtEnd.getText().toString())-1); + } + } + }else{ + Toast.makeText(context,"请输入要离线的章节",Toast.LENGTH_SHORT).show(); + } + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/widget/refreshview/BaseRefreshListener.java b/app/src/main/java/com/monke/monkeybook/widget/refreshview/BaseRefreshListener.java new file mode 100644 index 0000000000..844940759f --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/refreshview/BaseRefreshListener.java @@ -0,0 +1,6 @@ +package com.monke.monkeybook.widget.refreshview; + +public interface BaseRefreshListener { + + public void startRefresh(); +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/refreshview/OnLoadMoreListener.java b/app/src/main/java/com/monke/monkeybook/widget/refreshview/OnLoadMoreListener.java new file mode 100644 index 0000000000..cc3ce94095 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/refreshview/OnLoadMoreListener.java @@ -0,0 +1,8 @@ +package com.monke.monkeybook.widget.refreshview; + +public interface OnLoadMoreListener { + + public void startLoadmore(); + + public void loadMoreErrorTryAgain(); +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/refreshview/OnRefreshWithProgressListener.java b/app/src/main/java/com/monke/monkeybook/widget/refreshview/OnRefreshWithProgressListener.java new file mode 100644 index 0000000000..91f25883c0 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/refreshview/OnRefreshWithProgressListener.java @@ -0,0 +1,6 @@ +package com.monke.monkeybook.widget.refreshview; + +public interface OnRefreshWithProgressListener extends BaseRefreshListener{ + + public int getMaxProgress(); +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshProgressBar.java b/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshProgressBar.java new file mode 100644 index 0000000000..26e463123a --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshProgressBar.java @@ -0,0 +1,259 @@ +package com.monke.monkeybook.widget.refreshview; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.os.Handler; +import android.os.Looper; +import android.util.AttributeSet; +import android.view.View; + +import com.monke.monkeybook.R; + +public class RefreshProgressBar extends View { + private int maxProgress = 100; + private int durProgress = 0; + + private int secondMaxProgress = 100; + private int secondDurProgress = 0; + + private int bgColor = 0x00000000; + private int secondColor = 0xFFC1C1C1; + private int fontColor = 0xFF363636; + + private int speed = 1; + private int secondFinalProgress = 0; + + private Paint paint; + + private Handler handler; + + private Boolean isAutoLoading = false; + + public Boolean getIsAutoLoading() { + return isAutoLoading; + } + + public void setIsAutoLoading(Boolean loading) { + if(loading && getVisibility() != View.VISIBLE){ + setVisibility(View.VISIBLE); + } + isAutoLoading = loading; + if(!isAutoLoading){ + secondDurProgress = 0; + secondFinalProgress = 0; + } + maxProgress = 0; + + invalidate(); + } + + public RefreshProgressBar(Context context) { + this(context, null); + } + + public RefreshProgressBar(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RefreshProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + init(context, attrs, defStyleAttr); + } + + private void init(Context context, AttributeSet attrs, int defStyleAttr) { + handler = new Handler(Looper.getMainLooper()); + paint = new Paint(); + paint.setStyle(Paint.Style.FILL); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RefreshProgressBar); + speed = a.getDimensionPixelSize(R.styleable.RefreshProgressBar_speed, speed); + maxProgress = a.getInt(R.styleable.RefreshProgressBar_max_progress, maxProgress); + durProgress = a.getInt(R.styleable.RefreshProgressBar_dur_progress, durProgress); + secondDurProgress = a.getDimensionPixelSize(R.styleable.RefreshProgressBar_second_dur_progress, secondDurProgress); + secondFinalProgress = secondDurProgress; + secondMaxProgress = a.getDimensionPixelSize(R.styleable.RefreshProgressBar_second_max_progress, secondMaxProgress); + bgColor = a.getColor(R.styleable.RefreshProgressBar_bg_color, bgColor); + secondColor = a.getColor(R.styleable.RefreshProgressBar_second_color, secondColor); + fontColor = a.getColor(R.styleable.RefreshProgressBar_font_color, fontColor); + a.recycle(); + } + + int a = 1; + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + paint.setColor(bgColor); + Rect bgRect = new Rect(0, 0, getMeasuredWidth(), getMeasuredHeight()); + canvas.drawRect(bgRect, paint); + + if (secondDurProgress > 0 && secondMaxProgress>0) { + int secondDur = secondDurProgress; + if (secondDur < 0) { + secondDur = 0; + } + if (secondDur > secondMaxProgress) { + secondDur = secondMaxProgress; + } + paint.setColor(secondColor); + int tempW = (int) (getMeasuredWidth() * 1.0f * (secondDur * 1.0f / secondMaxProgress)); + Rect secondRect = new Rect(getMeasuredWidth() / 2 - tempW / 2, 0, getMeasuredWidth() / 2 + tempW / 2, getMeasuredHeight()); + canvas.drawRect(secondRect, paint); + } + + if (durProgress > 0 && maxProgress>0) { + paint.setColor(fontColor); + RectF fontRectF = new RectF(0, 0, getMeasuredWidth() * 1.0f * (durProgress * 1.0f / maxProgress), getMeasuredHeight()); + canvas.drawRect(fontRectF, paint); + } + + if (isAutoLoading) { + if (secondDurProgress >= secondMaxProgress) { + a = -1; + } else if (secondDurProgress <= 0) { + a = 1; + } + secondDurProgress += (a * speed); + if (secondDurProgress < 0) + secondDurProgress = 0; + else if (secondDurProgress > secondMaxProgress) + secondDurProgress = secondMaxProgress; + secondFinalProgress = secondDurProgress; + invalidate(); + }else{ + if (secondDurProgress != secondFinalProgress) { + if (secondDurProgress > secondFinalProgress) { + secondDurProgress -= speed; + if (secondDurProgress < secondFinalProgress) { + secondDurProgress = secondFinalProgress; + } + } else { + secondDurProgress += speed; + if (secondDurProgress > secondFinalProgress) { + secondDurProgress = secondFinalProgress; + } + } + this.invalidate(); + } + if(secondDurProgress==0 && durProgress==0 && secondFinalProgress==0 && getVisibility()==View.VISIBLE){ + setVisibility(View.INVISIBLE); + } + } + } + + public int getMaxProgress() { + return maxProgress; + } + + public void setMaxProgress(int maxProgress) { + this.maxProgress = maxProgress; + } + + public int getDurProgress() { + return durProgress; + } + + public void setDurProgress(int durProgress) { + if (durProgress < 0) { + durProgress = 0; + } + if (durProgress > maxProgress) { + durProgress = maxProgress; + } + this.durProgress = durProgress; + if (Looper.myLooper() == Looper.getMainLooper()) { + this.invalidate(); + } else { + this.postInvalidate(); + } + } + + public int getSecondMaxProgress() { + return secondMaxProgress; + } + + public void setSecondMaxProgress(int secondMaxProgress) { + this.secondMaxProgress = secondMaxProgress; + } + + public int getSecondDurProgress() { + return secondDurProgress; + } + + public void setSecondDurProgress(int secondDur) { + this.secondDurProgress = secondDur; + this.secondFinalProgress = secondDurProgress; + if (Looper.myLooper() == Looper.getMainLooper()) { + this.invalidate(); + } else { + this.postInvalidate(); + } + } + + public void setSecondDurProgressWithAnim(int secondDur) { + if (secondDur < 0) { + secondDur = 0; + } + if (secondDur > secondMaxProgress) { + secondDur = secondMaxProgress; + } + this.secondFinalProgress = secondDur; + if (Looper.myLooper() == Looper.getMainLooper()) { + this.invalidate(); + } else { + this.postInvalidate(); + } + } + + public void clean() { + durProgress = 0; + secondDurProgress = 0; + secondFinalProgress = 0; + if (Looper.myLooper() == Looper.getMainLooper()) { + this.invalidate(); + } else { + this.postInvalidate(); + } + } + + public void setBgColor(int bgColor) { + this.bgColor = bgColor; + } + + public void setSecondColor(int secondColor) { + this.secondColor = secondColor; + } + + public void setFontColor(int fontColor) { + this.fontColor = fontColor; + } + + public void setSpeed(int speed) { + this.speed = speed; + } + + public int getBgColor() { + return bgColor; + } + + public int getSecondColor() { + return secondColor; + } + + public int getFontColor() { + return fontColor; + } + + public int getSpeed() { + return speed; + } + + public int getSecondFinalProgress() { + return secondFinalProgress; + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshRecyclerView.java b/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshRecyclerView.java new file mode 100644 index 0000000000..f2a5b4b0cf --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshRecyclerView.java @@ -0,0 +1,276 @@ +package com.monke.monkeybook.widget.refreshview; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.widget.FrameLayout; + +import com.monke.monkeybook.R; + +public class RefreshRecyclerView extends FrameLayout { + private View view; + private RefreshProgressBar rpb; + private RecyclerView recyclerView; + + private View noDataView; + private View refreshErrorView; + + public RefreshRecyclerView(Context context) { + this(context, null); + } + + public RefreshRecyclerView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RefreshRecyclerView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + view = LayoutInflater.from(context).inflate(R.layout.view_refresh_recyclerview, this, false); + rpb = (RefreshProgressBar) view.findViewById(R.id.rpb); + recyclerView = (RecyclerView) view.findViewById(R.id.rv); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RefreshProgressBar); + rpb.setSpeed(a.getDimensionPixelSize(R.styleable.RefreshProgressBar_speed, rpb.getSpeed())); + rpb.setMaxProgress(a.getInt(R.styleable.RefreshProgressBar_max_progress, rpb.getMaxProgress())); + rpb.setSecondMaxProgress(a.getDimensionPixelSize(R.styleable.RefreshProgressBar_second_max_progress, rpb.getSecondMaxProgress())); + rpb.setBgColor(a.getColor(R.styleable.RefreshProgressBar_bg_color, rpb.getBgColor())); + rpb.setSecondColor(a.getColor(R.styleable.RefreshProgressBar_second_color, rpb.getSecondColor())); + rpb.setFontColor(a.getColor(R.styleable.RefreshProgressBar_font_color, rpb.getFontColor())); + a.recycle(); + + bindEvent(); + + addView(view); + } + + private float durTouchY = -1000000; + private BaseRefreshListener baseRefreshListener; + + public void setBaseRefreshListener(BaseRefreshListener baseRefreshListener) { + this.baseRefreshListener = baseRefreshListener; + } + + private OnLoadMoreListener loadMoreListener; + + public void setLoadMoreListener(OnLoadMoreListener loadMoreListener) { + this.loadMoreListener = loadMoreListener; + } + + private void bindEvent() { + recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + if (((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).canLoadMore() && ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).getItemCount() - 1 == ((LinearLayoutManager) recyclerView.getLayoutManager()).findLastVisibleItemPosition()) { + if(!((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).getLoadMoreError()){ + if (null != loadMoreListener) { + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsRequesting(2, false); + loadMoreListener.startLoadmore(); + } + } + } + } + }); + + recyclerView.setOnTouchListener(refreshTouchListener); + } + + public RefreshProgressBar getRpb() { + return rpb; + } + + public RecyclerView getRecyclerView() { + return recyclerView; + } + + public void refreshError() { + rpb.setIsAutoLoading(false); + rpb.clean(); + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsRequesting(0, true); + if (noDataView != null) { + noDataView.setVisibility(GONE); + } + if (refreshErrorView != null) { + refreshErrorView.setVisibility(VISIBLE); + } + } + + public void startRefresh() { + if (baseRefreshListener != null && baseRefreshListener instanceof OnRefreshWithProgressListener) { + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsAll(false, false); + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsRequesting(1, false); + rpb.setSecondDurProgress(rpb.getSecondMaxProgress()); + rpb.setMaxProgress(((OnRefreshWithProgressListener) baseRefreshListener).getMaxProgress()); + } else { + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsRequesting(1, true); + rpb.setIsAutoLoading(true); + if (noDataView != null) { + noDataView.setVisibility(GONE); + } + if (refreshErrorView != null) { + refreshErrorView.setVisibility(GONE); + } + } + } + + public void finishRefresh(Boolean needNoti) { + finishRefresh(((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).getItemcount() == 0, needNoti); + } + + public void finishRefresh(Boolean isAll, Boolean needNoti) { + rpb.setDurProgress(0); + if (isAll) { + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsRequesting(0, false); + rpb.setIsAutoLoading(false); + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsAll(isAll, needNoti); + } else { + rpb.setIsAutoLoading(false); + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsRequesting(0, needNoti); + } + + if (isAll) { + if (noDataView != null) { + if (((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).getItemcount() == 0) + noDataView.setVisibility(VISIBLE); + else + noDataView.setVisibility(GONE); + } + if (refreshErrorView != null) { + refreshErrorView.setVisibility(GONE); + } + } + } + + public void finishLoadMore(Boolean isAll, Boolean needNoti) { + if (isAll) { + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsRequesting(0, false); + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsAll(isAll, needNoti); + } else { + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsRequesting(0, needNoti); + } + + if (noDataView != null) { + noDataView.setVisibility(GONE); + } + if (refreshErrorView != null) { + refreshErrorView.setVisibility(GONE); + } + } + + public void setRefreshRecyclerViewAdapter(RefreshRecyclerViewAdapter refreshRecyclerViewAdapter, RecyclerView.LayoutManager layoutManager) { + refreshRecyclerViewAdapter.setClickTryAgainListener(new RefreshRecyclerViewAdapter.OnClickTryAgainListener() { + @Override + public void loadMoreErrorTryAgain() { + if (loadMoreListener != null) + loadMoreListener.loadMoreErrorTryAgain(); + } + }); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setAdapter(refreshRecyclerViewAdapter); + } + + public void loadMoreError() { + rpb.setIsAutoLoading(false); + rpb.clean(); + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setLoadMoreError(true, true); + } + + public void setNoDataAndrRefreshErrorView(View noData, View refreshError) { + if (noData != null) { + noDataView = noData; +// noDataView.setOnTouchListener(refreshTouchListener); + noDataView.setVisibility(GONE); + addView(noDataView, getChildCount() - 1); + + } + if (refreshError != null) { + refreshErrorView = refreshError; +// refreshErrorView.setOnTouchListener(refreshTouchListener); + addView(refreshErrorView, 2); + refreshErrorView.setVisibility(GONE); + } + } + + private OnTouchListener refreshTouchListener = new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + durTouchY = event.getY(); + break; + case MotionEvent.ACTION_MOVE: + if (durTouchY == -1000000) + durTouchY = event.getY(); + float dY = event.getY() - durTouchY; //>0下拉 + durTouchY = event.getY(); + if (baseRefreshListener != null && ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).getIsRequesting() == 0 && rpb.getSecondDurProgress() == rpb.getSecondFinalProgress()) { + if (rpb.getVisibility() != View.VISIBLE) { + rpb.setVisibility(View.VISIBLE); + } + if (recyclerView.getAdapter().getItemCount() > 0) { + if (0 == ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstCompletelyVisibleItemPosition()) { + rpb.setSecondDurProgress((int) (rpb.getSecondDurProgress() + dY)); + } + } else { + rpb.setSecondDurProgress((int) (rpb.getSecondDurProgress() + dY)); + } + if (rpb.getSecondDurProgress() <= 0) { + return false; + } else { + return true; + } + } + break; + case MotionEvent.ACTION_UP: + if (baseRefreshListener != null && rpb.getSecondMaxProgress() > 0 && rpb.getSecondDurProgress() > 0) { + if (rpb.getSecondDurProgress() >= rpb.getSecondMaxProgress() && ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).getIsRequesting() == 0) { + if (baseRefreshListener instanceof OnRefreshWithProgressListener) { + //带有进度的 + //执行刷新响应 + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsAll(false, false); + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsRequesting(1, true); + rpb.setMaxProgress(((OnRefreshWithProgressListener) baseRefreshListener).getMaxProgress()); + baseRefreshListener.startRefresh(); + if (noDataView != null) { + noDataView.setVisibility(GONE); + } + if (refreshErrorView != null) { + refreshErrorView.setVisibility(GONE); + } + } else { + //不带进度的 + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsAll(false, false); + ((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).setIsRequesting(1, true); + baseRefreshListener.startRefresh(); + if (noDataView != null) { + noDataView.setVisibility(GONE); + } + if (refreshErrorView != null) { + refreshErrorView.setVisibility(GONE); + } + rpb.setIsAutoLoading(true); + } + } else { + if (((RefreshRecyclerViewAdapter) recyclerView.getAdapter()).getIsRequesting() != 1) + rpb.setSecondDurProgressWithAnim(0); + } + } + durTouchY = -1000000; + break; + } + return false; + } + }; +} \ No newline at end of file diff --git a/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshRecyclerViewAdapter.java b/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshRecyclerViewAdapter.java new file mode 100644 index 0000000000..ef8861dc93 --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshRecyclerViewAdapter.java @@ -0,0 +1,177 @@ +package com.monke.monkeybook.widget.refreshview; + +import android.os.Handler; +import android.os.Looper; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.monke.monkeybook.R; + +public abstract class RefreshRecyclerViewAdapter extends RecyclerView.Adapter { + private final int LOADMORETYPE = 2001; + + private Handler handler; + private int isRequesting = 0; //0是未执行网络请求 1是正在下拉刷新 2是正在加载更多 + private Boolean needLoadMore = false; + private Boolean isAll = false; //判断是否还有更多 + private Boolean loadMoreError = false; + + private OnClickTryAgainListener clickTryAgainListener; + + public interface OnClickTryAgainListener { + public void loadMoreErrorTryAgain(); + } + + public RefreshRecyclerViewAdapter(Boolean needLoadMore) { + this.needLoadMore = needLoadMore; + handler = new Handler(); + } + + public int getIsRequesting() { + return isRequesting; + } + + public void setIsRequesting(int isRequesting, Boolean needNoti) { + this.isRequesting = isRequesting; + if (this.isRequesting == 1) { + isAll = false; + } + if (needNoti) { + if (Looper.myLooper() == Looper.getMainLooper()) { + notifyItemRangeChanged(getItemCount(), getItemCount() - getItemcount()); + } else { + handler.post(new Runnable() { + @Override + public void run() { + notifyDataSetChanged(); + } + }); + } + } + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (viewType == LOADMORETYPE) { + return new LoadMoreViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_refresh_loadmore, parent, false)); + } else + return onCreateViewholder(parent, viewType); + } + + public abstract RecyclerView.ViewHolder onCreateViewholder(ViewGroup parent, int viewType); + + @Override + public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { + if (holder.getItemViewType() == LOADMORETYPE) { + if (!loadMoreError) { + ((LoadMoreViewHolder) holder).tvLoadMore.setText("正在加载..."); + } else { + ((LoadMoreViewHolder) holder).tvLoadMore.setText("加载失败,点击重试"); + } + ((LoadMoreViewHolder) holder).tvLoadMore.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != clickTryAgainListener && loadMoreError) { + clickTryAgainListener.loadMoreErrorTryAgain(); + loadMoreError = false; + ((LoadMoreViewHolder) holder).tvLoadMore.setText("正在加载..."); + } + } + }); + } else + onBindViewholder(holder, position); + } + + public abstract void onBindViewholder(RecyclerView.ViewHolder holder, int position); + + @Override + public int getItemViewType(int position) { + if (needLoadMore && isRequesting != 1 && !isAll && position == getItemCount() - 1 && getItemcount() > 0) { + return LOADMORETYPE; + } else { + return getItemViewtype(position); + } + } + + public abstract int getItemViewtype(int position); + + @Override + public int getItemCount() { + if (needLoadMore && isRequesting != 1 && !isAll && getItemcount() > 0) { + return getItemcount() + 1; + } else + return getItemcount(); + } + + public abstract int getItemcount(); + + public void setIsAll(Boolean isAll, Boolean needNoti) { + this.isAll = isAll; + if (needNoti) { + if (Looper.myLooper() == Looper.getMainLooper()) { +// notifyItemRangeChanged(getItemCount(),getItemCount()-getItemcount()); + if (getItemCount() > getItemcount()) { + notifyItemRangeChanged(getItemCount(), getItemCount() - getItemcount()); + } else + notifyItemRemoved(getItemCount() + 1); + } else { + handler.post(new Runnable() { + @Override + public void run() { + notifyDataSetChanged(); + } + }); + } + } + } + + class LoadMoreViewHolder extends RecyclerView.ViewHolder { + FrameLayout llLoadMore; + TextView tvLoadMore; + + public LoadMoreViewHolder(View itemView) { + super(itemView); + llLoadMore = (FrameLayout) itemView.findViewById(R.id.ll_loadmore); + tvLoadMore = (TextView) itemView.findViewById(R.id.tv_loadmore); + } + } + + public Boolean canLoadMore() { + return needLoadMore && isRequesting == 0 && !isAll && getItemcount() > 0; + } + + public OnClickTryAgainListener getClickTryAgainListener() { + return clickTryAgainListener; + } + + public void setClickTryAgainListener(OnClickTryAgainListener clickTryAgainListener) { + this.clickTryAgainListener = clickTryAgainListener; + + } + + public Boolean getLoadMoreError() { + return loadMoreError; + } + + public void setLoadMoreError(Boolean loadMoreError, Boolean needNoti) { + this.isRequesting = 0; + this.loadMoreError = loadMoreError; + if (needNoti) { + if (Looper.myLooper() == Looper.getMainLooper()) { + notifyDataSetChanged(); + } else { + handler.post(new Runnable() { + @Override + public void run() { + notifyDataSetChanged(); + } + }); + } + } + } +} diff --git a/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshScrollView.java b/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshScrollView.java new file mode 100644 index 0000000000..49b800d35e --- /dev/null +++ b/app/src/main/java/com/monke/monkeybook/widget/refreshview/RefreshScrollView.java @@ -0,0 +1,101 @@ +package com.monke.monkeybook.widget.refreshview; + +import android.annotation.TargetApi; +import android.content.Context; +import android.os.Build; +import android.support.annotation.NonNull; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ScrollView; + +public class RefreshScrollView extends ScrollView{ + private RefreshProgressBar rpb; + private float durTouchY = -1000000; + private BaseRefreshListener baseRefreshListener; + private Boolean isRefreshing = false; + private OnTouchListener touchListener; + + public RefreshScrollView(Context context) { + this(context,null); + } + + public RefreshScrollView(Context context, AttributeSet attrs) { + this(context, attrs,0); + } + + public RefreshScrollView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public RefreshScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public void setRpb(@NonNull RefreshProgressBar rpb) { + this.rpb = rpb; + init(); + } + + private void init() { + touchListener = new OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + durTouchY = event.getY(); + break; + case MotionEvent.ACTION_MOVE: + if (durTouchY == -1000000) + durTouchY = event.getY(); + float dY = event.getY() - durTouchY; //>0下拉 + durTouchY = event.getY(); + if (baseRefreshListener != null && !isRefreshing && rpb.getSecondDurProgress() == rpb.getSecondFinalProgress() && getScrollY()<=0) { + if (rpb.getVisibility() != View.VISIBLE) { + rpb.setVisibility(View.VISIBLE); + } + rpb.setSecondDurProgress((int) (rpb.getSecondDurProgress() + dY)); + if (rpb.getSecondDurProgress() <= 0) { + return false; + } else { + return true; + } + } + break; + case MotionEvent.ACTION_UP: + if (baseRefreshListener != null && rpb.getSecondMaxProgress() > 0 && rpb.getSecondDurProgress() > 0) { + if (rpb.getSecondDurProgress() >= rpb.getSecondMaxProgress() && !isRefreshing) { + startRefresh(); + } else { + rpb.setSecondDurProgressWithAnim(0); + } + } + durTouchY = -1000000; + break; + } + return false; + } + }; + this.setOnTouchListener(touchListener); + } + + public void setBaseRefreshListener(BaseRefreshListener baseRefreshListener) { + this.baseRefreshListener = baseRefreshListener; + } + + public void startRefresh(){ + if(baseRefreshListener!=null){ + isRefreshing = true; + rpb.setIsAutoLoading(true); + baseRefreshListener.startRefresh(); + } + } + + public void finishRefresh(){ + isRefreshing = false; + rpb.setDurProgress(0); + rpb.setIsAutoLoading(false); + } +} diff --git a/app/src/main/res/anim/anim_act_importbook_in.xml b/app/src/main/res/anim/anim_act_importbook_in.xml new file mode 100644 index 0000000000..778ccd084d --- /dev/null +++ b/app/src/main/res/anim/anim_act_importbook_in.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_act_importbook_out.xml b/app/src/main/res/anim/anim_act_importbook_out.xml new file mode 100644 index 0000000000..971513920f --- /dev/null +++ b/app/src/main/res/anim/anim_act_importbook_out.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_bookshelf_item.xml b/app/src/main/res/anim/anim_bookshelf_item.xml new file mode 100644 index 0000000000..8a20cda449 --- /dev/null +++ b/app/src/main/res/anim/anim_bookshelf_item.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_pop_chapterlist_in.xml b/app/src/main/res/anim/anim_pop_chapterlist_in.xml new file mode 100644 index 0000000000..b0bcc5a05f --- /dev/null +++ b/app/src/main/res/anim/anim_pop_chapterlist_in.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_pop_chapterlist_out.xml b/app/src/main/res/anim/anim_pop_chapterlist_out.xml new file mode 100644 index 0000000000..6d294e780f --- /dev/null +++ b/app/src/main/res/anim/anim_pop_chapterlist_out.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_pop_checkaddshelf_in.xml b/app/src/main/res/anim/anim_pop_checkaddshelf_in.xml new file mode 100644 index 0000000000..9085b7e6d6 --- /dev/null +++ b/app/src/main/res/anim/anim_pop_checkaddshelf_in.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_pop_checkaddshelf_out.xml b/app/src/main/res/anim/anim_pop_checkaddshelf_out.xml new file mode 100644 index 0000000000..bd2d3a6f01 --- /dev/null +++ b/app/src/main/res/anim/anim_pop_checkaddshelf_out.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_pop_moresetting_in.xml b/app/src/main/res/anim/anim_pop_moresetting_in.xml new file mode 100644 index 0000000000..161eabc47a --- /dev/null +++ b/app/src/main/res/anim/anim_pop_moresetting_in.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_pop_moresetting_out.xml b/app/src/main/res/anim/anim_pop_moresetting_out.xml new file mode 100644 index 0000000000..10b6138562 --- /dev/null +++ b/app/src/main/res/anim/anim_pop_moresetting_out.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_pop_windowlight_in.xml b/app/src/main/res/anim/anim_pop_windowlight_in.xml new file mode 100644 index 0000000000..dffa737c47 --- /dev/null +++ b/app/src/main/res/anim/anim_pop_windowlight_in.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_pop_windowlight_out.xml b/app/src/main/res/anim/anim_pop_windowlight_out.xml new file mode 100644 index 0000000000..0e5ce0d84c --- /dev/null +++ b/app/src/main/res/anim/anim_pop_windowlight_out.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_pop_windowmenumore_in.xml b/app/src/main/res/anim/anim_pop_windowmenumore_in.xml new file mode 100644 index 0000000000..463c124481 --- /dev/null +++ b/app/src/main/res/anim/anim_pop_windowmenumore_in.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_pop_windowmenumore_out.xml b/app/src/main/res/anim/anim_pop_windowmenumore_out.xml new file mode 100644 index 0000000000..5b80de325b --- /dev/null +++ b/app/src/main/res/anim/anim_pop_windowmenumore_out.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_readbook_bottom_in.xml b/app/src/main/res/anim/anim_readbook_bottom_in.xml new file mode 100644 index 0000000000..48fe0c0aae --- /dev/null +++ b/app/src/main/res/anim/anim_readbook_bottom_in.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_readbook_bottom_out.xml b/app/src/main/res/anim/anim_readbook_bottom_out.xml new file mode 100644 index 0000000000..2e91beb957 --- /dev/null +++ b/app/src/main/res/anim/anim_readbook_bottom_out.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_readbook_top_in.xml b/app/src/main/res/anim/anim_readbook_top_in.xml new file mode 100644 index 0000000000..e36360bc0d --- /dev/null +++ b/app/src/main/res/anim/anim_readbook_top_in.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/anim_readbook_top_out.xml b/app/src/main/res/anim/anim_readbook_top_out.xml new file mode 100644 index 0000000000..0b8acbcebd --- /dev/null +++ b/app/src/main/res/anim/anim_readbook_top_out.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/moprogress_bottom_in.xml b/app/src/main/res/anim/moprogress_bottom_in.xml new file mode 100644 index 0000000000..ae7f63a7c3 --- /dev/null +++ b/app/src/main/res/anim/moprogress_bottom_in.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/moprogress_bottom_out.xml b/app/src/main/res/anim/moprogress_bottom_out.xml new file mode 100644 index 0000000000..fdb5058406 --- /dev/null +++ b/app/src/main/res/anim/moprogress_bottom_out.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/moprogress_in.xml b/app/src/main/res/anim/moprogress_in.xml new file mode 100644 index 0000000000..6a4c8020b4 --- /dev/null +++ b/app/src/main/res/anim/moprogress_in.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/moprogress_in_bottom_right.xml b/app/src/main/res/anim/moprogress_in_bottom_right.xml new file mode 100644 index 0000000000..ebbb68dd4f --- /dev/null +++ b/app/src/main/res/anim/moprogress_in_bottom_right.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/moprogress_in_top_right.xml b/app/src/main/res/anim/moprogress_in_top_right.xml new file mode 100644 index 0000000000..cb482348e2 --- /dev/null +++ b/app/src/main/res/anim/moprogress_in_top_right.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/moprogress_out.xml b/app/src/main/res/anim/moprogress_out.xml new file mode 100644 index 0000000000..4b30255984 --- /dev/null +++ b/app/src/main/res/anim/moprogress_out.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/moprogress_out_bottom_right.xml b/app/src/main/res/anim/moprogress_out_bottom_right.xml new file mode 100644 index 0000000000..b3570a50b3 --- /dev/null +++ b/app/src/main/res/anim/moprogress_out_bottom_right.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/moprogress_out_top_right.xml b/app/src/main/res/anim/moprogress_out_top_right.xml new file mode 100644 index 0000000000..bfb6ecf7f3 --- /dev/null +++ b/app/src/main/res/anim/moprogress_out_top_right.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/selector_kind_tv_color.xml b/app/src/main/res/color/selector_kind_tv_color.xml new file mode 100644 index 0000000000..b9f06fdf05 --- /dev/null +++ b/app/src/main/res/color/selector_kind_tv_color.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/bg_ib_pre.xml b/app/src/main/res/drawable-v21/bg_ib_pre.xml new file mode 100644 index 0000000000..eb16b456f7 --- /dev/null +++ b/app/src/main/res/drawable-v21/bg_ib_pre.xml @@ -0,0 +1,3 @@ + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/bg_ib_pre2.xml b/app/src/main/res/drawable-v21/bg_ib_pre2.xml new file mode 100644 index 0000000000..8aefd89439 --- /dev/null +++ b/app/src/main/res/drawable-v21/bg_ib_pre2.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/bg_ib_pre3.xml b/app/src/main/res/drawable-v21/bg_ib_pre3.xml new file mode 100644 index 0000000000..e824c04fc0 --- /dev/null +++ b/app/src/main/res/drawable-v21/bg_ib_pre3.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xxhdpi/bg_btn_watch_nor.png b/app/src/main/res/drawable-xxhdpi/bg_btn_watch_nor.png new file mode 100644 index 0000000000..86bd1f0f77 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_btn_watch_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_btn_watch_sel.png b/app/src/main/res/drawable-xxhdpi/bg_btn_watch_sel.png new file mode 100644 index 0000000000..7e896c8b0e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_btn_watch_sel.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_readbook_black.png b/app/src/main/res/drawable-xxhdpi/bg_readbook_black.png new file mode 100644 index 0000000000..67dbffc9fc Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_readbook_black.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_readbook_green.png b/app/src/main/res/drawable-xxhdpi/bg_readbook_green.png new file mode 100644 index 0000000000..e945543629 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_readbook_green.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_readbook_yellow.png b/app/src/main/res/drawable-xxhdpi/bg_readbook_yellow.png new file mode 100644 index 0000000000..98da496150 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_readbook_yellow.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_search.9.png b/app/src/main/res/drawable-xxhdpi/bg_search.9.png new file mode 100644 index 0000000000..00a193d3d2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_search.9.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_shadow.png b/app/src/main/res/drawable-xxhdpi/bg_shadow.png new file mode 100644 index 0000000000..cb8fee03db Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_shadow.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_shadow2.png b/app/src/main/res/drawable-xxhdpi/bg_shadow2.png new file mode 100644 index 0000000000..ac0124b670 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_shadow2.png differ diff --git a/app/src/main/res/drawable-xxhdpi/bg_welcome.png b/app/src/main/res/drawable-xxhdpi/bg_welcome.png new file mode 100644 index 0000000000..3464a85138 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_welcome.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_add_nor.png b/app/src/main/res/drawable-xxhdpi/icon_add_nor.png new file mode 100644 index 0000000000..cf5032a67d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_add_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_add_sel.png b/app/src/main/res/drawable-xxhdpi/icon_add_sel.png new file mode 100644 index 0000000000..af692f9e3e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_add_sel.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_catalog_nor.png b/app/src/main/res/drawable-xxhdpi/icon_catalog_nor.png new file mode 100644 index 0000000000..df8f7b838c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_catalog_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_catalog_pre.png b/app/src/main/res/drawable-xxhdpi/icon_catalog_pre.png new file mode 100644 index 0000000000..ad818997b8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_catalog_pre.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_close.png b/app/src/main/res/drawable-xxhdpi/icon_close.png new file mode 100644 index 0000000000..d04921b0da Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_close.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_cursor.png b/app/src/main/res/drawable-xxhdpi/icon_cursor.png new file mode 100644 index 0000000000..6e9ac2cb72 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_cursor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_download.png b/app/src/main/res/drawable-xxhdpi/icon_download.png new file mode 100644 index 0000000000..956490aa49 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_download.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_download_main_nor.png b/app/src/main/res/drawable-xxhdpi/icon_download_main_nor.png new file mode 100644 index 0000000000..a96f71ef02 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_download_main_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_download_main_pre.png b/app/src/main/res/drawable-xxhdpi/icon_download_main_pre.png new file mode 100644 index 0000000000..4491bf3543 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_download_main_pre.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_font_nor.png b/app/src/main/res/drawable-xxhdpi/icon_font_nor.png new file mode 100644 index 0000000000..2e1b7e5dea Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_font_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_font_pre.png b/app/src/main/res/drawable-xxhdpi/icon_font_pre.png new file mode 100644 index 0000000000..fe274989b8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_font_pre.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_library_nor.png b/app/src/main/res/drawable-xxhdpi/icon_library_nor.png new file mode 100644 index 0000000000..f61239c53d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_library_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_library_sel.png b/app/src/main/res/drawable-xxhdpi/icon_library_sel.png new file mode 100644 index 0000000000..3bddf31e51 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_library_sel.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_light_nor.png b/app/src/main/res/drawable-xxhdpi/icon_light_nor.png new file mode 100644 index 0000000000..f8f8a54bab Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_light_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_light_pre.png b/app/src/main/res/drawable-xxhdpi/icon_light_pre.png new file mode 100644 index 0000000000..0e90ef97e3 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_light_pre.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_money_nor.png b/app/src/main/res/drawable-xxhdpi/icon_money_nor.png new file mode 100644 index 0000000000..7e9828d437 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_money_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_money_sel.png b/app/src/main/res/drawable-xxhdpi/icon_money_sel.png new file mode 100644 index 0000000000..644952244c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_money_sel.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_monkovel_big_black.png b/app/src/main/res/drawable-xxhdpi/icon_monkovel_big_black.png new file mode 100644 index 0000000000..9d0f051d93 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_monkovel_big_black.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_monkovel_big_white.png b/app/src/main/res/drawable-xxhdpi/icon_monkovel_big_white.png new file mode 100644 index 0000000000..f684097295 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_monkovel_big_white.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_monkovel_black.png b/app/src/main/res/drawable-xxhdpi/icon_monkovel_black.png new file mode 100644 index 0000000000..fd83c0639d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_monkovel_black.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_monkovel_white.png b/app/src/main/res/drawable-xxhdpi/icon_monkovel_white.png new file mode 100644 index 0000000000..26959f21e3 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_monkovel_white.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_nor.png b/app/src/main/res/drawable-xxhdpi/icon_more_nor.png new file mode 100644 index 0000000000..74132f047f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_more_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_more_pre.png b/app/src/main/res/drawable-xxhdpi/icon_more_pre.png new file mode 100644 index 0000000000..05ade391f8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_more_pre.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_readbook_black.png b/app/src/main/res/drawable-xxhdpi/icon_readbook_black.png new file mode 100644 index 0000000000..a0abc8e742 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_readbook_black.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_readbook_green.png b/app/src/main/res/drawable-xxhdpi/icon_readbook_green.png new file mode 100644 index 0000000000..e123b04f5c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_readbook_green.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_readbook_white.png b/app/src/main/res/drawable-xxhdpi/icon_readbook_white.png new file mode 100644 index 0000000000..534dd31c91 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_readbook_white.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_readbook_yellow.png b/app/src/main/res/drawable-xxhdpi/icon_readbook_yellow.png new file mode 100644 index 0000000000..13c38fd5f6 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_readbook_yellow.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_return_nor.png b/app/src/main/res/drawable-xxhdpi/icon_return_nor.png new file mode 100644 index 0000000000..0734f4fd5d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_return_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_return_pre.png b/app/src/main/res/drawable-xxhdpi/icon_return_pre.png new file mode 100644 index 0000000000..c60cdc561a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_return_pre.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_search_nor.png b/app/src/main/res/drawable-xxhdpi/icon_search_nor.png new file mode 100644 index 0000000000..cb219b76ae Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_search_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_search_sel.png b/app/src/main/res/drawable-xxhdpi/icon_search_sel.png new file mode 100644 index 0000000000..c6861b736d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_search_sel.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_select.png b/app/src/main/res/drawable-xxhdpi/icon_select.png new file mode 100644 index 0000000000..aed88aed5b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_select.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_setting_nor.png b/app/src/main/res/drawable-xxhdpi/icon_setting_nor.png new file mode 100644 index 0000000000..d920458c2d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_setting_nor.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_setting_pre.png b/app/src/main/res/drawable-xxhdpi/icon_setting_pre.png new file mode 100644 index 0000000000..33c74bab6f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_setting_pre.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_slider.png b/app/src/main/res/drawable-xxhdpi/icon_slider.png new file mode 100644 index 0000000000..83b5e18a94 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_slider.png differ diff --git a/app/src/main/res/drawable-xxhdpi/icon_text.png b/app/src/main/res/drawable-xxhdpi/icon_text.png new file mode 100644 index 0000000000..93c796327f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_text.png differ diff --git a/app/src/main/res/drawable-xxhdpi/img_cover_default.9.png b/app/src/main/res/drawable-xxhdpi/img_cover_default.9.png new file mode 100644 index 0000000000..e1f9011823 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_cover_default.9.png differ diff --git a/app/src/main/res/drawable-xxhdpi/img_shelf_lastest.png b/app/src/main/res/drawable-xxhdpi/img_shelf_lastest.png new file mode 100644 index 0000000000..04eb8b25a0 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_shelf_lastest.png differ diff --git a/app/src/main/res/drawable-xxhdpi/img_shelf_lastest_tips.png b/app/src/main/res/drawable-xxhdpi/img_shelf_lastest_tips.png new file mode 100644 index 0000000000..80640c43de Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_shelf_lastest_tips.png differ diff --git a/app/src/main/res/drawable-xxhdpi/img_shelf_other.png b/app/src/main/res/drawable-xxhdpi/img_shelf_other.png new file mode 100644 index 0000000000..047b7abbaa Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/img_shelf_other.png differ diff --git a/app/src/main/res/drawable/bg_edit.xml b/app/src/main/res/drawable/bg_edit.xml new file mode 100644 index 0000000000..c3b7f04078 --- /dev/null +++ b/app/src/main/res/drawable/bg_edit.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_ib_pre.xml b/app/src/main/res/drawable/bg_ib_pre.xml new file mode 100644 index 0000000000..a370bb64b8 --- /dev/null +++ b/app/src/main/res/drawable/bg_ib_pre.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_ib_pre2.xml b/app/src/main/res/drawable/bg_ib_pre2.xml new file mode 100644 index 0000000000..d44a8b2f01 --- /dev/null +++ b/app/src/main/res/drawable/bg_ib_pre2.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_ib_pre3.xml b/app/src/main/res/drawable/bg_ib_pre3.xml new file mode 100644 index 0000000000..ef700a7d9a --- /dev/null +++ b/app/src/main/res/drawable/bg_ib_pre3.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_search_content.xml b/app/src/main/res/drawable/bg_search_content.xml new file mode 100644 index 0000000000..29ea287ba3 --- /dev/null +++ b/app/src/main/res/drawable/bg_search_content.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/moprogress_bg_white.xml b/app/src/main/res/drawable/moprogress_bg_white.xml new file mode 100644 index 0000000000..d1fc02078b --- /dev/null +++ b/app/src/main/res/drawable/moprogress_bg_white.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_bg_download.xml b/app/src/main/res/drawable/selector_bg_download.xml new file mode 100644 index 0000000000..de0df4196b --- /dev/null +++ b/app/src/main/res/drawable/selector_bg_download.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_bg_download_cancel.xml b/app/src/main/res/drawable/selector_bg_download_cancel.xml new file mode 100644 index 0000000000..e67909fa7a --- /dev/null +++ b/app/src/main/res/drawable/selector_bg_download_cancel.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_bg_watch.xml b/app/src/main/res/drawable/selector_bg_watch.xml new file mode 100644 index 0000000000..c93c4c9e1c --- /dev/null +++ b/app/src/main/res/drawable/selector_bg_watch.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_book_detail_read_bg.xml b/app/src/main/res/drawable/selector_book_detail_read_bg.xml new file mode 100644 index 0000000000..3c905af67a --- /dev/null +++ b/app/src/main/res/drawable/selector_book_detail_read_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_book_detail_shelf_bg.xml b/app/src/main/res/drawable/selector_book_detail_shelf_bg.xml new file mode 100644 index 0000000000..3c9bda89b9 --- /dev/null +++ b/app/src/main/res/drawable/selector_book_detail_shelf_bg.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_icon_catalog.xml b/app/src/main/res/drawable/selector_icon_catalog.xml new file mode 100644 index 0000000000..e156b6ab64 --- /dev/null +++ b/app/src/main/res/drawable/selector_icon_catalog.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_icon_donwload_main.xml b/app/src/main/res/drawable/selector_icon_donwload_main.xml new file mode 100644 index 0000000000..2d738e83fc --- /dev/null +++ b/app/src/main/res/drawable/selector_icon_donwload_main.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_icon_font.xml b/app/src/main/res/drawable/selector_icon_font.xml new file mode 100644 index 0000000000..da87cde8c8 --- /dev/null +++ b/app/src/main/res/drawable/selector_icon_font.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_icon_light.xml b/app/src/main/res/drawable/selector_icon_light.xml new file mode 100644 index 0000000000..fad91388ad --- /dev/null +++ b/app/src/main/res/drawable/selector_icon_light.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_icon_more.xml b/app/src/main/res/drawable/selector_icon_more.xml new file mode 100644 index 0000000000..d8b885d8bd --- /dev/null +++ b/app/src/main/res/drawable/selector_icon_more.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_icon_return.xml b/app/src/main/res/drawable/selector_icon_return.xml new file mode 100644 index 0000000000..d40f61c7ec --- /dev/null +++ b/app/src/main/res/drawable/selector_icon_return.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_icon_setting.xml b/app/src/main/res/drawable/selector_icon_setting.xml new file mode 100644 index 0000000000..f83dd60093 --- /dev/null +++ b/app/src/main/res/drawable/selector_icon_setting.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_importbook_btn_bg.xml b/app/src/main/res/drawable/selector_importbook_btn_bg.xml new file mode 100644 index 0000000000..672efce673 --- /dev/null +++ b/app/src/main/res/drawable/selector_importbook_btn_bg.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_iv_add.xml b/app/src/main/res/drawable/selector_iv_add.xml new file mode 100644 index 0000000000..3076d258ce --- /dev/null +++ b/app/src/main/res/drawable/selector_iv_add.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_iv_library.xml b/app/src/main/res/drawable/selector_iv_library.xml new file mode 100644 index 0000000000..70c2b43aad --- /dev/null +++ b/app/src/main/res/drawable/selector_iv_library.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_iv_money.xml b/app/src/main/res/drawable/selector_iv_money.xml new file mode 100644 index 0000000000..e40c6512fa --- /dev/null +++ b/app/src/main/res/drawable/selector_iv_money.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_iv_search.xml b/app/src/main/res/drawable/selector_iv_search.xml new file mode 100644 index 0000000000..2a5807834a --- /dev/null +++ b/app/src/main/res/drawable/selector_iv_search.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_pop_font_bg.xml b/app/src/main/res/drawable/selector_pop_font_bg.xml new file mode 100644 index 0000000000..35f40dcc9c --- /dev/null +++ b/app/src/main/res/drawable/selector_pop_font_bg.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_pop_font_color.xml b/app/src/main/res/drawable/selector_pop_font_color.xml new file mode 100644 index 0000000000..eab98a4511 --- /dev/null +++ b/app/src/main/res/drawable/selector_pop_font_color.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_switchbutton.xml b/app/src/main/res/drawable/selector_switchbutton.xml new file mode 100644 index 0000000000..3798dff206 --- /dev/null +++ b/app/src/main/res/drawable/selector_switchbutton.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_tv_addshelf.xml b/app/src/main/res/drawable/selector_tv_addshelf.xml new file mode 100644 index 0000000000..a9cf4560ec --- /dev/null +++ b/app/src/main/res/drawable/selector_tv_addshelf.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_tv_addshelf_text.xml b/app/src/main/res/drawable/selector_tv_addshelf_text.xml new file mode 100644 index 0000000000..66b52780ea --- /dev/null +++ b/app/src/main/res/drawable/selector_tv_addshelf_text.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_tv_black.xml b/app/src/main/res/drawable/selector_tv_black.xml new file mode 100644 index 0000000000..eab98a4511 --- /dev/null +++ b/app/src/main/res/drawable/selector_tv_black.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_tv_green.xml b/app/src/main/res/drawable/selector_tv_green.xml new file mode 100644 index 0000000000..c4076a97d8 --- /dev/null +++ b/app/src/main/res/drawable/selector_tv_green.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_tv_rank_kind.xml b/app/src/main/res/drawable/selector_tv_rank_kind.xml new file mode 100644 index 0000000000..0ea4bec9ee --- /dev/null +++ b/app/src/main/res/drawable/selector_tv_rank_kind.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/selector_tv_rank_kind_color.xml b/app/src/main/res/drawable/selector_tv_rank_kind_color.xml new file mode 100644 index 0000000000..46932370ad --- /dev/null +++ b/app/src/main/res/drawable/selector_tv_rank_kind_color.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_download_cancel_nor.xml b/app/src/main/res/drawable/shape_bg_download_cancel_nor.xml new file mode 100644 index 0000000000..80358afa19 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_download_cancel_nor.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_download_cancel_pre.xml b/app/src/main/res/drawable/shape_bg_download_cancel_pre.xml new file mode 100644 index 0000000000..1b13965db5 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_download_cancel_pre.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_download_nor.xml b/app/src/main/res/drawable/shape_bg_download_nor.xml new file mode 100644 index 0000000000..f4899d3a48 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_download_nor.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_download_pre.xml b/app/src/main/res/drawable/shape_bg_download_pre.xml new file mode 100644 index 0000000000..40b56073cd --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_download_pre.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_readbook_black.xml b/app/src/main/res/drawable/shape_bg_readbook_black.xml new file mode 100644 index 0000000000..cf29463566 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_readbook_black.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_readbook_green.xml b/app/src/main/res/drawable/shape_bg_readbook_green.xml new file mode 100644 index 0000000000..f836245d24 --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_readbook_green.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_readbook_white.xml b/app/src/main/res/drawable/shape_bg_readbook_white.xml new file mode 100644 index 0000000000..03188bb0da --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_readbook_white.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_bg_readbook_yellow.xml b/app/src/main/res/drawable/shape_bg_readbook_yellow.xml new file mode 100644 index 0000000000..1bc9854c6c --- /dev/null +++ b/app/src/main/res/drawable/shape_bg_readbook_yellow.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pop_checkaddshelf_bg.xml b/app/src/main/res/drawable/shape_pop_checkaddshelf_bg.xml new file mode 100644 index 0000000000..982ce7981c --- /dev/null +++ b/app/src/main/res/drawable/shape_pop_checkaddshelf_bg.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pop_font_bg_nor.xml b/app/src/main/res/drawable/shape_pop_font_bg_nor.xml new file mode 100644 index 0000000000..9d6194c546 --- /dev/null +++ b/app/src/main/res/drawable/shape_pop_font_bg_nor.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_pop_font_bg_pre.xml b/app/src/main/res/drawable/shape_pop_font_bg_pre.xml new file mode 100644 index 0000000000..1d38ec3b07 --- /dev/null +++ b/app/src/main/res/drawable/shape_pop_font_bg_pre.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_progress_cursor_read.xml b/app/src/main/res/drawable/shape_progress_cursor_read.xml new file mode 100644 index 0000000000..3a653c7ea2 --- /dev/null +++ b/app/src/main/res/drawable/shape_progress_cursor_read.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_search_history_roundrect.xml b/app/src/main/res/drawable/shape_search_history_roundrect.xml new file mode 100644 index 0000000000..8d1abe27bd --- /dev/null +++ b/app/src/main/res/drawable/shape_search_history_roundrect.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_search_history_roundrect_disable.xml b/app/src/main/res/drawable/shape_search_history_roundrect_disable.xml new file mode 100644 index 0000000000..fd12ce2574 --- /dev/null +++ b/app/src/main/res/drawable/shape_search_history_roundrect_disable.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_search_history_roundrect_press.xml b/app/src/main/res/drawable/shape_search_history_roundrect_press.xml new file mode 100644 index 0000000000..ba754634fa --- /dev/null +++ b/app/src/main/res/drawable/shape_search_history_roundrect_press.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_text_cursor.xml b/app/src/main/res/drawable/shape_text_cursor.xml new file mode 100644 index 0000000000..4534c51711 --- /dev/null +++ b/app/src/main/res/drawable/shape_text_cursor.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_bookchoice.xml b/app/src/main/res/layout/activity_bookchoice.xml new file mode 100644 index 0000000000..288bfb156f --- /dev/null +++ b/app/src/main/res/layout/activity_bookchoice.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_bookread.xml b/app/src/main/res/layout/activity_bookread.xml new file mode 100644 index 0000000000..035c6f2129 --- /dev/null +++ b/app/src/main/res/layout/activity_bookread.xml @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml new file mode 100644 index 0000000000..ea17f322f9 --- /dev/null +++ b/app/src/main/res/layout/activity_detail.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_importbook.xml b/app/src/main/res/layout/activity_importbook.xml new file mode 100644 index 0000000000..955d79b870 --- /dev/null +++ b/app/src/main/res/layout/activity_importbook.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_library.xml b/app/src/main/res/layout/activity_library.xml new file mode 100644 index 0000000000..26a86aa2a8 --- /dev/null +++ b/app/src/main/res/layout/activity_library.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000000..27b0caada6 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_search.xml b/app/src/main/res/layout/activity_search.xml new file mode 100644 index 0000000000..5304a2eb7a --- /dev/null +++ b/app/src/main/res/layout/activity_search.xml @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_welcome.xml b/app/src/main/res/layout/activity_welcome.xml new file mode 100644 index 0000000000..0db76654bb --- /dev/null +++ b/app/src/main/res/layout/activity_welcome.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_bookshelf_lastest.xml b/app/src/main/res/layout/adapter_bookshelf_lastest.xml new file mode 100644 index 0000000000..a4be80cae8 --- /dev/null +++ b/app/src/main/res/layout/adapter_bookshelf_lastest.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_bookshelf_other.xml b/app/src/main/res/layout/adapter_bookshelf_other.xml new file mode 100644 index 0000000000..9e0c5da8a3 --- /dev/null +++ b/app/src/main/res/layout/adapter_bookshelf_other.xml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_content_switch_item.xml b/app/src/main/res/layout/adapter_content_switch_item.xml new file mode 100644 index 0000000000..06fe0bc38b --- /dev/null +++ b/app/src/main/res/layout/adapter_content_switch_item.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_library_hotauthor_item.xml b/app/src/main/res/layout/adapter_library_hotauthor_item.xml new file mode 100644 index 0000000000..e597600467 --- /dev/null +++ b/app/src/main/res/layout/adapter_library_hotauthor_item.xml @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_library_kindbook.xml b/app/src/main/res/layout/adapter_library_kindbook.xml new file mode 100644 index 0000000000..97585f5c53 --- /dev/null +++ b/app/src/main/res/layout/adapter_library_kindbook.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_searchbook_item.xml b/app/src/main/res/layout/adapter_searchbook_item.xml new file mode 100644 index 0000000000..a43390af1c --- /dev/null +++ b/app/src/main/res/layout/adapter_searchbook_item.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_searchhistory_item.xml b/app/src/main/res/layout/adapter_searchhistory_item.xml new file mode 100644 index 0000000000..e597600467 --- /dev/null +++ b/app/src/main/res/layout/adapter_searchhistory_item.xml @@ -0,0 +1,13 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/moprogress_dialog_downloadchoice.xml b/app/src/main/res/layout/moprogress_dialog_downloadchoice.xml new file mode 100644 index 0000000000..cd7774b891 --- /dev/null +++ b/app/src/main/res/layout/moprogress_dialog_downloadchoice.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/moprogress_dialog_infor.xml b/app/src/main/res/layout/moprogress_dialog_infor.xml new file mode 100644 index 0000000000..f108b8fb91 --- /dev/null +++ b/app/src/main/res/layout/moprogress_dialog_infor.xml @@ -0,0 +1,50 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/moprogress_dialog_loading.xml b/app/src/main/res/layout/moprogress_dialog_loading.xml new file mode 100644 index 0000000000..f1dda950ab --- /dev/null +++ b/app/src/main/res/layout/moprogress_dialog_loading.xml @@ -0,0 +1,44 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/moprogress_dialog_two.xml b/app/src/main/res/layout/moprogress_dialog_two.xml new file mode 100644 index 0000000000..7347129e78 --- /dev/null +++ b/app/src/main/res/layout/moprogress_dialog_two.xml @@ -0,0 +1,54 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_adapter_chapterlist.xml b/app/src/main/res/layout/view_adapter_chapterlist.xml new file mode 100644 index 0000000000..d54e1475a1 --- /dev/null +++ b/app/src/main/res/layout/view_adapter_chapterlist.xml @@ -0,0 +1,30 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_adapter_importbook.xml b/app/src/main/res/layout/view_adapter_importbook.xml new file mode 100644 index 0000000000..71f2ddc841 --- /dev/null +++ b/app/src/main/res/layout/view_adapter_importbook.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_chapterlist.xml b/app/src/main/res/layout/view_chapterlist.xml new file mode 100644 index 0000000000..669f28c112 --- /dev/null +++ b/app/src/main/res/layout/view_chapterlist.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_kind.xml b/app/src/main/res/layout/view_kind.xml new file mode 100644 index 0000000000..efcceab2a4 --- /dev/null +++ b/app/src/main/res/layout/view_kind.xml @@ -0,0 +1,30 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_library_hotauthor.xml b/app/src/main/res/layout/view_library_hotauthor.xml new file mode 100644 index 0000000000..aa29afd8a9 --- /dev/null +++ b/app/src/main/res/layout/view_library_hotauthor.xml @@ -0,0 +1,24 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_library_kindbook.xml b/app/src/main/res/layout/view_library_kindbook.xml new file mode 100644 index 0000000000..fbc25a24e8 --- /dev/null +++ b/app/src/main/res/layout/view_library_kindbook.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_pop_checkaddshelf.xml b/app/src/main/res/layout/view_pop_checkaddshelf.xml new file mode 100644 index 0000000000..e07473552a --- /dev/null +++ b/app/src/main/res/layout/view_pop_checkaddshelf.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_pop_downloadlist.xml b/app/src/main/res/layout/view_pop_downloadlist.xml new file mode 100644 index 0000000000..c34aec068a --- /dev/null +++ b/app/src/main/res/layout/view_pop_downloadlist.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_pop_font.xml b/app/src/main/res/layout/view_pop_font.xml new file mode 100644 index 0000000000..1a0169d697 --- /dev/null +++ b/app/src/main/res/layout/view_pop_font.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_pop_menumore.xml b/app/src/main/res/layout/view_pop_menumore.xml new file mode 100644 index 0000000000..6240b764cd --- /dev/null +++ b/app/src/main/res/layout/view_pop_menumore.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/view_pop_moresetting.xml b/app/src/main/res/layout/view_pop_moresetting.xml new file mode 100644 index 0000000000..93a44bc3db --- /dev/null +++ b/app/src/main/res/layout/view_pop_moresetting.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_pop_windowlight.xml b/app/src/main/res/layout/view_pop_windowlight.xml new file mode 100644 index 0000000000..147067fafd --- /dev/null +++ b/app/src/main/res/layout/view_pop_windowlight.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_refresh_loadmore.xml b/app/src/main/res/layout/view_refresh_loadmore.xml new file mode 100644 index 0000000000..5af142f8c8 --- /dev/null +++ b/app/src/main/res/layout/view_refresh_loadmore.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_refresh_recyclerview.xml b/app/src/main/res/layout/view_refresh_recyclerview.xml new file mode 100644 index 0000000000..fda88e6ef2 --- /dev/null +++ b/app/src/main/res/layout/view_refresh_recyclerview.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_searchbook_nodata.xml b/app/src/main/res/layout/view_searchbook_nodata.xml new file mode 100644 index 0000000000..88c086bc74 --- /dev/null +++ b/app/src/main/res/layout/view_searchbook_nodata.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_searchbook_refresherror.xml b/app/src/main/res/layout/view_searchbook_refresherror.xml new file mode 100644 index 0000000000..562c64cd03 --- /dev/null +++ b/app/src/main/res/layout/view_searchbook_refresherror.xml @@ -0,0 +1,30 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000..06b7002679 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000..c59e47e26f Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000..d2dc8c1188 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000..5273ac93d7 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000..5273ac93d7 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/values/attr.xml b/app/src/main/res/values/attr.xml new file mode 100644 index 0000000000..e3c07ebc7b --- /dev/null +++ b/app/src/main/res/values/attr.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000000..98cc17649b --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,19 @@ + + + #3F51B5 + #303F9F + #FF4081 + + #c1c1c1 + #aaaaaa + + #737373 + #adadad + #343434 + #f1f1f1 + + #ffffff + #7891A5 + #7891A5 + #587A8A + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000000..47c8224673 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 16dp + 16dp + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000000..948c7137f7 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,18 @@ + + MONKOVEL + + 5954b3f999f0c76d1b001600 + + 9942412 + 5cZ5UKGW2tqEXK0dUiv4ngLEQ7I4Bf6s + + 没有网络 + 网络连接超时 + 数据解析失败 + + 观看至:%s + 《%s》 + 最新章节:%s + 是否将《%s》放入书架? + 共%s个Text文件 + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000000..5525b74a4a --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,40 @@ + + + + + + + + + + ' + + + + + + \ No newline at end of file diff --git a/app/src/test/java/com/monke/monkeybook/ExampleUnitTest.java b/app/src/test/java/com/monke/monkeybook/ExampleUnitTest.java new file mode 100644 index 0000000000..59cf255f1a --- /dev/null +++ b/app/src/test/java/com/monke/monkeybook/ExampleUnitTest.java @@ -0,0 +1,14 @@ +package com.monke.monkeybook; + +import org.junit.Test; +import static org.junit.Assert.*; + +/** + * To work on unit tests, switch the Test Artifact in the Build Variants view. + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/basemvplib/.gitignore b/basemvplib/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/basemvplib/.gitignore @@ -0,0 +1 @@ +/build diff --git a/basemvplib/build.gradle b/basemvplib/build.gradle new file mode 100644 index 0000000000..56b089664f --- /dev/null +++ b/basemvplib/build.gradle @@ -0,0 +1,46 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 25 + buildToolsVersion '25.0.0' + + defaultConfig { + minSdkVersion 14 + targetSdkVersion 25 + versionCode 2 + versionName "1.1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + testCompile 'junit:junit:4.12' + compile 'com.android.support:appcompat-v7:25.1.0' + + //RxAndroid + compile 'io.reactivex.rxjava2:rxandroid:2.0.1' + compile 'io.reactivex.rxjava2:rxjava:2.0.1' + + //Rxlifecycle + compile 'com.trello.rxlifecycle2:rxlifecycle:2.0.1' + compile 'com.trello.rxlifecycle2:rxlifecycle-android:2.0.1' // If you want to bind to Android-specific lifecycles + compile 'com.trello.rxlifecycle2:rxlifecycle-components:2.0.1' // If you want pre-written Activities and Fragments you can subclass as providers + compile 'com.trello.rxlifecycle2:rxlifecycle-navi:2.0.1' // If you want to use Navi for providers + compile 'com.trello.rxlifecycle2:rxlifecycle-kotlin:2.0.1' // If you want to use Kotlin syntax + + //Retrofit + compile 'com.squareup.retrofit2:retrofit:2.2.0' + compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0' + compile 'com.squareup.retrofit2:converter-scalars:2.2.0' + + //RxBus + compile ('com.hwangjr.rxbus:rxbus:2.0.0-beta') { + exclude group: 'com.jakewharton.timber', module: 'timber' + } +} \ No newline at end of file diff --git a/basemvplib/proguard-rules.pro b/basemvplib/proguard-rules.pro new file mode 100644 index 0000000000..8993fa46d1 --- /dev/null +++ b/basemvplib/proguard-rules.pro @@ -0,0 +1,35 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in D:\CodeTool\Android\Android_SDK/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} +-optimizationpasses 5 +-dontskipnonpubliclibraryclassmembers +-dontusemixedcaseclassnames +-classobfuscationdictionary obfuscationClassNames.txt +-dontskipnonpubliclibraryclasses + +##################OKGO######################## +#okgo +-dontwarn com.lzy.okgo.** +-keep class com.lzy.okgo.**{*;} + +#okrx +-dontwarn com.lzy.okrx.** +-keep class com.lzy.okrx.**{*;} + +#okserver +-dontwarn com.lzy.okserver.** +-keep class com.lzy.okserver.**{*;} \ No newline at end of file diff --git a/basemvplib/src/androidTest/java/com/monke/basemvplib/ApplicationTest.java b/basemvplib/src/androidTest/java/com/monke/basemvplib/ApplicationTest.java new file mode 100644 index 0000000000..19307d1ed6 --- /dev/null +++ b/basemvplib/src/androidTest/java/com/monke/basemvplib/ApplicationTest.java @@ -0,0 +1,13 @@ +package com.monke.basemvplib; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/basemvplib/src/main/AndroidManifest.xml b/basemvplib/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..4ae41b34b3 --- /dev/null +++ b/basemvplib/src/main/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/basemvplib/src/main/java/com/monke/basemvplib/AppActivityManager.java b/basemvplib/src/main/java/com/monke/basemvplib/AppActivityManager.java new file mode 100644 index 0000000000..87e1062192 --- /dev/null +++ b/basemvplib/src/main/java/com/monke/basemvplib/AppActivityManager.java @@ -0,0 +1,115 @@ +package com.monke.basemvplib; + +import android.app.Activity; + +import com.monke.basemvplib.impl.BaseActivity; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Activity管理器,管理项目中Activity的状态 + */ +public class AppActivityManager { + + private static List> activities; + + private AppActivityManager(){ + activities = new ArrayList<>(); + } + + private static volatile AppActivityManager instance; + + public static AppActivityManager getInstance(){ + if(null == instance){ + synchronized (AppActivityManager.class){ + if(null == instance){ + instance = new AppActivityManager(); + } + } + } + return instance; + } + + public List> getActivities() { + return activities; + } + + /* + 添加Activity + */ + public void add(Activity activity){ + activities.add(new WeakReference(activity)); + } + + /* + 移除Activity + */ + public void remove(Activity activity){ + for(WeakReference temp :activities){ + if(null != temp.get() && temp.get() == activity){ + activities.remove(temp); + break; + } + } + } + + /* + 移除Activity + */ + public void remove(Class activityClass){ + for(Iterator> iterator = activities.iterator();iterator.hasNext();){ + WeakReference item = iterator.next(); + if(null != item && null != item.get() && item.get().getClass() == activityClass){ + iterator.remove(); + } + } + } + + /* + 关闭指定 activity + */ + public void finishActivity(BaseActivity... activities){ + for(int i=0;i... activityClasses){ + ArrayList> waitfinish = new ArrayList<>(); + for(WeakReference temp :activities){ + for(int i=0;i activityWeakReference:waitfinish){ + if(null != activityWeakReference.get()){ + activityWeakReference.get().finish(); + } + } + } + + /* + 判断指定Activity是否存在 + */ + public Boolean isExist(Class activityClass){ + Boolean result = false; + for(Iterator> iterator = activities.iterator();iterator.hasNext();){ + WeakReference item = iterator.next(); + if(null != item && null != item.get() && item.get().getClass() == activityClass){ + result = true; + break; + } + } + return result; + } +} \ No newline at end of file diff --git a/basemvplib/src/main/java/com/monke/basemvplib/BaseApplication.java b/basemvplib/src/main/java/com/monke/basemvplib/BaseApplication.java new file mode 100644 index 0000000000..f030ad6b7b --- /dev/null +++ b/basemvplib/src/main/java/com/monke/basemvplib/BaseApplication.java @@ -0,0 +1,10 @@ +package com.monke.basemvplib; + +import android.app.Application; + +public class BaseApplication extends Application{ + @Override + public void onCreate() { + super.onCreate(); + } +} \ No newline at end of file diff --git a/basemvplib/src/main/java/com/monke/basemvplib/EncodoConverter.java b/basemvplib/src/main/java/com/monke/basemvplib/EncodoConverter.java new file mode 100644 index 0000000000..23cde75d7a --- /dev/null +++ b/basemvplib/src/main/java/com/monke/basemvplib/EncodoConverter.java @@ -0,0 +1,44 @@ +package com.monke.basemvplib; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.nio.charset.Charset; +import okhttp3.ResponseBody; +import okio.BufferedSource; +import okio.Okio; +import retrofit2.Converter; +import retrofit2.Retrofit; + +public class EncodoConverter extends Converter.Factory { + + private String encode = "utf-8"; + + private EncodoConverter(){ + + } + private EncodoConverter(String encode){ + this.encode = encode; + } + + public static EncodoConverter create(){ + return new EncodoConverter(); + } + + public static EncodoConverter create(String en){ + return new EncodoConverter(en); + } + + @Override + public Converter responseBodyConverter(Type type, Annotation[] annotations, + Retrofit retrofit) { + return new Converter() { + @Override + public String convert(ResponseBody value) throws IOException { + BufferedSource bufferedSource = Okio.buffer(value.source()); + String responseData = bufferedSource.readString(Charset.forName(encode)); + return responseData; + } + }; + } +} diff --git a/basemvplib/src/main/java/com/monke/basemvplib/IPresenter.java b/basemvplib/src/main/java/com/monke/basemvplib/IPresenter.java new file mode 100644 index 0000000000..80fe36e934 --- /dev/null +++ b/basemvplib/src/main/java/com/monke/basemvplib/IPresenter.java @@ -0,0 +1,15 @@ +package com.monke.basemvplib; + +import android.support.annotation.NonNull; + +public interface IPresenter { + /** + * 注入View,使之能够与View相互响应 + */ + void attachView(@NonNull IView iView); + + /** + * 释放资源,如果使用了网络请求 可以在此执行IModel.cancelRequest() + */ + void detachView(); +} diff --git a/basemvplib/src/main/java/com/monke/basemvplib/IView.java b/basemvplib/src/main/java/com/monke/basemvplib/IView.java new file mode 100644 index 0000000000..667797a152 --- /dev/null +++ b/basemvplib/src/main/java/com/monke/basemvplib/IView.java @@ -0,0 +1,7 @@ +package com.monke.basemvplib; + +import android.content.Context; + +public interface IView { + public Context getContext(); +} diff --git a/basemvplib/src/main/java/com/monke/basemvplib/impl/BaseActivity.java b/basemvplib/src/main/java/com/monke/basemvplib/impl/BaseActivity.java new file mode 100644 index 0000000000..8ed98d5bfc --- /dev/null +++ b/basemvplib/src/main/java/com/monke/basemvplib/impl/BaseActivity.java @@ -0,0 +1,140 @@ +package com.monke.basemvplib.impl; + +import android.app.ActivityOptions; +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.view.View; +import com.monke.basemvplib.AppActivityManager; +import com.monke.basemvplib.IPresenter; +import com.monke.basemvplib.IView; +import com.trello.rxlifecycle2.components.support.RxAppCompatActivity; + +public abstract class BaseActivity extends RxAppCompatActivity implements IView { + protected Bundle savedInstanceState; + protected T mPresenter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.savedInstanceState = savedInstanceState; + AppActivityManager.getInstance().add(this); + initSDK(); + onCreateActivity(); + mPresenter = initInjector(); + attachView(); + initData(); + bindView(); + bindEvent(); + firstRequest(); + } + + /** + * 首次逻辑操作 + */ + protected void firstRequest() { + + } + + /** + * 事件触发绑定 + */ + protected void bindEvent() { + + } + + /** + * 控件绑定 + */ + protected void bindView() { + + } + + /** + * P层绑定V层 + */ + private void attachView() { + if (null != mPresenter) { + mPresenter.attachView(this); + } + } + + /** + * P层解绑V层 + */ + private void detachView() { + if (null != mPresenter) { + mPresenter.detachView(); + } + } + + /** + * SDK初始化 + */ + protected void initSDK() { + + } + + /** + * P层绑定 若无则返回null; + * + * @return + */ + protected abstract T initInjector(); + + /** + * 布局载入 setContentView() + */ + protected abstract void onCreateActivity(); + + /** + * 数据初始化 + */ + protected abstract void initData(); + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + detachView(); + AppActivityManager.getInstance().remove(this); + } + + ////////////////////////////////启动Activity转场动画///////////////////////////////////////////// + + protected void startActivityForResultByAnim(Intent intent, int requestCode, int animIn, int animExit) { + startActivityForResult(intent, requestCode); + overridePendingTransition(animIn, animExit); + } + + protected void startActivityByAnim(Intent intent, int animIn, int animExit) { + startActivity(intent); + overridePendingTransition(animIn, animExit); + } + + protected void startActivityForResultByAnim(Intent intent, int requestCode, @NonNull View view, @NonNull String transitionName, int animIn, int animExit) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + startActivityForResult(intent, requestCode, ActivityOptions.makeSceneTransitionAnimation(this, view, transitionName).toBundle()); + } else { + startActivityForResultByAnim(intent, requestCode, animIn, animExit); + } + } + + protected void startActivityByAnim(Intent intent, @NonNull View view, @NonNull String transitionName, int animIn, int animExit) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, view, transitionName).toBundle()); + } else { + startActivityByAnim(intent, animIn, animExit); + } + } + + public Context getContext(){ + return this; + } +} \ No newline at end of file diff --git a/basemvplib/src/main/java/com/monke/basemvplib/impl/BaseFragment.java b/basemvplib/src/main/java/com/monke/basemvplib/impl/BaseFragment.java new file mode 100644 index 0000000000..d27f45a61d --- /dev/null +++ b/basemvplib/src/main/java/com/monke/basemvplib/impl/BaseFragment.java @@ -0,0 +1,67 @@ +package com.monke.basemvplib.impl; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import com.monke.basemvplib.IPresenter; +import com.monke.basemvplib.IView; +import com.trello.rxlifecycle2.components.RxFragment; + +public abstract class BaseFragment extends RxFragment implements IView{ + protected View view; + protected Bundle savedInstanceState; + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + this.savedInstanceState = savedInstanceState; + initSDK(); + view = createView(inflater, container); + initData(); + bindView(); + bindEvent(); + firstRequest(); + return view; + } + + /** + * 事件触发绑定 + */ + protected void bindEvent() { + + } + + /** + * 控件绑定 + */ + protected void bindView() { + + } + + /** + * 数据初始化 + */ + protected void initData() { + + } + + /** + * 首次逻辑操作 + */ + protected void firstRequest() { + + } + + /** + * 加载布局 + */ + protected abstract View createView(LayoutInflater inflater, ViewGroup container); + + /** + * 第三方SDK初始化 + */ + protected void initSDK() { + + } +} diff --git a/basemvplib/src/main/java/com/monke/basemvplib/impl/BaseModelImpl.java b/basemvplib/src/main/java/com/monke/basemvplib/impl/BaseModelImpl.java new file mode 100644 index 0000000000..dfcfb853ce --- /dev/null +++ b/basemvplib/src/main/java/com/monke/basemvplib/impl/BaseModelImpl.java @@ -0,0 +1,39 @@ +package com.monke.basemvplib.impl; + +import com.monke.basemvplib.EncodoConverter; + +import java.util.concurrent.TimeUnit; + +import okhttp3.OkHttpClient; +import retrofit2.Retrofit; +import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; +import retrofit2.converter.scalars.ScalarsConverterFactory; + +public class BaseModelImpl { + + protected OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .readTimeout(10, TimeUnit.SECONDS) + .addInterceptor(new RetryIntercepter(1)); + + protected Retrofit getRetrofitObject(String url) { + return new Retrofit.Builder().baseUrl(url) + //增加返回值为字符串的支持(以实体类返回) + .addConverterFactory(ScalarsConverterFactory.create()) + //增加返回值为Oservable的支持 + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .client(clientBuilder.build()) + .build(); + } + + protected Retrofit getRetrofitString(String url, String encode) { + return new Retrofit.Builder().baseUrl(url) + //增加返回值为字符串的支持(以实体类返回) + .addConverterFactory(EncodoConverter.create(encode)) + //增加返回值为Oservable的支持 + .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + .client(clientBuilder.build()) + .build(); + } +} \ No newline at end of file diff --git a/basemvplib/src/main/java/com/monke/basemvplib/impl/BasePresenterImpl.java b/basemvplib/src/main/java/com/monke/basemvplib/impl/BasePresenterImpl.java new file mode 100644 index 0000000000..b11479c49a --- /dev/null +++ b/basemvplib/src/main/java/com/monke/basemvplib/impl/BasePresenterImpl.java @@ -0,0 +1,14 @@ +package com.monke.basemvplib.impl; + +import android.support.annotation.NonNull; +import com.monke.basemvplib.IPresenter; +import com.monke.basemvplib.IView; + +public abstract class BasePresenterImpl implements IPresenter{ + protected T mView; + + @Override + public void attachView(@NonNull IView iView) { + mView = (T) iView; + } +} diff --git a/basemvplib/src/main/java/com/monke/basemvplib/impl/RetryIntercepter.java b/basemvplib/src/main/java/com/monke/basemvplib/impl/RetryIntercepter.java new file mode 100644 index 0000000000..0966e3db34 --- /dev/null +++ b/basemvplib/src/main/java/com/monke/basemvplib/impl/RetryIntercepter.java @@ -0,0 +1,27 @@ +package com.monke.basemvplib.impl; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +public class RetryIntercepter implements Interceptor { + public int maxRetry;//最大重试次数 + private int retryNum = 0;//假如设置为3次重试的话,则最大可能请求4次(默认1次+3次重试) + + public RetryIntercepter(int maxRetry) { + this.maxRetry = maxRetry; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + Response response = chain.proceed(request); + while (!response.isSuccessful() && retryNum < maxRetry) { + retryNum++; + response = chain.proceed(request); + } + return response; + } +} diff --git a/basemvplib/src/main/res/mipmap-hdpi/ic_launcher.png b/basemvplib/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000..cde69bccce Binary files /dev/null and b/basemvplib/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/basemvplib/src/main/res/mipmap-mdpi/ic_launcher.png b/basemvplib/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000..c133a0cbd3 Binary files /dev/null and b/basemvplib/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/basemvplib/src/main/res/mipmap-xhdpi/ic_launcher.png b/basemvplib/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000..bfa42f0e7b Binary files /dev/null and b/basemvplib/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/basemvplib/src/main/res/mipmap-xxhdpi/ic_launcher.png b/basemvplib/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000..324e72cdd7 Binary files /dev/null and b/basemvplib/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/basemvplib/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/basemvplib/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000..aee44e1384 Binary files /dev/null and b/basemvplib/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/basemvplib/src/main/res/values/colors.xml b/basemvplib/src/main/res/values/colors.xml new file mode 100644 index 0000000000..3ab3e9cbce --- /dev/null +++ b/basemvplib/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #3F51B5 + #303F9F + #FF4081 + diff --git a/basemvplib/src/main/res/values/strings.xml b/basemvplib/src/main/res/values/strings.xml new file mode 100644 index 0000000000..ab8ac00723 --- /dev/null +++ b/basemvplib/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + BaseMvpLib + diff --git a/basemvplib/src/main/res/values/styles.xml b/basemvplib/src/main/res/values/styles.xml new file mode 100644 index 0000000000..5885930df6 --- /dev/null +++ b/basemvplib/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/basemvplib/src/test/java/com/monke/basemvplib/ExampleUnitTest.java b/basemvplib/src/test/java/com/monke/basemvplib/ExampleUnitTest.java new file mode 100644 index 0000000000..8e8424df97 --- /dev/null +++ b/basemvplib/src/test/java/com/monke/basemvplib/ExampleUnitTest.java @@ -0,0 +1,15 @@ +package com.monke.basemvplib; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * To work on unit tests, switch the Test Artifact in the Build Variants view. + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..2cb82cc114 --- /dev/null +++ b/build.gradle @@ -0,0 +1,21 @@ + +buildscript { + repositories { + jcenter() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'org.greenrobot:greendao-gradle-plugin:3.0.0' + } +} + +allprojects { + repositories { + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000000..1fd9202b5d --- /dev/null +++ b/gradle.properties @@ -0,0 +1,20 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +APP_NAME = MONKOVEL \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000..13372aef5e Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..a047b7a90f --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri May 26 22:05:25 CST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000000..9d82f78915 --- /dev/null +++ b/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000000..8a0b282aa6 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/projectFilesBackup/.idea/workspace.xml b/projectFilesBackup/.idea/workspace.xml new file mode 100644 index 0000000000..f6d9b91015 --- /dev/null +++ b/projectFilesBackup/.idea/workspace.xml @@ -0,0 +1,3520 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1498441612398 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000000..c6610a591e --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':app', ':basemvplib'