This commit is contained in:
bobwang 2024-02-06 22:23:29 +08:00
parent 92b28c32c8
commit a156f2b21d
829 changed files with 2745499 additions and 811 deletions

View File

@ -1,123 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="corretto-1.8" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$/.." />
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="resolveExternalAnnotations" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:animated-vector-drawable:28.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/e1ffb8d0d4395c4b4bcd108def592fa3/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/e1ffb8d0d4395c4b4bcd108def592fa3/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,14 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:appcompat-v7:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/ca9169ec03d50fc2cb804a0225c8e738/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/ca9169ec03d50fc2cb804a0225c8e738/AndroidManifest.xml" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/ca9169ec03d50fc2cb804a0225c8e738/res" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/ca9169ec03d50fc2cb804a0225c8e738/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:asynclayoutinflater:28.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/69844d934bc11b713a721b0cde122d24/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/69844d934bc11b713a721b0cde122d24/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:cardview-v7:28.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/01bf5b774cbe9d3151e0d2837bfe2913/AndroidManifest.xml" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/01bf5b774cbe9d3151e0d2837bfe2913/res" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/01bf5b774cbe9d3151e0d2837bfe2913/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support.constraint:constraint-layout:1.1.3@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/ed932a14058041c8e18a5d0ec0d01a0c/res" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/ed932a14058041c8e18a5d0ec0d01a0c/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/ed932a14058041c8e18a5d0ec0d01a0c/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:customview:28.0.0@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/dd731db04b68a264583e70cb981070f6/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/dd731db04b68a264583e70cb981070f6/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,14 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:design:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/d1b888bd35e3c191b426bfce32307b01/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/d1b888bd35e3c191b426bfce32307b01/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/d1b888bd35e3c191b426bfce32307b01/res" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/d1b888bd35e3c191b426bfce32307b01/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:documentfile:28.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/0450778958607913673ffbafa510d017/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/0450778958607913673ffbafa510d017/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:drawerlayout:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/0da46aaf8530a2470293982bd0295773/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/0da46aaf8530a2470293982bd0295773/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/0da46aaf8530a2470293982bd0295773/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:interpolator:28.0.0@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/2847cdbc55666ff1750ac5e579b96e1f/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/2847cdbc55666ff1750ac5e579b96e1f/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:loader:28.0.0@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/545f4b3a0d7a5b4245105d8c042dfa25/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/545f4b3a0d7a5b4245105d8c042dfa25/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:localbroadcastmanager:28.0.0@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/39bd49a9c0e3e1c21a406a5bb7618d0b/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/39bd49a9c0e3e1c21a406a5bb7618d0b/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:print:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/4168492e47436054090cde3cc7a53000/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/4168492e47436054090cde3cc7a53000/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/4168492e47436054090cde3cc7a53000/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,14 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:recyclerview-v7:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/70d1ec048487bdbb4cdf7f01349e1c44/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/70d1ec048487bdbb4cdf7f01349e1c44/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/70d1ec048487bdbb4cdf7f01349e1c44/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/70d1ec048487bdbb4cdf7f01349e1c44/res" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:slidingpanelayout:28.0.0@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/362cff32302e8b37126799617779e1de/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/362cff32302e8b37126799617779e1de/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,14 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:support-compat:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/978f84024bcee9fe3f4487321f9a884d/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/978f84024bcee9fe3f4487321f9a884d/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/978f84024bcee9fe3f4487321f9a884d/AndroidManifest.xml" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/978f84024bcee9fe3f4487321f9a884d/res" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:support-fragment:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/34003dc1b37a8ca740c882aaa8fee6eb/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/34003dc1b37a8ca740c882aaa8fee6eb/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/34003dc1b37a8ca740c882aaa8fee6eb/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,14 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:support-media-compat:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/38ee00efd05c70d3d9487a9a80998155/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/38ee00efd05c70d3d9487a9a80998155/res" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/38ee00efd05c70d3d9487a9a80998155/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/38ee00efd05c70d3d9487a9a80998155/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:support-v4:28.0.0@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/bd7eefeaf847647bdde20b42c4094d06/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/bd7eefeaf847647bdde20b42c4094d06/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:support-vector-drawable:28.0.0@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/882ea5dd2e761b665964ac987e2ef759/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/882ea5dd2e761b665964ac987e2ef759/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:swiperefreshlayout:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/a66805a153f6490257dc169c3e60cbef/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/a66805a153f6490257dc169c3e60cbef/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/a66805a153f6490257dc169c3e60cbef/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,14 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:transition:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/2866f73c40bec794af35fd22b4a56fc7/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/2866f73c40bec794af35fd22b4a56fc7/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/2866f73c40bec794af35fd22b4a56fc7/AndroidManifest.xml" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/2866f73c40bec794af35fd22b4a56fc7/res" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:versionedparcelable:28.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/ae1e8fdd6c97eb0ac7f3f64e4958e241/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/ae1e8fdd6c97eb0ac7f3f64e4958e241/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:viewpager:28.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/e30e10dad870a3b54b076848c43c6ac2/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/e30e10dad870a3b54b076848c43c6ac2/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.github.bumptech.glide:glide:4.9.0@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/64477f162cdedacbba113fea60791695/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/64477f162cdedacbba113fea60791695/res" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/64477f162cdedacbba113fea60791695/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.bumptech.glide/glide/4.9.0/5f95e3cc34b116a8024f2af42f66e257d2e28ccb/glide-4.9.0-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.github.chengzipi:Searchbox:v1.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/5f4184f1af6a3ac5fd3926196f513fbd/res" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/5f4184f1af6a3ac5fd3926196f513fbd/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/5f4184f1af6a3ac5fd3926196f513fbd/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.github.ixiaow:multilayout:1.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/6bc8e6cd9ab8f815a7e5a70cf76384a4/AndroidManifest.xml" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/6bc8e6cd9ab8f815a7e5a70cf76384a4/res" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/6bc8e6cd9ab8f815a7e5a70cf76384a4/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.google.android.gms:play-services-audience:16.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/df552696f0ef320f1cd4cda6885dfeda/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/df552696f0ef320f1cd4cda6885dfeda/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.google.android.gms:play-services-base:16.0.1@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/a149ed3a7048aca8eabd1fa8dc516106/res" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/a149ed3a7048aca8eabd1fa8dc516106/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/a149ed3a7048aca8eabd1fa8dc516106/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.google.android.gms:play-services-basement:16.0.1@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/96f85fd6dc9e2f7e45b1c96585605fcd/res" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/96f85fd6dc9e2f7e45b1c96585605fcd/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/96f85fd6dc9e2f7e45b1c96585605fcd/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.google.android.gms:play-services-plus:16.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/8f6b6f0bc79b89956bb7f87a0e7173ec/AndroidManifest.xml" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/8f6b6f0bc79b89956bb7f87a0e7173ec/res" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/8f6b6f0bc79b89956bb7f87a0e7173ec/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.google.android.gms:play-services-tasks:16.0.1@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/39889ff485b55c89e32b58edcbdbabcd/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/39889ff485b55c89e32b58edcbdbabcd/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,11 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.packetzoom:pz-android-sdk:3.2.43@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/1a6a05f0f7dc1e39d409ba61835a841d/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/1a6a05f0f7dc1e39d409ba61835a841d/res" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/1a6a05f0f7dc1e39d409ba61835a841d/AndroidManifest.xml" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.packetzoom:pz-okhttp3-interceptor:3.2.43@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/19e7db6b92928b468e43a5de6e3472e8/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/19e7db6b92928b468e43a5de6e3472e8/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Gradle: com.youth.banner:banner:1.4.10@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/f6f9fc9c78282bd6fadccc7aaf7ea97d/AndroidManifest.xml" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/f6f9fc9c78282bd6fadccc7aaf7ea97d/res" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/f6f9fc9c78282bd6fadccc7aaf7ea97d/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.youth.banner/banner/1.4.10/eae835ac9b7ca690031f2b42fbcc88edab66ce5f/banner-1.4.10-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Gradle: org.litepal.android:core:3.0.0@aar">
<CLASSES>
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/c21c9e13468b30a7844894a813ca9cbe/jars/classes.jar!/" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/c21c9e13468b30a7844894a813ca9cbe/AndroidManifest.xml" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/c21c9e13468b30a7844894a813ca9cbe/res" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.litepal.android/core/3.0.0/aee6bfbad95aadfd0903570b5d110eb3d02921ca/core-3.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Gradle: org.litepal.android:java:3.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/7595c7051d66e41669b1f8e3afd8b0ed/AndroidManifest.xml" />
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/7595c7051d66e41669b1f8e3afd8b0ed/res" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/7595c7051d66e41669b1f8e3afd8b0ed/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.litepal.android/java/3.0.0/494ed8ebec335809cec8e1b782b6cd0267ee59c2/java-3.0.0-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -1,209 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidLayouts">
<shared>
<config />
</shared>
</component>
<component name="AndroidLogFilters">
<option name="TOOL_WINDOW_CONFIGURED_FILTER" value="Show only selected application" />
</component>
<component name="AutoImportSettings">
<option name="autoReloadType" value="NONE" />
</component>
<component name="ChangeListManager">
<list default="true" id="780636d5-0553-4880-a34f-94d61513aba0" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ClangdSettings">
<option name="formatViaClangd" value="false" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="device_and_snapshot_combo_box_target[]" />
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="ExternalProjectsManager">
<system id="GRADLE">
<state>
<task path="$PROJECT_DIR$">
<activation />
</task>
<projects_view>
<tree_state>
<expand>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="asProjects" type="f1a62948:ProjectNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="asProjects" type="f1a62948:ProjectNode" />
<item name="zhuike" type="2d1252cf:ModuleNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="asProjects" type="f1a62948:ProjectNode" />
<item name="zhuike" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="asProjects" type="f1a62948:ProjectNode" />
<item name="zhuike" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
<item name="other" type="c8890929:TasksNode$1" />
</path>
</expand>
<select />
</tree_state>
</projects_view>
</state>
</system>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/src/main/AndroidManifest.xml" />
<option value="$PROJECT_DIR$/build.gradle" />
</list>
</option>
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="1503" />
<option name="y" value="152" />
<option name="width" value="1633" />
<option name="height" value="931" />
</component>
<component name="ProjectId" id="2bkn6s21Ax50N6JyWSbdFQKZCsy" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane" />
<pane id="AndroidView">
<subPane>
<expand>
<path>
<item name="asProjects" type="1abcf292:AndroidViewProjectNode" />
<item name="zhuike" type="feadf853:AndroidModuleNode" />
</path>
<path>
<item name="asProjects" type="1abcf292:AndroidViewProjectNode" />
<item name="Gradle Scripts" type="ae0cef3a:AndroidBuildScriptsGroupNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="PackagesPane" />
<pane id="Scope" />
</panes>
</component>
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.cidr.known.project.marker": "true",
"android.gradle.sync.needed": "true",
"cf.first.check.clang-format": "false",
"cidr.known.project.marker": "true",
"last_opened_file_path": "D:/androidx/asProjects/zhuike",
"project.structure.last.edited": "Project",
"project.structure.proportion": "0.17",
"project.structure.side.proportion": "0.2",
"settings.editor.selected.configurable": "reference.settingsdialog.project.gradle"
}
}]]></component>
<component name="PsdUISettings">
<option name="MODULE_TAB" value="Properties" />
<option name="BUILD_VARIANTS_TAB" value="Build Types" />
<option name="LAST_EDITED_SIGNING_CONFIG" value="debug" />
<option name="LAST_EDITED_BUILD_TYPE" value="release" />
</component>
<component name="RunManager">
<configuration default="true" type="AndroidJUnit" factoryName="Android JUnit">
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="SvnConfiguration" cleanupOnStartRun="true">
<configuration>C:\Users\bobwang\AppData\Roaming\Subversion</configuration>
<supportedVersion>125</supportedVersion>
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="780636d5-0553-4880-a34f-94d61513aba0" name="Default Changelist" comment="" />
<created>1560561612729</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1560561612729</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="1358" y="-8" width="1936" height="1096" extended-state="6" />
<editor active="true" />
<layout>
<window_info active="true" content_ui="combo" id="Project" visible="true" weight="0.27665246" />
<window_info id="Structure" side_tool="true" />
<window_info id="Build Variants" side_tool="true" />
<window_info id="Image Layers" />
<window_info id="Designer" />
<window_info id="Capture Tool" />
<window_info id="Favorites" side_tool="true" />
<window_info id="Captures" order="0" side_tool="true" weight="0.25" />
<window_info anchor="bottom" id="Run" weight="0.32952183" />
<window_info anchor="bottom" id="Logcat" weight="0.32952183" />
<window_info anchor="bottom" id="Version Control" show_stripe_button="false" />
<window_info anchor="bottom" id="TODO" />
<window_info anchor="bottom" id="Android Profiler" />
<window_info anchor="bottom" id="Debug" />
<window_info anchor="bottom" id="Terminal" />
<window_info anchor="bottom" id="Event Log" side_tool="true" />
<window_info anchor="bottom" id="Build" visible="true" weight="0.27338877" />
<window_info anchor="right" id="Device File Explorer" side_tool="true" />
<window_info anchor="right" id="Capture Analysis" />
<window_info anchor="right" id="Gradle" />
<window_info anchor="right" id="Theme Preview" />
<window_info anchor="right" id="Palette&#9;" />
</layout>
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/../build.gradle">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/src/main/AndroidManifest.xml">
<provider editor-type-id="android-manifest" />
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="331">
<caret line="194" column="11" selection-start-line="194" selection-start-column="11" selection-end-line="194" selection-end-column="11" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/build.gradle">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="304">
<caret line="16" column="44" selection-start-line="16" selection-start-column="44" selection-end-line="16" selection-end-column="44" />
</state>
</provider>
</entry>
</component>
</project>

1
zhuike/.svn/entries Normal file
View File

@ -0,0 +1 @@
12

1
zhuike/.svn/format Normal file
View File

@ -0,0 +1 @@
12

View File

@ -0,0 +1,264 @@
package com.novelbook.android.dialog;
import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import com.novelbook.android.utils.Config;
import com.novelbook.android.R;
import com.novelbook.android.view.BookPageWidget;
import java.text.DecimalFormat;
public class ReadSettingDialog implements BaseDialog,View.OnClickListener {
ImageButton btn_return;
ImageButton btn_ight;
ImageButton btn_listener_book;
TextView tv_pre;
SeekBar sb_progress;
TextView tv_next;
TextView tv_directory;
TextView tv_dayornight;
TextView tv_setting;
TextView tv_Progress;
RelativeLayout rl_Progress;
private PopupWindow mPopupWindow,mPopupWindowTop;
private BookPageWidget mBookPageWidget;
private View view,viewTop;
private SettingListener mSettingListener;
private Context mContext;
private Config config;
private Boolean mDayOrNight;
public ReadSettingDialog(BookPageWidget bookPageWidget) {
this.mBookPageWidget = bookPageWidget;
mContext = bookPageWidget.getContext();
LayoutInflater layoutInflater = (LayoutInflater) bookPageWidget.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.zdialog_read_setting, null);
viewTop = layoutInflater.inflate(R.layout.zdialog_read_setting_top, null);
btn_return = (ImageButton) viewTop.findViewById(R.id.btn_return);
btn_ight = (ImageButton) viewTop.findViewById(R.id.btn_light);
btn_listener_book = (ImageButton) viewTop.findViewById(R.id.btn_listener_book);
tv_pre = (TextView) view.findViewById(R.id.tv_pre);
sb_progress = (SeekBar) view.findViewById(R.id.sb_progress);
tv_next = (TextView) view.findViewById(R.id.tv_next);
tv_directory = (TextView) view.findViewById(R.id.tv_directory);
tv_dayornight = (TextView) view.findViewById(R.id.tv_dayornight);
tv_setting = (TextView) view.findViewById(R.id.tv_setting);
tv_Progress = (TextView) view.findViewById(R.id.tv_progress);
rl_Progress = (RelativeLayout) view.findViewById(R.id.rl_progress);
btn_return.setOnClickListener(this);
btn_ight.setOnClickListener(this);
btn_listener_book.setOnClickListener(this);
tv_pre.setOnClickListener(this);
sb_progress.setOnClickListener(this);
tv_next.setOnClickListener(this);
tv_directory.setOnClickListener(this);
tv_dayornight.setOnClickListener(this);
tv_setting.setOnClickListener(this);
tv_Progress.setOnClickListener(this);
rl_Progress.setOnClickListener(this);
mPopupWindow = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
mPopupWindowTop = new PopupWindow(viewTop, ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
mPopupWindow.setOutsideTouchable(true);
mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
mPopupWindow.setOutsideTouchable(true);
mPopupWindow.setFocusable(true);// menu菜单获得焦点 如果没有获得焦点menu菜单中的控件事件无法响应
mPopupWindow.update();
mPopupWindowTop.setOutsideTouchable(true);
mPopupWindowTop.setBackgroundDrawable(new BitmapDrawable());
mPopupWindowTop.setOutsideTouchable(true);
mPopupWindowTop.setFocusable(true);// menu菜单获得焦点 如果没有获得焦点menu菜单中的控件事件无法响应
mPopupWindowTop.update();
view.setOnTouchListener(new View.OnTouchListener()// 需要设置点击之后取消popupview即使点击外面也可以捕获事件
{
public boolean onTouch(View v, MotionEvent event)
{
if (isShow())
{
dismiss();
}
return false;
}
});
config = Config.getInstance();
sb_progress.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
float pro;
// 触发操作,拖动
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
pro = (float) (progress / 10000.0);
showProgress(pro);
}
// 表示进度条刚开始拖动,开始拖动时候触发的操作
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
// 停止拖动时候
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
if (mSettingListener != null){
mSettingListener.changeProgress(pro);
}
}
});
initDayOrNight();
}
public void initDayOrNight(){
mDayOrNight = config.getDayOrNight();
if (mDayOrNight){
tv_dayornight.setText(mContext.getResources().getString(R.string.read_setting_day));
}else{
tv_dayornight.setText(mContext.getResources().getString(R.string.read_setting_night));
}
}
//改变显示模式
public void changeDayOrNight(){
if (mDayOrNight){
mDayOrNight = false;
tv_dayornight.setText(mContext.getResources().getString(R.string.read_setting_night));
}else{
mDayOrNight = true;
tv_dayornight.setText(mContext.getResources().getString(R.string.read_setting_day));
}
config.setDayOrNight(mDayOrNight);
if (mSettingListener != null) {
mSettingListener.dayorNight(mDayOrNight);
}
}
//显示书本进度
public void showProgress(float progress){
if (rl_Progress.getVisibility() != View.VISIBLE) {
rl_Progress.setVisibility(View.VISIBLE);
}
setProgress(progress);
}
//隐藏书本进度
public void hideProgress(){
rl_Progress.setVisibility(View.GONE);
}
@Override
public void show() {
hideProgress();
mPopupWindowTop.showAtLocation(mBookPageWidget, Gravity.TOP, 0, 0);
mPopupWindow.showAtLocation(mBookPageWidget, Gravity.BOTTOM, 0, 0);
}
private void setProgress(float progress){
DecimalFormat decimalFormat=new DecimalFormat("00.00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
String p=decimalFormat.format(progress * 100.0);//format 返回的是字符串
tv_Progress.setText(p + "%");
}
public void setSeekBarProgress(float progress){
sb_progress.setProgress((int) (progress * 10000));
}
@Override
public void dismiss() {
mPopupWindowTop.dismiss();
mPopupWindow.dismiss();
}
@Override
public Boolean isShow() {
return mPopupWindow.isShowing() || mPopupWindowTop.isShowing();
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_return:
if (mSettingListener != null) {
mSettingListener.back();
}
break;
case R.id.btn_light:
break;
case R.id.btn_listener_book:
break;
case R.id.tv_pre:
if (mSettingListener != null) {
mSettingListener.pre();
}
break;
case R.id.sb_progress:
break;
case R.id.tv_next:
if (mSettingListener != null) {
mSettingListener.next();
}
break;
case R.id.tv_directory:
if (mSettingListener != null) {
mSettingListener.directory();
}
break;
case R.id.tv_dayornight:
changeDayOrNight();
break;
case R.id.tv_setting:
if (mSettingListener != null) {
mSettingListener.setting();
}
break;
}
}
public void setSettingListener(SettingListener settingListener) {
this.mSettingListener = settingListener;
}
public interface SettingListener {
void back();
void pre();
void dismiss();
void next();
void directory();
void dayorNight(Boolean isNight);
void setting();
void changeProgress(float progress);
}
}

View File

@ -0,0 +1,10 @@
<component name="libraryTable">
<library name="Gradle: com.packetzoom:pz-okhttp3-interceptor:3.2.43@aar">
<CLASSES>
<root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/pz-okhttp3-interceptor-3.2.43.aar/d3dede00ee90d31b0f32cd372a35eab6/res" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/pz-okhttp3-interceptor-3.2.43.aar/d3dede00ee90d31b0f32cd372a35eab6/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -0,0 +1,462 @@
package com.novelbook.android.utils;
import android.content.Context;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
import com.novelbook.android.db.Novel;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
public class Fileutil {
public static String name ;
public static int folderNum = 0;
/**
* 计算目录大小
*
* @param dir
* @return
*/
public static long getDirSize(File dir) {
if (dir == null) {
return 0;
}
// 不是目录
if (!dir.isDirectory()) {
return 0;
}
long dirSize = 0;
File[] files = dir.listFiles();
for (File file : files) {
if (file.isFile()) {
dirSize += file.length();
} else if (file.isDirectory()) {
// dirSize += file.length();
// 递归调用
dirSize += getDirSize(file);
}
}
return dirSize;
}
/**
* 转换文件大小
*
* @param fileS
* @return B/KB/MB/GB
*/
public static String formatFileSize(long fileS) {
if (fileS == 0) {
return "0.00B";
}
DecimalFormat dFormat = new DecimalFormat("#.00");
String fileSizeString = "";
if (fileS < 1024) {
fileSizeString = dFormat.format((double) fileS) + "B";
} else if (fileS < 1048576) {
fileSizeString = dFormat.format((double) fileS / 1024) + "KB";
} else if (fileS < 1073741824) {
fileSizeString = dFormat.format((double) fileS / 1048576) + "MB";
} else {
fileSizeString = dFormat.format((double) fileS / 1073741824) + "GB";
}
return fileSizeString;
}
/**
* 文件目录地址
*
* @return
*/
public static String fileDirectory(String dirPath, String fileName) {
String filePath = "";
String storageState = Environment.getExternalStorageState();
if (storageState.equals(Environment.MEDIA_MOUNTED)) {
filePath = Environment.getExternalStorageDirectory()
.getAbsolutePath() + dirPath;
File file = new File(filePath);
if (!file.exists()) {
// 建立一个新的目录
file.mkdirs();
}
filePath = filePath + fileName;
}
return filePath;
}
/**
* 获取文件目录
*
* @return
*/
public static File getDirectoryFile(String dirPath) {
String storageState = Environment.getExternalStorageState();
File file = null;
if (storageState.equals(Environment.MEDIA_MOUNTED)) {
String filePath = Environment.getExternalStorageDirectory()
.getAbsolutePath() + dirPath;
file = new File(filePath);
if (!file.exists()) {
// 建立一个新的目录
file.mkdirs();
}
}
return file;
}
/**
* 检查文件后缀
*
* @param checkItsEnd
* @param fileEndings
* @return
*/
private static boolean checkEndsWithInStringArray(String checkItsEnd,
String[] fileEndings) {
for (String aEnd : fileEndings) {
if (checkItsEnd.endsWith(aEnd))
return true;
}
return false;
}
/**
* 根据不同的后缀打开不同的文件
*
* @param fileName
*/
/** public static void openFile(Context context, String fileName, File file) {
Intent intent;
if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingImage))) {
intent = OpenFiles.getImageFileIntent(file);
context.startActivity(intent);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingWebText))) {
intent = OpenFiles.getHtmlFileIntent(file);
context.startActivity(intent);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingPackage))) {
intent = OpenFiles.getApkFileIntent(file);
context.startActivity(intent);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingAudio))) {
intent = OpenFiles.getAudioFileIntent(file);
context.startActivity(intent);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingVideo))) {
intent = OpenFiles.getVideoFileIntent(file);
context.startActivity(intent);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingText))) {
intent = OpenFiles.getTextFileIntent(file);
context.startActivity(intent);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingPdf))) {
intent = OpenFiles.getPdfFileIntent(file);
context.startActivity(intent);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingWord))) {
intent = OpenFiles.getWordFileIntent(file);
context.startActivity(intent);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingExcel))) {
intent = OpenFiles.getExcelFileIntent(file);
context.startActivity(intent);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingPPT))) {
intent = OpenFiles.getPPTFileIntent(file);
context.startActivity(intent);
} else {
Toast.makeText(context, "打开文件错误", Toast.LENGTH_SHORT).show();
}
} */
/**
* 根据不同的后缀imageView设置不同的值
*
* @param fileName
*/
/** public static void setImage(Context context, String fileName,
ImageView imageView) {
if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingImage))) {
imageView.setImageResource(R.drawable.file_icon_picture);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingWebText))) {
imageView.setImageResource(R.drawable.file_icon_txt);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingPackage))) {
imageView.setImageResource(R.drawable.file_icon_rar);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingAudio))) {
imageView.setImageResource(R.drawable.file_icon_mp3);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingVideo))) {
imageView.setImageResource(R.drawable.file_icon_video);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingText))) {
imageView.setImageResource(R.drawable.file_icon_txt);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingPdf))) {
imageView.setImageResource(R.drawable.file_icon_pdf);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingWord))) {
imageView.setImageResource(R.drawable.file_icon_office);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingExcel))) {
imageView.setImageResource(R.drawable.file_icon_office);
} else if (checkEndsWithInStringArray(fileName, context.getResources()
.getStringArray(R.array.fileEndingPPT))) {
imageView.setImageResource(R.drawable.file_icon_office);
} else {
imageView.setImageResource(R.drawable.file);
}
} */
/**
*
* 返回本地文件列表
*
* @param //本地文件夹路径
*/
public static List<File> getFileListByPath( String path) {
Novel bookList = new Novel();
int fileNum = 0 ;
File dir = new File(path);
List<File> folderList = new ArrayList<File>();
List<File> fileList = new ArrayList<File>();
// 获取指定盘符下的所有文件列表。listFiles可以获得指定路径下的所有文件以数组方式返回
File[] files = dir.listFiles();
// 如果该目录下面为空,则该目录的此方法执行
if (files == null) {
return folderList;
}
// 通过循环将所遍历所有文件
for (int i = 0; i < files.length; i++) {
if (!files[i].isHidden()) {
if (files[i].isDirectory()) {
folderList.add(files[i]);
folderNum++;
}
if (files[i].isFile()) {
if (files[i].toString().contains(".txt")) { //txt".equals(extName)
fileList.add(files[i]);
// name = files[i].toString();
// FileActivity.paths.add(files[i].toString());
}
}
}
Log.d("Fileutil", folderNum + "");
}
folderList.addAll(fileList);
return folderList;
}
public static int getFileNum (List<File> list) {
File file;
int num = 0;
for (int i = 0 ; i<list.size(); i++) {
file = list.get(i);
if (file.isFile()){
num++;
}
}
return num;
}
/**
* 复制一个目录及其子目录、文件到另外一个目录
*
* @param src
* @param dest
* @throws IOException
*/
public static void copyFolder(File src, File dest) {
if (src.isDirectory()) {
if (!dest.exists()) {
dest.mkdir();
}
String files[] = src.list();
for (String file : files) {
File srcFile = new File(src, file);
File destFile = new File(dest, file);
// 递归复制
copyFolder(srcFile, destFile);
}
} else {
InputStream in;
OutputStream out;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
in.close();
out.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* @param src
* 源文件路径
* @param name
* 源文件名字
* @param dest
* 目标目录
*/
public static void copyFile(File src, String name, File dest) {
File file = new File(dest, name);
InputStream inputStream = null;
OutputStream outputStream = null;
try {
inputStream = new FileInputStream(src);
outputStream = new FileOutputStream(file);
byte[] b = new byte[1024];
int len = 0;
while ((len = inputStream.read(b)) != -1) {
outputStream.write(b, 0, len);
}
outputStream.close();
inputStream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 创建目录或文件
*/
public static void createDirorFile(String path, String name, Context context,int check) {
File file = new File(path + File.separator + name);
if (check==0) {// 如果为文件
try {
file.createNewFile();
Toast.makeText(context, "创建文件成功", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(context, "创建文件失败", Toast.LENGTH_SHORT).show();
}
} else if(check==1){
// 创建目录
if (file.mkdirs()) {
Toast.makeText(context, "创建目录成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "创建目录失败", Toast.LENGTH_SHORT).show();
}
}
}
/**
* 删除一个目录
*/
public static void deleteDir(File dir) {
if (dir == null || !dir.exists() || !dir.isDirectory()) {
return;
}
for (File file : dir.listFiles()) {
if (file.isFile())
file.delete(); // 删除所有文件
else if (file.isDirectory())
deleteDir(file); // 递规的方式删除文件夹
}
dir.delete();
}
/**
* @param fromDir
* 这个为源目录
* @param fromPath
* 这个为源目录的上一级路径
* @param toName
* 要修改的名字
*/
public static boolean renameFile(File fromDir, String fromPath,
String toName) {
File tempFile = new File(fromPath + File.separator + toName);
if (tempFile.exists()) {
return false;
} else {
return fromDir.renameTo(tempFile);
}
}
/** 去掉文件扩展名
*
*
* */
public static String getFileNameNoEx (String filename) {
if ((filename != null) && (filename.length() > 0)) {
int dot = filename.lastIndexOf('.');
if ((dot >-1) && (dot < (filename.length()))) {
return filename.substring(0, dot);
}
}
return filename;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,10 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:documentfile:28.0.0@aar">
<CLASSES>
<root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/documentfile-28.0.0.aar/bd8a84573a14077e3418642e1bf16f95/res" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/documentfile-28.0.0.aar/bd8a84573a14077e3418642e1bf16f95/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -0,0 +1,401 @@
package com.novelbook.android.Fragments;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.novelbook.android.R;
import com.novelbook.android.db.Novel;
import com.novelbook.android.netsubscribe.BookSubscribe;
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
import com.novelbook.android.netutils.OnSuccessAndFaultSub;
import com.novelbook.android.utils.Constants;
import com.novelbook.android.utils.GsonUtil;
import com.novelbook.android.utils.OnItemClickListener;
import com.novelbook.android.adapter.BookListAdapter;
import com.umeng.analytics.MobclickAgent;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
public class Fragment_booklist extends BasicFragment {
public static final String TAG = Fragment_booklist.class.getSimpleName();
private static final String EXTR_CATE ="cate" ;
private static final String EXTR_PROGRESS ="progress" ;
private static final String EXTR_SEARCH ="search";
private static final String EXTR_FN ="fn" ;
private static final String EXTR_BANGDAN ="bangdan" ;
private static final String EXTR_HISTORY ="history" ;
private static final String EXTR_CID ="cid" ;
private BookListAdapter mAdapter;
// private BookListAdapter mAdapter;
private List mData;;
private List mMoreData;
private String cate;
private int progress,cid;
private String keyWord ,fn,bangdan,history;
private int listItem =R.layout.recycle_list_item_horizon;
//private int pageNo=1;
private int totalCount;
// private int pageCount;
@BindView(R.id.rvBooklist)
RecyclerView mRecyclerView;
@SuppressLint("ValidFragment")
public Fragment_booklist(String cate, int progress) {
this.cate =cate;
this.progress = progress;
}
public Fragment_booklist() {
// Required empty public constructor
}
public static Fragment_booklist newInstance(int cid,String bangdan) {
Fragment_booklist fragment = new Fragment_booklist();
Bundle args = new Bundle();
args.putInt(EXTR_CID,cid);
args.putString(EXTR_BANGDAN,bangdan);
fragment.setArguments(args);
return fragment;
}
public static Fragment_booklist newInstance(String fn,String bangdan) {
Fragment_booklist fragment = new Fragment_booklist();
Bundle args = new Bundle();
args.putString(EXTR_FN,fn);
args.putString(EXTR_BANGDAN,bangdan);
fragment.setArguments(args);
return fragment;
}
public static Fragment_booklist newInstance(String noveType,int progress) {
Fragment_booklist fragment = new Fragment_booklist();
Bundle args = new Bundle();
args.putString(EXTR_CATE,noveType);
args.putInt(EXTR_PROGRESS, progress);
fragment.setArguments(args);
return fragment;
}
public static Fragment_booklist search(String keyWord) {
Fragment_booklist fragment = new Fragment_booklist();
Bundle args = new Bundle();
args.putString(EXTR_SEARCH,keyWord);
fragment.setArguments(args);
return fragment;
}
public static Fragment_booklist history() {
Fragment_booklist fragment = new Fragment_booklist();
Bundle args = new Bundle();
args.putString(EXTR_HISTORY,EXTR_HISTORY);
fragment.setArguments(args);
return fragment;
}
protected void processArguments(){
if (getArguments() != null) {
Bundle bundle = getArguments() ;
bangdan =bundle.getString(EXTR_BANGDAN);
fn= bundle.getString(EXTR_FN);
cid =bundle.getInt(EXTR_CID);
if(!TextUtils.isEmpty((fn))){
return;
}
cate = bundle.getString(EXTR_CATE);
progress = bundle.getInt(EXTR_PROGRESS);
keyWord =bundle.getString(EXTR_SEARCH);
history =bundle.getString(EXTR_HISTORY);
if(!TextUtils.isEmpty(history)){
listItem =R.layout.recycle_list_item_history;
}
}
}
int lastPageNo =0;
@Override
protected void fillData() {
if(mRecyclerView.getAdapter()==null) {
mRecyclerView.setLayoutManager(new LinearLayoutManager(activity));
mRecyclerView.setAdapter(mAdapter);
}
if(mMoreData!=null) {
if(mMoreData.size()>0) {
pageNo++;
}
int status =getPageCount()>= pageNo ? BookListAdapter.PULLUP_LOAD_MORE : BookListAdapter.NO_LOAD_MORE;
// mAdapter.setPercent(pageNo/pageCount);
mAdapter.AddFooterItem(mMoreData);
mAdapter.changeMoreStatus(status);
mMoreData.clear();
}
}
@Override
protected int getLayoutRes() {
return R.layout.fragment_fragment_booklist;
}
@Override
public void initData() {
if(pageNo>1){
if(lastPageNo ==pageNo){
return;
}
}
lastPageNo = pageNo;
// int pn = pageNo;
if(pageNo==1) {
if (mData != null) { //下拉刷新
mData = new ArrayList<Novel>();
mAdapter.setData(mData);
// loadListAd(mAdapter,1,false);
} else {
initialDataAdapter();
}
}
/* if(mAdapter!=null){
mAdapter.changeMoreStatus(BookListAdapter.LOADING_MORE);
}*/
mMoreData =null;
OnSuccessAndFaultListener successAndFaultListener = new OnSuccessAndFaultListener() {
@Override
public void onSuccess(String result) {
// mFirstPage= gson.fromJson(result, FirstPage.class);
try {
JSONObject jsonObject = new JSONObject(result);
setPageCount(jsonObject.getInt("pageCount")); ;
mMoreData = GsonUtil. parserJsonArray(jsonObject,Constants.BLOCK_TITLE_NOVELS);
if(mMoreData.size()>0){
loadListAd(mAdapter,1,mData.size()>0);
}
} catch (Exception e) {
e.printStackTrace(); Log.e(TAG, "onSuccess: 解析失败",e );
}
handler.sendEmptyMessage(1);
}
@Override
public void onFault(String errorMsg) {
//失败
Log.d(TAG, "error on get firstpage: " + errorMsg);
handler.sendEmptyMessage(1);
}
};
showProgressDialog(false,"正在加载...");
Log.d(TAG,String.format("fn is %s",fn) );
if(!TextUtils.isEmpty(bangdan) && (cid >0 || !TextUtils.isEmpty(fn))){ //榜单
// showProgressDialog(true, "正在加载榜单");
mAdapter.setShowTop(true);
BookSubscribe.getPaihangBangList(Constants.SEX,pageNo,cid,new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
@Override
public void onSuccess(String result) {
try {
JSONObject jsonObject = new JSONObject(result);
String resultstr = jsonObject.getString("rank") ;
setPageCount(jsonObject.getJSONObject("rank").getInt("pageCount")); ;
mMoreData = GsonUtil. parserJsonArray(resultstr,Constants.BLOCK_TITLE_NOVELS);
Log.d(TAG, "排行榜详细 onSuccess: pageCount " + getPageCount());
if(mMoreData.size()>0){
loadListAd(mAdapter,1,mData.size()>0);
}
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "onSuccess: 解析失败",e );
}
handler.sendEmptyMessage(1);
}
@Override
public void onFault(String errorMsg) {
//失败
Log.d(TAG, "error on get firstpage: " + errorMsg);
handler.sendEmptyMessage(1);
}
}, getActivity()));
}else if(!TextUtils.isEmpty(fn)){ //首页 更多
mAdapter.setShowTop(true);
// showProgressDialog(true, "正在加载更多");
BookSubscribe.getNovelPaihang(fn,Constants.SEX,new OnSuccessAndFaultSub(successAndFaultListener, getActivity()));
}
else if(!TextUtils.isEmpty((cate))) { //分类
mAdapter.setShowTop(true);
// showProgressDialog(true, "正在加载分类");
BookSubscribe.getCateNovelList(cate, pageNo, Constants.SEX, progress, new OnSuccessAndFaultSub(successAndFaultListener, getActivity()));
}else if(!TextUtils.isEmpty(keyWord)){ //搜索
// showProgressDialog(true, "正在加载搜索");
// mAdapter.setShowTop(true);
BookSubscribe.getSearchNovelList( keyWord,pageNo, Constants.SEX, new OnSuccessAndFaultSub(successAndFaultListener, getActivity()));
}else if(!TextUtils.isEmpty(history)){
loadHistory();
}else{
handler.sendEmptyMessage(1);
}
}
private void initialDataAdapter() {
mData = new ArrayList<Novel>();
mAdapter = new BookListAdapter(activity, mData, listItem, new OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
if(mData.get(position) instanceof Novel)
showBookDetail((Novel)mData.get(position));
// openBook(mData.get(position),mAdapter);
}
@Override
public void onItemLongClick(View view, int position) {
// initDialog(position);
// mAdapter.removeData(position);
}
@Override
public void onLinearOutClick(View view, int position, int llId) {
Toast.makeText(activity, "book " + position + " clicked",
Toast.LENGTH_SHORT).show();
}
});
mAdapter.setShowFootView(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(activity));
mRecyclerView.setAdapter(mAdapter);
}
@Override
public void initViews(){
//mRecyclerView
//lv_catalogue.setFastScrollStyle(R.style.FastScrollTheme); //不起作用
initLoadMoreListener();
}
//----------------绑定列表
void initialBookList() {
}
@Override
public void setFTag() {
}
private void initLoadMoreListener() {
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
int lastVisibleItem ;
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
Log.d(TAG, String.format("onScrollStateChanged , state %s ,lastVisibleitem %s ,getItemCount %s,pageno %s ,getPageCount() %s",
newState==RecyclerView.SCROLL_STATE_IDLE,lastVisibleItem,mAdapter.getItemCount(),pageNo,getPageCount()));
//判断RecyclerView的状态 是空闲时同时是最后一个可见的ITEM时才加载
if(newState==RecyclerView.SCROLL_STATE_IDLE&&lastVisibleItem+1==mAdapter.getItemCount()){
if(pageNo <= getPageCount()) {
//设置正在加载更多
mAdapter.changeMoreStatus(mAdapter.LOADING_MORE);
//改为网络请求
initData();
}else{
mAdapter.changeMoreStatus(mAdapter.NO_LOAD_MORE);
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
//最后一个可见的ITEM
lastVisibleItem=layoutManager.findLastVisibleItemPosition();
}
});
}
void loadHistory(){
initialDataAdapter();
new Thread() {
@Override
public void run() {
super.run();
mMoreData = Novel.getNovelsHistory();
setPageCount(1);
//
handler.sendEmptyMessage(1);
if(mMoreData!=null && mMoreData.size()>5) {
loadListAd(mAdapter, 1, mData.size() > 0);
}
}
}.start();
}
boolean isFirstLoad =true;
@Override
public void onResume(){
super.onResume();
// pageNo=1;
if(!TextUtils.isEmpty(history)){
if(isFirstLoad) {
isFirstLoad=false;
}else{
initData();
}
}
MobclickAgent.onPageStart(TAG);
}
@Override
public void onPause(){
super.onPause();
MobclickAgent.onPageEnd(TAG);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 975 B

View File

@ -0,0 +1,348 @@
package com.novelbook.android.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.novelbook.android.R;
/**
* 流程控制的比较严谨比如setup函数的使用
* updateShaderMatrix保证图片损失度最小和始终绘制图片正中央的那部分
* 作者思路是画圆用渲染器位图填充而不是把Bitmap重绘切割成一个圆形图片。
*/
public class CircleImageView extends ImageView {
//缩放类型
private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP;
private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888;
private static final int COLORDRAWABLE_DIMENSION = 2;
// 默认边界宽度
private static final int DEFAULT_BORDER_WIDTH = 0;
// 默认边界颜色
private static final int DEFAULT_BORDER_COLOR = Color.BLACK;
private static final boolean DEFAULT_BORDER_OVERLAY = false;
private final RectF mDrawableRect = new RectF();
private final RectF mBorderRect = new RectF();
private final Matrix mShaderMatrix = new Matrix();
//这个画笔最重要的是关联了mBitmapShader 使canvas在执行的时候可以切割原图片(mBitmapShader是关联了原图的bitmap的)
private final Paint mBitmapPaint = new Paint();
//这个描边则与本身的原图bitmap没有任何关联
private final Paint mBorderPaint = new Paint();
//这里定义了 圆形边缘的默认宽度和颜色
private int mBorderColor = DEFAULT_BORDER_COLOR;
private int mBorderWidth = DEFAULT_BORDER_WIDTH;
private Bitmap mBitmap;
private BitmapShader mBitmapShader; // 位图渲染
private int mBitmapWidth; // 位图宽度
private int mBitmapHeight; // 位图高度
private float mDrawableRadius;// 图片半径
private float mBorderRadius;// 带边框的的图片半径
private ColorFilter mColorFilter;
//初始false
private boolean mReady;
private boolean mSetupPending;
private boolean mBorderOverlay;
//构造函数
public CircleImageView(Context context) {
super(context);
init();
}
//构造函数
public CircleImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
/**
* 构造函数
*/
public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
//通过obtainStyledAttributes 获得一组值赋给 TypedArray数组 , 这一组值来自于res/values/attrs.xml中的name="CircleImageView"的declare-styleable中。
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0);
//通过TypedArray提供的一系列方法getXXXX取得我们在xml里定义的参数值
// 获取边界的宽度
mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH);
// 获取边界的颜色
mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR);
mBorderOverlay = DEFAULT_BORDER_OVERLAY;
//调用 recycle() 回收TypedArray,以便后面重用
a.recycle();
System.out.println("CircleImageView -- 构造函数");
init();
}
/**
* 作用就是保证第一次执行setup函数里下面代码要在构造函数执行完毕时调用
*/
private void init() {
//在这里ScaleType被强制设定为CENTER_CROP就是将图片水平垂直居中进行缩放。
super.setScaleType(SCALE_TYPE);
mReady = true;
if (mSetupPending) {
setup();
mSetupPending = false;
}
}
@Override
public ScaleType getScaleType() {
return SCALE_TYPE;
}
/**
* 这里明确指出 此种imageview 只支持CENTER_CROP 这一种属性
*
* @param scaleType
*/
@Override
public void setScaleType(ScaleType scaleType) {
if (scaleType != SCALE_TYPE) {
throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType));
}
}
@Override
public void setAdjustViewBounds(boolean adjustViewBounds) {
if (adjustViewBounds) {
throw new IllegalArgumentException("adjustViewBounds not supported.");
}
}
@Override
protected void onDraw(Canvas canvas) {
//如果图片不存在就不画
if (getDrawable() == null) {
return;
}
//绘制内圆形 图片 画笔为mBitmapPaint
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint);
//如果圆形边缘的宽度不为0 我们还要绘制带边界的外圆形 边界画笔为mBorderPaint
if (mBorderWidth != 0) {
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
setup();
}
public int getBorderColor() {
return mBorderColor;
}
public void setBorderColor(int borderColor) {
if (borderColor == mBorderColor) {
return;
}
mBorderColor = borderColor;
mBorderPaint.setColor(mBorderColor);
invalidate();
}
public void setBorderColorResource(@ColorRes int borderColorRes) {
setBorderColor(getContext().getResources().getColor(borderColorRes));
}
public int getBorderWidth() {
return mBorderWidth;
}
public void setBorderWidth(int borderWidth) {
if (borderWidth == mBorderWidth) {
return;
}
mBorderWidth = borderWidth;
setup();
}
public boolean isBorderOverlay() {
return mBorderOverlay;
}
public void setBorderOverlay(boolean borderOverlay) {
if (borderOverlay == mBorderOverlay) {
return;
}
mBorderOverlay = borderOverlay;
setup();
}
/**
* 以下四个函数都是
* 复写ImageView的setImageXxx()方法
* 注意这个函数先于构造函数调用之前调用
* @param bm
*/
@Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
mBitmap = bm;
setup();
}
@Override
public void setImageDrawable(Drawable drawable) {
super.setImageDrawable(drawable);
mBitmap = getBitmapFromDrawable(drawable);
System.out.println("setImageDrawable -- setup");
setup();
}
@Override
public void setImageResource(@DrawableRes int resId) {
super.setImageResource(resId);
mBitmap = getBitmapFromDrawable(getDrawable());
setup();
}
@Override
public void setImageURI(Uri uri) {
super.setImageURI(uri);
mBitmap = getBitmapFromDrawable(getDrawable());
setup();
}
@Override
public void setColorFilter(ColorFilter cf) {
if (cf == mColorFilter) {
return;
}
mColorFilter = cf;
mBitmapPaint.setColorFilter(mColorFilter);
invalidate();
}
/**
* Drawable转Bitmap
* @param drawable
* @return
*/
private Bitmap getBitmapFromDrawable(Drawable drawable) {
if (drawable == null) {
return null;
}
if (drawable instanceof BitmapDrawable) {
//通常来说 我们的代码就是执行到这里就返回了。返回的就是我们最原始的bitmap
return ((BitmapDrawable) drawable).getBitmap();
}
try {
Bitmap bitmap;
if (drawable instanceof ColorDrawable) {
bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
} else {
bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
}
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (OutOfMemoryError e) {
return null;
}
}
/**
* 这个函数很关键,进行图片画笔边界画笔(Paint)一些重绘参数初始化:
* 构建渲染器BitmapShader用Bitmap来填充绘制区域,设置样式以及内外圆半径计算等,
* 以及调用updateShaderMatrix()函数和 invalidate()函数;
*/
private void setup() {
//因为mReady默认值为false,所以第一次进这个函数的时候if语句为真进入括号体内
//设置mSetupPending为true然后直接返回后面的代码并没有执行。
if (!mReady) {
mSetupPending = true;
return;
}
//防止空指针异常
if (mBitmap == null) {
return;
}
// 构建渲染器用mBitmap位图来填充绘制区域 ,参数值代表如果图片太小的话 就直接拉伸
mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
// 设置图片画笔反锯齿
mBitmapPaint.setAntiAlias(true);
// 设置图片画笔渲染器
mBitmapPaint.setShader(mBitmapShader);
// 设置边界画笔样式
mBorderPaint.setStyle(Paint.Style.STROKE);//设画笔为空心
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor); //画笔颜色
mBorderPaint.setStrokeWidth(mBorderWidth);//画笔边界宽度
//这个地方是取的原图片的宽高
mBitmapHeight = mBitmap.getHeight();
mBitmapWidth = mBitmap.getWidth();
// 设置含边界显示区域取的是CircleImageView的布局实际大小为方形查看xml也就是160dp(240px) getWidth得到是某个view的实际尺寸
mBorderRect.set(0, 0, getWidth(), getHeight());
//计算 圆形带边界部分外圆的最小半径取mBorderRect的宽高减去一个边缘大小的一半的较小值这个地方我比较纳闷为什么求外圆半径需要先减去一个边缘大小
mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2);
// 初始图片显示区域为mBorderRectCircleImageView的布局实际大小
mDrawableRect.set(mBorderRect);
if (!mBorderOverlay) {
//demo里始终执行
//通过inset方法 使得图片显示的区域从mBorderRect大小上下左右内移边界的宽度形成区域查看xml边界宽度为2dp3px,所以方形边长为就是160-4=156dp(234px)
mDrawableRect.inset(mBorderWidth, mBorderWidth);
}
//这里计算的是内圆的最小半径,也即去除边界宽度的半径
mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2);
//设置渲染器的变换矩阵也即是mBitmap用何种缩放形式填充
updateShaderMatrix();
//手动触发ondraw()函数 完成最终的绘制
invalidate();
}
/**
* 这个函数为设置BitmapShader的Matrix参数设置最小缩放比例平移参数。
* 作用:保证图片损失度最小和始终绘制图片正中央的那部分
*/
private void updateShaderMatrix() {
float scale;
float dx = 0;
float dy = 0;
mShaderMatrix.set(null);
// 这里不好理解 这个不等式也就是(mBitmapWidth / mDrawableRect.width()) > (mBitmapHeight / mDrawableRect.height())
//取最小的缩放比例
if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) {
//y轴缩放 x轴平移 使得图片的y轴方向的边的尺寸缩放到图片显示区域mDrawableRect一样
scale = mDrawableRect.height() / (float) mBitmapHeight;
dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f;
} else {
//x轴缩放 y轴平移 使得图片的x轴方向的边的尺寸缩放到图片显示区域mDrawableRect一样
scale = mDrawableRect.width() / (float) mBitmapWidth;
dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f;
}
// shaeder的变换矩阵我们这里主要用于放大或者缩小。
mShaderMatrix.setScale(scale, scale);
// 平移
mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top);
// 设置变换矩阵
mBitmapShader.setLocalMatrix(mShaderMatrix);
}
}

View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Main2Activity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ToolBarTheme.AppBarOverlay">
<!--android:layout_height="?attr/actionBarSize"-->
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/Toolbar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbarHeight"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ToolBarTheme.PopupOverlay" >
<TextView
android:id="@+id/toolbarTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:gravity="center"
android:text="我是标题"
android:textSize="18sp"
android:layout_weight="1"
android:visibility="visible"
android:textColor="@color/white"
/>
<!-- <android.support.v7.widget.AppCompatSpinner
android:id="@+id/sexSelect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="50dp"
style="@style/common_spinner"
app:theme="@style/common_spinner"
android:popupTheme="@style/common_spinner"
android:entries="@array/sex"
android:layout_gravity="left|center_vertical"
android:layout_weight="0"
android:visibility="gone"
/>-->
<RadioGroup
android:id="@+id/rgSex"
style="@style/radioGroup"
android:layout_gravity="center_horizontal"
>
<RadioButton
android:id="@+id/radioButtonBoy"
android:text="男生"
style="@style/radioButton"
android:checked="true"
/>
<RadioButton
android:id="@+id/radioButtonGirl"
android:text="女生"
style="@style/radioButton"
/>
</RadioGroup>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/realcontent" />
</LinearLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:layout_margin="@dimen/fab_margin"
android:visibility="gone"
app:srcCompat="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<resources></resources>

View File

@ -0,0 +1,75 @@
package com.novelbook.android.AD.toutiao;
/*import android.content.Context;
import android.text.TextUtils;
import android.util.Log;
import com.bytedance.sdk.openadsdk.TTAdConfig;
import com.bytedance.sdk.openadsdk.TTAdConstant;
import com.bytedance.sdk.openadsdk.TTAdManager;
import com.bytedance.sdk.openadsdk.TTAdSdk;
import com.novelbook.android.BuildConfig;
import com.novelbook.android.utils.Constants;
import static com.novelbook.android.bean.AdSetting.getAppID;*/
import android.content.Context;
/**
* 可以用一个单例来保存TTAdManager实例在需要初始化sdk的时候调用
*/
public class TTAdManagerHolder {
//step1:接入网盟广告sdk的初始化操作详情见接入文档和穿山甲平台说明
private static void doInit(Context context) {
/* if (!sInit) {
TTAdSdk.init(context, buildConfig(context));
sInit = true;
}*/
}
public static void init(Context context) {
/* if( Constants.AD_SETTING.isShowAdsense() &&
!TextUtils.isEmpty(getAppID(Constants.AD_TOUTIAO)) ) {
doInit(context);
}*/
}
/*
private static boolean sInit;
public static TTAdManager get() {
if (!sInit) {
throw new RuntimeException("TTAdSdk is not init, please check.");
}
return TTAdSdk.getAdManager();
}
public static void init(Context context) {
if( Constants.AD_SETTING.isShowAdsense() &&
!TextUtils.isEmpty(getAppID(Constants.AD_TOUTIAO)) ) {
doInit(context);
}
}
private static TTAdConfig buildConfig(Context context) {
Log.d("adinit", "buildConfig:Constants.SEX= "+Constants.SEX );
return new TTAdConfig.Builder()
.appId(getAppID(Constants.AD_TOUTIAO))
.useTextureView(false) //使用TextureView控件播放视频,默认为SurfaceView,当有SurfaceView冲突的场景可以使用TextureView
.appName("如意小说")
.titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK)
.allowShowNotify(true) //是否允许sdk展示通知栏提示
.allowShowPageWhenScreenLock(true) //是否在锁屏场景支持展示广告落地页
// .debug(true) //测试阶段打开,可以通过日志排查问题,上线时去除该调用
.directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI, TTAdConstant.NETWORK_STATE_4G) //允许直接下载的网络状态集合
.supportMultiProcess(false) //是否支持多进程true支持
.gender(Constants.SEX==1 ? TTAdConstant.GENDER_MALE : TTAdConstant.GENDER_FEMALE) // TTAdConstant.GENDER_UNKNOWN)
// .age(20) //TODO: 年龄收集
.build();
}*/
public static void initOnSexChange(Context context){
// buildConfig(context);
}
}

View File

@ -0,0 +1,53 @@
package com.novelbook.android.utils;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class BitmapUtil {
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
/** final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
} */
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// 选择宽和高中最小的比率作为inSampleSize的值这样可以保证最终图片的宽和高
// 一定都不会大于等于目标的宽和高。
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -0,0 +1,421 @@
package com.novelbook.android.Fragments;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.novelbook.android.R;
import com.novelbook.android.db.Novel;
import com.novelbook.android.netsubscribe.BookSubscribe;
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
import com.novelbook.android.netutils.OnSuccessAndFaultSub;
import com.novelbook.android.utils.Constants;
import com.novelbook.android.utils.GsonUtil;
import com.novelbook.android.utils.OnItemClickListener;
import com.novelbook.android.adapter.BookListAdapter;
import com.umeng.analytics.MobclickAgent;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
public class Fragment_booklist extends BasicFragment {
public static final String TAG = Fragment_booklist.class.getSimpleName();
private static final String EXTR_CATE ="cate" ;
private static final String EXTR_PROGRESS ="progress" ;
private static final String EXTR_SEARCH ="search";
private static final String EXTR_FN ="fn" ;
private static final String EXTR_BANGDAN ="bangdan" ;
private static final String EXTR_HISTORY ="history" ;
private static final String EXTR_CID ="cid" ;
private BookListAdapter mAdapter;
// private BookListAdapter mAdapter;
private List mData;;
private List mMoreData;
private String cate;
private int progress,cid;
private String keyWord ,fn,bangdan,history;
private int listItem =R.layout.recycle_list_item_horizon;
//private int pageNo=1;
private int totalCount;
// private int pageCount;
@BindView(R.id.rvBooklist)
RecyclerView mRecyclerView;
@SuppressLint("ValidFragment")
public Fragment_booklist(String cate, int progress) {
this.cate =cate;
this.progress = progress;
}
public Fragment_booklist() {
// Required empty public constructor
}
public static Fragment_booklist newInstance(int cid,String bangdan) {
Fragment_booklist fragment = new Fragment_booklist();
Bundle args = new Bundle();
args.putInt(EXTR_CID,cid);
args.putString(EXTR_BANGDAN,bangdan);
fragment.setArguments(args);
return fragment;
}
public static Fragment_booklist newInstance(String fn,String bangdan) {
Fragment_booklist fragment = new Fragment_booklist();
Bundle args = new Bundle();
args.putString(EXTR_FN,fn);
args.putString(EXTR_BANGDAN,bangdan);
fragment.setArguments(args);
return fragment;
}
public static Fragment_booklist newInstance(String noveType,int progress) {
Fragment_booklist fragment = new Fragment_booklist();
Bundle args = new Bundle();
args.putString(EXTR_CATE,noveType);
args.putInt(EXTR_PROGRESS, progress);
fragment.setArguments(args);
return fragment;
}
public static Fragment_booklist search(String keyWord) {
Fragment_booklist fragment = new Fragment_booklist();
Bundle args = new Bundle();
args.putString(EXTR_SEARCH,keyWord);
fragment.setArguments(args);
return fragment;
}
public static Fragment_booklist history() {
Fragment_booklist fragment = new Fragment_booklist();
Bundle args = new Bundle();
args.putString(EXTR_HISTORY,EXTR_HISTORY);
fragment.setArguments(args);
return fragment;
}
protected void processArguments(){
if (getArguments() != null) {
Bundle bundle = getArguments() ;
bangdan =bundle.getString(EXTR_BANGDAN);
fn= bundle.getString(EXTR_FN);
cid =bundle.getInt(EXTR_CID);
if(!TextUtils.isEmpty((fn))){
return;
}
cate = bundle.getString(EXTR_CATE);
progress = bundle.getInt(EXTR_PROGRESS);
keyWord =bundle.getString(EXTR_SEARCH);
history =bundle.getString(EXTR_HISTORY);
if(!TextUtils.isEmpty(history)){
listItem =R.layout.recycle_list_item_history;
}
}
}
int lastPageNo =0;
@Override
protected void fillData() {
if(mRecyclerView.getAdapter()==null) {
mRecyclerView.setLayoutManager(new LinearLayoutManager(activity));
mRecyclerView.setAdapter(mAdapter);
}
if(mMoreData!=null) {
if(mMoreData.size()>0) {
pageNo++;
}
int status =getPageCount()>= pageNo ? BookListAdapter.PULLUP_LOAD_MORE : BookListAdapter.NO_LOAD_MORE;
// mAdapter.setPercent(pageNo/pageCount);
mAdapter.AddFooterItem(mMoreData);
mAdapter.changeMoreStatus(status);
mMoreData.clear();
}
}
@Override
protected int getLayoutRes() {
return R.layout.fragment_fragment_booklist;
}
@Override
public void initData() {
if(pageNo>1){
if(lastPageNo ==pageNo){
return;
}
}
lastPageNo = pageNo;
// int pn = pageNo;
if(pageNo==1) {
noveIds = new ArrayList<Integer>();
if (mData != null) { //下拉刷新
mData = new ArrayList<Novel>();
mAdapter.setData(mData);
// loadListAd(mAdapter,1,false);
} else {
initialDataAdapter();
}
}
/* if(mAdapter!=null){
mAdapter.changeMoreStatus(BookListAdapter.LOADING_MORE);
}*/
mMoreData =null;
OnSuccessAndFaultListener successAndFaultListener = new OnSuccessAndFaultListener() {
@Override
public void onSuccess(String result) {
// mFirstPage= gson.fromJson(result, FirstPage.class);
try {
JSONObject jsonObject = new JSONObject(result);
setPageCount(jsonObject.getInt("pageCount")); ;
List<Novel> list = GsonUtil. parserJsonArray(jsonObject,Constants.BLOCK_TITLE_NOVELS);
mMoreData =new ArrayList<Novel>();
for(Novel novel :list){
if(!noveIds.contains(novel.getNovelId())){
mMoreData.add(novel);
noveIds.add(novel.getNovelId());
}
}
if(mMoreData.size()>0){
loadListAd(mAdapter,1,mData.size()>0);
}
} catch (Exception e) {
e.printStackTrace(); Log.e(TAG, "onSuccess: 解析失败",e );
}
handler.sendEmptyMessage(1);
}
@Override
public void onFault(String errorMsg) {
//失败
Log.d(TAG, "error on get firstpage: " + errorMsg);
handler.sendEmptyMessage(1);
}
};
showProgressDialog(false,"正在加载...");
Log.d(TAG,String.format("fn is %s",fn) );
if(!TextUtils.isEmpty(bangdan) && (cid >0 || !TextUtils.isEmpty(fn))){ //榜单
// showProgressDialog(true, "正在加载榜单");
mAdapter.setShowTop(true);
BookSubscribe.getPaihangBangList(Constants.SEX,pageNo,cid,new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
@Override
public void onSuccess(String result) {
try {
JSONObject jsonObject = new JSONObject(result);
String resultstr = jsonObject.getString("rank") ;
setPageCount(jsonObject.getJSONObject("rank").getInt("pageCount")); ;
List<Novel> list = GsonUtil. parserJsonArray(resultstr,Constants.BLOCK_TITLE_NOVELS);
mMoreData =new ArrayList<Novel>();
for(Novel novel :list){
if(!noveIds.contains(novel.getNovelId())){
mMoreData.add(novel);
noveIds.add(novel.getNovelId());
}
}
Log.d(TAG, "排行榜详细 onSuccess: pageCount " + getPageCount());
if(mMoreData.size()>0){
loadListAd(mAdapter,1,mData.size()>0);
}
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "onSuccess: 解析失败",e );
}
Log.d(TAG, "progress: progress to hide");
handler.sendEmptyMessage(1);
}
@Override
public void onFault(String errorMsg) {
//失败
Log.d(TAG, "error on get firstpage: " + errorMsg);
handler.sendEmptyMessage(1);
}
}, getActivity()));
}else if(!TextUtils.isEmpty(fn)){ //首页 更多
mAdapter.setShowTop(true);
// showProgressDialog(true, "正在加载更多");
BookSubscribe.getNovelPaihang(fn,pageNo,Constants.SEX,new OnSuccessAndFaultSub(successAndFaultListener, getActivity()));
}
else if(!TextUtils.isEmpty((cate))) { //分类
mAdapter.setShowTop(true);
// showProgressDialog(true, "正在加载分类");
BookSubscribe.getCateNovelList(cate, pageNo, Constants.SEX, progress, new OnSuccessAndFaultSub(successAndFaultListener, getActivity()));
}else if(!TextUtils.isEmpty(keyWord)){ //搜索
// showProgressDialog(true, "正在加载搜索");
// mAdapter.setShowTop(true);
BookSubscribe.getSearchNovelList( keyWord,pageNo, Constants.SEX, new OnSuccessAndFaultSub(successAndFaultListener, getActivity()));
}else if(!TextUtils.isEmpty(history)){
loadHistory();
}else{
handler.sendEmptyMessage(1);
}
}
private void initialDataAdapter() {
mData = new ArrayList<Novel>();
mAdapter = new BookListAdapter(activity, mData, listItem, new OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
if(mData.get(position) instanceof Novel)
showBookDetail((Novel)mData.get(position));
// openBook(mData.get(position),mAdapter);
}
@Override
public void onItemLongClick(View view, int position) {
// initDialog(position);
// mAdapter.removeData(position);
}
@Override
public void onLinearOutClick(View view, int position, int llId) {
Toast.makeText(activity, "book " + position + " clicked",
Toast.LENGTH_SHORT).show();
}
});
mAdapter.setShowFootView(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(activity));
mRecyclerView.setAdapter(mAdapter);
}
@Override
public void initViews(){
//mRecyclerView
//lv_catalogue.setFastScrollStyle(R.style.FastScrollTheme); //不起作用
initLoadMoreListener();
}
//----------------绑定列表
void initialBookList() {
}
@Override
public void setFTag() {
}
private void initLoadMoreListener() {
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
int lastVisibleItem ;
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
Log.d(TAG, String.format("onScrollStateChanged , state %s ,lastVisibleitem %s ,getItemCount %s,pageno %s ,getPageCount() %s",
newState==RecyclerView.SCROLL_STATE_IDLE,lastVisibleItem,mAdapter.getItemCount(),pageNo,getPageCount()));
//判断RecyclerView的状态 是空闲时同时是最后一个可见的ITEM时才加载
if(newState==RecyclerView.SCROLL_STATE_IDLE&&lastVisibleItem+1==mAdapter.getItemCount()){
if(pageNo <= getPageCount()) {
//设置正在加载更多
mAdapter.changeMoreStatus(mAdapter.LOADING_MORE);
//改为网络请求
initData();
}else{
mAdapter.changeMoreStatus(mAdapter.NO_LOAD_MORE);
}
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
//最后一个可见的ITEM
lastVisibleItem=layoutManager.findLastVisibleItemPosition();
}
});
}
void loadHistory(){
initialDataAdapter();
new Thread() {
@Override
public void run() {
super.run();
mMoreData = Novel.getNovelsHistory();
setPageCount(1);
//
handler.sendEmptyMessage(1);
if(mMoreData!=null && mMoreData.size()>5) {
loadListAd(mAdapter, 1, mData.size() > 0);
}
}
}.start();
}
boolean isFirstLoad =true;
@Override
public void onResume(){
super.onResume();
// pageNo=1;
if(!TextUtils.isEmpty(history)){
if(isFirstLoad) {
isFirstLoad=false;
}else{
initData();
}
}
MobclickAgent.onPageStart(TAG);
}
@Override
public void onPause(){
super.onPause();
MobclickAgent.onPageEnd(TAG);
}
}

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 边框颜色值 -->
<item>
<shape>
<solid android:color="#9c9c9c" />
</shape>
</item>
<!-- 主体背景颜色值 -->
<item android:bottom="1dp"> <!--设置只有底部有边框-->
<shape>
<solid android:color="#ffffff" />
</shape>
</item>
</layer-list>

View File

@ -0,0 +1,12 @@
<component name="libraryTable">
<library name="Gradle: com.android.support.test:monitor:1.0.2@aar">
<CLASSES>
<root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/monitor-1.0.2.aar/f9313d309242cd0979a51392ae691413/res" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/monitor-1.0.2.aar/f9313d309242cd0979a51392ae691413/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.support.test/monitor/1.0.2/5764301056100b445e9ba31df7d1b554a55450f6/monitor-1.0.2-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -0,0 +1,91 @@
package com.novelbook.android.utils;
import com.novelbook.android.R;
import com.novelbook.android.bean.AdSetting;
import com.novelbook.android.bean.ProgressType;
import java.util.ArrayList;
import java.util.List;
public class Constants {
public static final String BLOCK_TITLE_NOVELS = "ns";
public static final String HOT_KEYS = "keywords";
public static final int NOVEL_SPAN_CNT =3 ; //grid columns
public static final int MAXAGE_MAX =60*60*24*28; //28 天 ;
public static final int MAXAGE_MULU = 60*60*24*7*2; //2周;;
public static final String VERSION_ADDRESS ="version.xml";
public static int APP_START_COUNT_4AD =0 ;
public static int APP_START_COUNT =0 ;
public static int SHELF_ORDER =0 ;
public static AdSetting AD_SETTING;
public static final int AD_TENCENT_QQ =1;
public static final int AD_MOB =2;
public static final int AD_TOUTIAO =3;
public static final int AD_BANNER_TOP =1;
public static final int AD_BANNER_BOTTOM =2;
public static boolean AD_BACKGROUND_TRANSPARENT =true ;
public static boolean PRE_LOAD_CHAPT = false;
public static int SCREEN_HEIGHT_PIX =1920 ;
public static int SCREEN_WIDTH_PIX = 1080;
public static String DECLARE ="";
public static boolean SHOW_NOVEL_CHAPTER_URL =false;
/* public static boolean SHOWAD =false ;
public static int AD_NATIVE_BANNER_SOURCE = 1 ; //1:tencent,2:toutiao
public static int AD_BANNER_SOURCE = 2 ; //1:tencent,2:toutiao
public static int AD_UNIFIED_RECYCLE_SOURCE = 2 ; //1:tencent,2:toutiao
public static int AD_SPLASH_SOURCE = 1 ; //1:tencent,2:toutiao
public static int AD_SOURCE =1 ; //1:tencent,2:toutiao
public static long AD_SPLASH_INVTERVAL = 5*60*1000;//间隔5分钟
public static int AD_SPLASH_PAGES = 15;
public static int AD_CHAPT_TOP_BANNER_PER_PAGE_COUNT=0; //每几页show topbanner
public static int AD_CHAPT_NATIVE_BANNER_PER_PAGE_COUNT=0; //每几页show nativebanner
public static int AD_CHAPTER_BANNER_POSITION =1;//1 top 2 bottom
public static int AD_CHAPTER_BANNER_KEEP_PAGES =20;//1 top 2 bottom
public static boolean AD_SHOW_CHAPT_END_BANNER =true;*/
public static int ONE_DP_SIZE =1;
public static long LAST_G = 0;//主目录API上次访问时间
public static long MAXAGE_G = 3600;//主目录API上次访问时间
public static String[] HOT_KEYS_VALUE = {};
public static int SEX=1; //1 男2女
public static String A_Regex = "<a[^>]+href[\\s]*=[\\s]*['\"]?([^'\"]+)['\"\\s]?[^>]*>([^<]+)<"; //TODO: 从服务器更新
public static List<String> lstProperties =null;
public static List<String> lstSex =null;
public static List<String> lstNt=null;
//public static List<Progress> lstProgress=null;
public static String[] lstProgress={"连载中","已完本","新书"};
public static List<ProgressType> lstProgressType=null;
public static int retryCnt =5;
public static int muluRetryCnt =5;
// public static List<String> lstProgress=null;
public static boolean showDialogOnUi =true;
public static boolean showDialogOnUiPage =false;
public static String announcement ="免责声明:阅读内容均来自互联网,本软件仅提供转码服务";
public static String email ="";
public static int minVersion =0;
public static int version =0;
public static int serverVersion =0;
public static String updateUrl="http://xiaoshuofenxiang.com/version.xml";;
public static final String BAD_CHAR =" ";//not blank,don't edit
public final static int MAX_PAGE_CNT =10;//最多加载的页数
public final static int MAX_SLEEP_4_CHAPT_DOWNLOAD =15000;//最多等待时间10s
public final static int MAX_SHELF_CNT =100;
public static final String REPORT_NEW_UPDATE ="HasNewUpdate"; //其它源有新章节
public static final String REPORT_REX_CHAPTER_CONTENT_ERROR ="EmptyText";//章节内容解析错误
public static final String REPORT_REX_MULU_ERROR ="NovelNotFound";//目录获取错误 ,或书不存在
public static List<String> REPORT_HIS = new ArrayList<String>();
}

View File

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="0dp"
android:layout_weight="1"
android:background="@drawable/item_selector"
android:clickable="true"
android:gravity="center"
android:orientation="vertical"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView"
style="@style/NovelImage.horizon"
android:src="@drawable/googleg_standard_color_18" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="top"
android:orientation="vertical"
>
<TextView
android:id="@+id/title"
style="@style/TextViewNovelTitle.horizon"
android:text="ddd " />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:orientation="horizontal">
<TextView
android:id="@+id/category"
style="@style/TextViewNovelType"
android:text=" " />
<TextView
android:id="@+id/tvNovelStatus"
style="@style/TextViewNovelType.Status"
android:layout_marginLeft="10dp"
android:text=" "
/>
<TextView
android:id="@+id/author"
style="@style/TextViewNovelAuthor"
android:text=" " />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="2dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tvLastRead"
style="@style/TextViewNovelType"
android:layout_marginStart="10dp"
android:text=" "
android:textColor="@color/common_google_signin_btn_text_light" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="4dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tvProgress"
style="@style/TextViewNovelType"
android:text=" "
android:textColor="@color/common_google_signin_btn_text_light" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="2dp"
android:orientation="horizontal">
<TextView
android:id="@+id/tvReadtime"
style="@style/TextViewNovelType"
android:layout_marginLeft="10dp"
android:text=" "
android:textColor="@color/common_google_signin_btn_text_light" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout style="@style/llGraySplit.2dp.gray" />
</LinearLayout>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
<component name="libraryTable">
<library name="Gradle: com.squareup.okhttp3:logging-interceptor:3.14.0@jar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup.okhttp3/logging-interceptor/3.14.0/65ba5af1b51eeb92af9ca825cd0058d085d8619e/logging-interceptor-3.14.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup.okhttp3/logging-interceptor/3.14.0/a5dfb590845f34a7b24f053c0feee1eaccbc5179/logging-interceptor-3.14.0-sources.jar!/" />
</SOURCES>
</library>
</component>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@drawable/item_selector"
android:clickable="true"
android:layout_marginBottom="0dp"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:layout_weight="1">
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageView"
style="@style/NovelImage.horizon"
android:src="@drawable/googleg_standard_color_18" />
<ImageView
android:id="@+id/imageTop1"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="start"
android:layout_marginTop="2dp"
android:layout_marginRight="6dp"
android:visibility="gone"
android:src="@drawable/sc_top_one" />
<ImageView
android:id="@+id/imageTop2"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="start"
android:layout_marginTop="2dp"
android:layout_marginRight="6dp"
android:visibility="gone"
android:src="@drawable/sc_top_two" />
<ImageView
android:id="@+id/imageTop3"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="start"
android:layout_marginTop="2dp"
android:layout_marginRight="6dp"
android:visibility="gone"
android:src="@drawable/sc_top_three" />
</FrameLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top"
android:layout_weight="1"
>
<TextView
android:id="@+id/title"
style="@style/TextViewNovelTitle.horizon"
android:text=" "
/>
<LinearLayout
android:layout_marginTop="2dp"
android:layout_marginLeft="0dp"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
style="@style/TextViewNovelType"
android:id="@+id/category"
android:text=" "
/>
<TextView
style="@style/TextViewNovelType.Status"
android:id="@+id/tvNovelStatus"
android:text=""
android:layout_marginLeft="10dp"
/>
<TextView
android:id="@+id/author"
style="@style/TextViewNovelAuthor"
android:text=" "
/>
</LinearLayout>
<TextView
android:id="@+id/desc"
style="@style/TextViewNovelDesc"
android:text=" "
/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,791 @@
package com.novelbook.android.Fragments;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.BottomSheetDialog;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.androidquery.callback.AQuery2;
import com.novelbook.android.AD.toutiao.TTAdManagerHolder;
import com.novelbook.android.BuildConfig;
import com.novelbook.android.Main2Activity;
import com.novelbook.android.R;
import com.novelbook.android.db.Chapter;
import com.novelbook.android.db.Novel;
import com.novelbook.android.filechooser.FileChooserActivity;
import com.novelbook.android.netsubscribe.BookSubscribe;
import com.novelbook.android.netutils.HttpMethods;
import com.novelbook.android.netutils.NetUtil;
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
import com.novelbook.android.netutils.OnSuccessAndFaultSub;
import com.novelbook.android.utils.CommonUtil;
import com.novelbook.android.utils.Constants;
import com.novelbook.android.utils.FileUtils;
import com.novelbook.android.utils.Fileutil;
import com.novelbook.android.utils.GsonUtil;
import com.novelbook.android.utils.ImageUtil;
import com.novelbook.android.utils.MyImageLoader;
import com.novelbook.android.utils.OnItemClickListener;
import com.novelbook.android.adapter.BookListAdapter;
import com.umeng.analytics.MobclickAgent;
import org.json.JSONObject;
import org.litepal.LitePal;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class Fragment_Shelf extends BasicFragment {
public static final String TAG = Fragment_Shelf.class.getSimpleName();
private boolean[] flag;//此处添加一个boolean类型的数组
private boolean isSelectAll = true;
private MyImageLoader loader = new MyImageLoader();
@BindView(R.id.llShelfBottom)
LinearLayout llShelfBottom;
@BindView(R.id.id_recyclerview)
RecyclerView mRecyclerView;
// private List<Novel> mDatas;
private BookListAdapter mAdapter;
List<Novel> lstUpdate = new ArrayList<Novel>();
private List<Novel> bookLists;
// private ShelfAdapter adapter;
private String noveIds;
BottomSheetDialog bottomSheetDialog;
@BindView(R.id.banner_container)
FrameLayout mBannerContainer;
public Fragment_Shelf() {
// Required empty public constructor
}
public static Fragment_Shelf newInstance(String param1, String param2) {
Fragment_Shelf fragment = new Fragment_Shelf();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
private void loadNovelsOnShelf() {
bookLists = Novel.getNovelsOnShelf();
noveIds = "";
for (Novel novel : bookLists) {
if (novel.isFinished() || novel.isLocalBook() || novel.isUpdated()) {
continue;
}
noveIds += novel.getNovelId() + ",";
}
}
void test(int maxAge) {
String url = "http://xiaoshuofenxiang.com/api/r/need-update";
Request request = new Request.Builder().url(url) // .header("User-Agent", "OkHttp Example")
.removeHeader("Pragma")
.header("Cache-Control", "public, max-age=" + maxAge)
.build();
if (maxAge == -1) {
request = new Request.Builder().url(url).build();
}
HttpMethods.getOkClient().newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
ResponseBody body = response.body();
Log.d(TAG, "onResponse:test " + body.string());
handler.sendEmptyMessage(1);
}
});
}
@Override
protected int getLayoutRes() {
return R.layout.fragment_fragment__shelf;
}
/**
* to get updated info from server,TODO: put it in service ,scheduled
*/
private void getUpdatedData() {
List<Integer> novelIds;
OnSuccessAndFaultListener successAndFaultListener = new OnSuccessAndFaultListener() {
@Override
public void onSuccess(String result) {
// mFirstPage= gson.fromJson(result, FirstPage.class);
try {
lstUpdate = GsonUtil.parserJsonArray(result, Constants.BLOCK_TITLE_NOVELS);
if (lstUpdate.size() > 0) {
for (Novel novel2 : lstUpdate) {
novel2.checkAndUpdate();
}
}
loadNovelsOnShelf();
/* for(Novel nove : bookLists){
nove.testUpdate();
}*/
} catch (Exception e) {
e.printStackTrace();
}
handler.sendEmptyMessage(1);
}
@Override
public void onFault(String errorMsg) {
//失败
Log.d(TAG, "error on get firstpage: " + errorMsg);
handler.sendEmptyMessage(1);
}
};
if (TextUtils.isEmpty(noveIds)) {
loadNovelsOnShelf();
}
if (!TextUtils.isEmpty(noveIds)) {
BookSubscribe.getNovelsByIds(noveIds, new OnSuccessAndFaultSub(successAndFaultListener, getActivity()));
} else {
handler.sendEmptyMessage(1);
}
}
@Override
public void initData() {
// mDatas = initData(mDatas,'X');
// bookLists = LitePal.where("isOnShelf=? or novelId=? ","1","").find(Novel.class);
loadNovelsOnShelf();
// getUpdatedData();
flag = new boolean[bookLists.size()];
/* if(bookLists.size()>0) { //TODO: to remove
bookLists.get(0).setUpdated(true);
// bookLists.get(bookLists.size()-1).setUpdated(true);
}*/
mAdapter = new BookListAdapter(activity, bookLists, R.layout.recycle_list_item, new OnItemClickListener() {
private long lastTimeMillis;
private static final long MIN_CLICK_INTERVAL = 1000;
protected boolean isTimeEnabled() {
long currentTimeMillis = System.currentTimeMillis();
if ((currentTimeMillis - lastTimeMillis) > MIN_CLICK_INTERVAL) {
lastTimeMillis = currentTimeMillis;
return true;
}
return false;
}
@Override
public void onItemClick(View view, int position) {
if (isTimeEnabled()) {
Novel book = bookLists.get(position);
openBook(book, mAdapter);
} else {
Log.d(TAG, "onclickInterval: bad click");
}
}
@Override
public void onItemLongClick(View view, int position) {
initDialog(position);
// mAdapter.removeData(position);
}
@Override
public void onLinearOutClick(View view, int position, int llId) {
}
});
mAdapter.setNorecord(R.string.noRecordInshelf);
((Main2Activity) activity).setShelfFragment(this);
}
@Override
void initSwipeRefreshLayout() {
super.initSwipeRefreshLayout();
mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
// 开始刷新,设置当前为刷新状态
//swipeRefreshLayout.setRefreshing(true);
pageNo = 1;
getUpdatedData();
}
});
}
@Override
public void initViews() {
initReceyleView();
}
protected void processArguments() {
if (getArguments() != null) {
Bundle bundle = getArguments();
}
}
@Override
protected void fillData() {
/* for(Novel nv :bookLists){
nv.testUpdate();
}*/
mAdapter.setData(bookLists);
}
public void initReceyleView() {
// initData();
// mRecyclerView.setLayoutManager(new LinearLayoutManager(this.activity));
mRecyclerView.setLayoutManager(new GridLayoutManager(activity, 3));
mRecyclerView.setAdapter(mAdapter);
llShelfBottom.setVisibility(View.GONE);
}
public void showShelfMoreSheet() {
BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(this.activity);
bottomSheetDialog.setContentView(R.layout.fragment_shelf_more_sheet);
//给布局设置透明背景色
bottomSheetDialog.getDelegate().findViewById(android.support.design.R.id.design_bottom_sheet)
.setBackgroundColor(getResources().getColor(android.R.color.transparent));
Button btnZhengli = bottomSheetDialog.findViewById(R.id.btnZhengli);
btnZhengli.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
bottomSheetDialog.dismiss();
initZhengliDialog();
}
});
Button btnImport = bottomSheetDialog.findViewById(R.id.btnImport);
btnImport.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
bottomSheetDialog.dismiss();
Intent intent = new Intent(activity, FileChooserActivity.class);
startActivityForResult(intent, Activity.RESULT_FIRST_USER);
// startActivity(intent);
}
});
Button btnCancel = bottomSheetDialog.findViewById(R.id.btnCancel);
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
bottomSheetDialog.dismiss();
}
});
bottomSheetDialog.show();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// bookLists = LitePal.findAll(Novel.class);
// mAdapter.notifyDataSetChanged();
initViews();
}
private void initDialog(int position) {
bottomSheetDialog = new BottomSheetDialog(this.activity);
bottomSheetDialog.setContentView(R.layout.fragment_shelf_botoomsheetdialog);
//给布局设置透明背景色
bottomSheetDialog.getDelegate().findViewById(android.support.design.R.id.design_bottom_sheet)
.setBackgroundColor(getResources().getColor(android.R.color.transparent));
TextView tvTitle = (TextView) bottomSheetDialog.findViewById(R.id.bdTitle);
TextView tvLatestChapt = (TextView) bottomSheetDialog.findViewById(R.id.txtLatestCate);
TextView tvAuthor = (TextView) bottomSheetDialog.findViewById(R.id.tvAuthor);
tvTitle.setText(bookLists.get(position).getName());
if (!bookLists.get(position).isLocalBook()) {
tvAuthor.setText(bookLists.get(position).getAuthor());
TextView tvLatest = (TextView) bottomSheetDialog.findViewById(R.id.txtLatestUpdate);
tvLatestChapt.setText(bookLists.get(position).getChapterName());
tvLatest.setText(CommonUtil.getDateString(bookLists.get(position).getLastUpdateTime()));
} else {
tvLatestChapt.setText("本地导入");
tvAuthor.setText("");
}
ImageView imageView = (ImageView) bottomSheetDialog.findViewById(R.id.imageG1);
ImageUtil.loadImage(activity, bookLists.get(position).getCover(), imageView);
LinearLayout lldetail = (LinearLayout) bottomSheetDialog.findViewById(R.id.llBookdetail);
if (!bookLists.get(position).isLocalBook())
lldetail.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
showBookDetail(bookLists.get(position));
}
});
TextView tvCache = (TextView) bottomSheetDialog.findViewById(R.id.tvCache);
tvCache.setText(FileUtils.getCacheSizeK(bookLists.get(position).getId()));
if (!bookLists.get(position).isLocalBook()) {
LinearLayout llClearCache = (LinearLayout) bottomSheetDialog.findViewById(R.id.llClearCache);
llClearCache.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FileUtils.clearChapterCache(bookLists.get(position).getId());
long size = FileUtils.getCacheSize(bookLists.get(position).getId());
size = size / 1024;
tvCache.setText(String.format("%sK", size));
Toast.makeText(activity, "缓存清除成功", Toast.LENGTH_SHORT);
}
});
} else {
TextView tvClearCache = (TextView) bottomSheetDialog.findViewById(R.id.tvClearCache);
tvClearCache.setText("导入文本");
}
LinearLayout lltop = (LinearLayout) bottomSheetDialog.findViewById(R.id.llTop);
TextView tvTop = (TextView) bottomSheetDialog.findViewById(R.id.tvTop);
ImageView imgTop = (ImageView) bottomSheetDialog.findViewById(R.id.imageTop);
if (bookLists.get(position).isTop()) {
tvTop.setText("取消置顶");
imgTop.setImageResource(R.mipmap.star_inactive);
} else {
tvTop.setText("置顶显示");
imgTop.setImageResource(R.mipmap.star_active);
}
lltop.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (bookLists.get(position).isTop()) {
bookLists.get(position).setToDefault("isTop");
tvTop.setText("置顶显示");
imgTop.setImageResource(R.mipmap.star_active);
} else {
bookLists.get(position).setTop(true);
tvTop.setText("取消置顶");
imgTop.setImageResource(R.mipmap.star_inactive);
}
bookLists.get(position).update(bookLists.get(position).getId());
loadNovelsOnShelf();
mAdapter.setData(bookLists);
//Toast.makeText(activity,"缓存清除成功",Toast.LENGTH_SHORT);
}
});
bottomSheetDialog.show();
}
@BindView(R.id.btnDelete)
Button btnDelete;
@BindView(R.id.btnSelect)
Button btnSelectAll;
@OnClick({R.id.btnSelect, R.id.btnDelete})
void shelfZhengliSubmit(View view) {
if (view.getId() == R.id.btnSelect) {
if (isSelectAll) {
btnSelectAll.setText("全不选");
} else {
btnSelectAll.setText("全选");
}
for (int i = 0; i < flag.length; i++) {
flag[i] = isSelectAll;
}
isSelectAll = !isSelectAll;
mChkAdapter.notifyDataSetChanged();
} else if (view.getId() == R.id.btnDelete) {
boolean isChecked = false;
for(boolean b :flag){
if(b) {
isChecked = true;
break;
}
}
if(!isChecked){
new AlertDialog.Builder(activity)
.setTitle(this.getString(R.string.app_name))
.setMessage( "您还没有选择要移除的书籍")
.setNegativeButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
return;
}
})
.setCancelable(false).show();
return;
}
new AlertDialog.Builder(activity)
.setTitle(this.getString(R.string.app_name))
.setMessage( "您将从书架移除选中的书籍,是否继续?")
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
return;
}
})
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
for (int i = 0; i < bookLists.size(); i++) {
if (flag[i]) {
Novel nv = bookLists.get(i);
if (nv.isLocalBook()) {
nv.delete();
LitePal.deleteAllAsync(Chapter.class, "novelId=?", nv.getId() + "");
//TODO: remove cache on a new thread
FileUtils.clearChapterCache(nv.getId());
} else {
Log.d(TAG, "shelfZhengliSubmit: to delete novel " + nv.getName());
nv.setToDefault("isOnShelf");
nv.setToDefault("isTop");
//nv.setOnShelf(false);
nv.update(nv.getId());
// nv.update(nv.getId()); //not work,,,If you set a default value to a field, the corresponding column won't be updated.
}
// flag = new boolean[bookLists.size()];
// bookLists.remove(i);
}
}
btnSelectAll.setText("全选");
bookLists = Novel.getNovelsOnShelf();
flag = new boolean[bookLists.size()];
zhengliShelf();
initData();
}
})
.setCancelable(false).show();
// List<Integer> toRemove = new ArrayList<Integer>();
/*for (int i = 0; i < bookLists.size(); i++) {
if (flag[i]) {
bookLists.remove(i);
flag[i] =false;
}
}
*/
// mChkAdapter.notifyDataSetChanged();
}
}
private void initZhengliDialog() {
if( flag==null || flag.length ==0 ){
flag= new boolean[bookLists.size()];
}
if( flag==null || flag.length ==0 ){
new AlertDialog.Builder(activity)
.setTitle(this.getString(R.string.app_name))
.setMessage( "您书架上还没有书籍可以整理")
.setNegativeButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
return;
}
})
.setCancelable(false).show();
return;
}
zhengliShelf();
llShelfBottom.setVisibility(View.VISIBLE);
Main2Activity main2Activity = (Main2Activity) activity;
main2Activity.switchShelfZhengli(false);
}
CheckAdapter mChkAdapter;
void zhengliShelf() {
mChkAdapter = new CheckAdapter(activity, bookLists, R.layout.recycle_list_item, new OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
}
@Override
public void onItemLongClick(View view, int position) {
}
@Override
public void onLinearOutClick(View view, int position, int llId) {
}
});
mRecyclerView.setLayoutManager(new GridLayoutManager(activity, 3));
mRecyclerView.setAdapter(mChkAdapter);
}
//--------------------整理 adapter---------------
class CheckAdapter extends RecyclerView.Adapter<CheckAdapter.MyViewHolder> {
private final int EMPTY_VIEW = 1;
private final int PROGRESS_VIEW = 2;
private final int IMAGE_VIEW = 3;
private Context context;
private List<Novel> mDatas = new ArrayList<Novel>();
private OnItemClickListener mOnItemClickListener;
private int listItemID;
public CheckAdapter(Context context, List<Novel> mDatas, int listItemID, OnItemClickListener clickLitener) {
this.context = context;
this.mDatas = mDatas;
this.mOnItemClickListener = clickLitener;
this.listItemID = listItemID;
}
public CheckAdapter(Context context, OnItemClickListener clickLitener) {
this.context = context;
this.mOnItemClickListener = clickLitener;
}
@Override
public int getItemViewType(int position) {
if (mDatas.size() == 0) {
return EMPTY_VIEW;
} else if (mDatas.get(position) == null) {
return PROGRESS_VIEW;
} else {
return super.getItemViewType(position);
}
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder holder = new MyViewHolder(LayoutInflater.from(
context).inflate(listItemID, parent,
false));
return holder;
}
public void setParameters(List<Novel> mDatas, int listItemID) {
this.mDatas = mDatas;
this.listItemID = listItemID;
}
public void setOnItemClickLitener(OnItemClickListener mOnItemClickLitener) {
this.mOnItemClickListener = mOnItemClickLitener;
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.tvTitle.setText(mDatas.get(position).getName());
if (holder.tvAuthor != null) holder.tvAuthor.setText(mDatas.get(position).getAuthor());
if (holder.tvCate != null) holder.tvCate.setText(mDatas.get(position).getNovelType());
if (holder.tvDesc != null) holder.tvDesc.setText(mDatas.get(position).getDesc());
if (holder.checkBox != null) holder.checkBox.setVisibility(View.VISIBLE);
if (holder.imageView != null && !TextUtils.isEmpty(mDatas.get(position).getCover())) {
loader.displayImage(context, NetUtil.getCoverUrl(mDatas.get(position).getCover()), holder.imageView);
}
if (mDatas.get(position).isTop()) {
holder.imageTop.setVisibility(View.VISIBLE);
} else {
holder.imageTop.setVisibility(View.GONE);
}
// 如果设置了回调,则设置点击事件
if (mOnItemClickListener != null) {
holder.checkBox.setOnCheckedChangeListener(null);//先设置一次CheckBox的选中监听器传入参数null
holder.checkBox.setChecked(flag[position]);//用数组中的值设置CheckBox的选中状态
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
holder.checkBox.setChecked(!holder.checkBox.isChecked());
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
return false;
}
});
//再设置一次CheckBox的选中监听器当CheckBox的选中状态发生改变时把改变后的状态储存在数组中
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
flag[position] = b;
}
});
}
}
@Override
public int getItemCount() {
return mDatas.size();
}
public void addData(int position) {
// mDatas.add(position, "Insert One");
notifyItemInserted(position);
}
public void removeData(int position) {
mDatas.remove(position);
notifyItemRemoved(position);
}
class MyViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.id_check_box)
CheckBox checkBox;
@BindView(R.id.imageView)
ImageView imageView;
@BindView(R.id.imageTop)
ImageView imageTop;
@BindView(R.id.title)
TextView tvTitle;
@Nullable
@BindView(R.id.author)
TextView tvAuthor;
@Nullable
@BindView(R.id.category)
TextView tvCate;
@Nullable
@BindView(R.id.desc)
TextView tvDesc;
public MyViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
//tvTitle = (TextView) view.findViewById(R.id.title);
// tvAuthor = (TextView) view.findViewById(R.id.author);
}
}
}
@Override
public void onResume() {
super.onResume();
getUpdatedData();
if (bottomSheetDialog != null) {
bottomSheetDialog.hide();
}
MobclickAgent.onPageStart(TAG);
}
@Override
public void onPause() {
super.onPause();
MobclickAgent.onPageEnd(TAG);
}
//----------toutiao ad
}

View File

@ -0,0 +1,396 @@
package com.novelbook.android.view;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.Scroller;
import android.widget.Toast;
import com.novelbook.android.utils.CommonUtil;
import com.novelbook.android.utils.PageFactory;
import com.novelbook.android.view.animation.AnimationProvider;
import com.novelbook.android.view.animation.CoverAnimation;
import com.novelbook.android.view.animation.NoneAnimation;
import com.novelbook.android.view.animation.SimulationAnimation;
import com.novelbook.android.view.animation.SlideAnimation;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import static com.novelbook.android.utils.Config.*;
public class PageWidget extends View {
private final static String TAG = "BookPageWidget";
private int mScreenWidth = 0; // 屏幕宽
private int mScreenHeight = 0; // 屏幕高
private Context mContext;
//是否移动了
private Boolean isMove = false;
//是否翻到下一页
private Boolean isNext = false;
//是否取消翻页
private Boolean cancelPage = false;
//是否没下一页或者上一页
private Boolean noNext = false;
private int downX = 0;
private int downY = 0;
private int moveX = 0;
private int moveY = 0;
//翻页动画是否在执行
private Boolean isRuning =false;
Bitmap mCurPageBitmap = null; // 当前页
Bitmap mNextPageBitmap = null;
private AnimationProvider mAnimationProvider;
Scroller mScroller;
private int mBgColor = 0xFFCEC29C;
private TouchListener mTouchListener;
public void setActivity(Activity activity) {
this.activity = activity;
}
public void setFrmContainer(FrameLayout frmContainer) {
this.frmContainer = frmContainer;
}
private FrameLayout frmContainer;
private Activity activity;
public PageWidget(Context context) {
this(context,null);
}
public PageWidget(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public PageWidget(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initPage();
mScroller = new Scroller(getContext(),new LinearInterpolator());
mAnimationProvider = new SimulationAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
}
private void initPage(){
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metric = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metric);
mScreenWidth = metric.widthPixels;
// mScreenHeight = metric.heightPixels;
// mScreenHeight = CommonUtil.getDpi(mContext);
mScreenHeight = CommonUtil.getScreenHeight(mContext);
mCurPageBitmap = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.RGB_565); //android:LargeHeap=true use in manifest application
mNextPageBitmap = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.RGB_565);
}
int mPageMode =0;
public void setPageMode(int pageMode){
mPageMode=pageMode;
switch (pageMode){
case PAGE_MODE_SIMULATION:
mAnimationProvider = new SimulationAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_COVER:
mAnimationProvider = new CoverAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_SLIDE:
mAnimationProvider = new SlideAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_NONE:
mAnimationProvider = new NoneAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
default:
mAnimationProvider = new SimulationAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
}
}
/* public void setPageMode2(int pageMode){
switch (pageMode){
case PAGE_MODE_SIMULATION:
mAnimationProvider = new SimulationAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_COVER:
mAnimationProvider = new CoverAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_SLIDE:
mAnimationProvider = new SlideAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_NONE:
mAnimationProvider = new NoneAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
default:
mAnimationProvider = new SimulationAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
}
}
private Bitmap getCurPageBitmap(){
return Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.RGB_565);
}
private Bitmap getNextPageBitmap(){
return mNextPageBitmap;
}*/
public Bitmap getCurPage(){
return mCurPageBitmap;
}
public void setetCurPage(Bitmap bitmap){
// mCurPageBitmap =bitmap;
mAnimationProvider.setetCurPage(bitmap);
}
public void setetNextPage(Bitmap bitmap){
// mCurPageBitmap =bitmap;
mAnimationProvider.setetNextPage(bitmap);
}
public Bitmap getNextPage(){
return mNextPageBitmap;
}
public void setBgColor(int color){
mBgColor = color;
}
@Override
protected void onDraw(Canvas canvas) {
// canvas.drawColor(0xFFAAAAAA);
canvas.drawColor(mBgColor);
Log.e("pagewidget onDraw","isMoveing isNext:" + isNext + " isRuning:" + isRuning);
if (isRuning) {
mAnimationProvider.drawMove(canvas);
} else {
mAnimationProvider.drawStatic(canvas);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
if(!PageFactory.canTouch()){
return true;
}
/* if ( PageFactory.getStatus() != PageFactory.Status.FINISH){
return true;
}*/
int x = (int)event.getX();
int y = (int)event.getY();
Log.d(TAG, String.format("onTouchEvent: x %s,y %s ",x,y));
mAnimationProvider.setTouchPoint(x,y);
if (event.getAction() == MotionEvent.ACTION_DOWN){ //mAnimationProvider.setCancel(false); https://github.com/PeachBlossom/treader/issues/4
downX = (int) event.getX();
downY = (int) event.getY();
moveX = 0;
moveY = 0;
isMove = false;
// cancelPage = false;
noNext = false;
isNext = false;
isRuning = false;
mAnimationProvider.setStartPoint(downX,downY);
abortAnimation();
mAnimationProvider.setCancel(false);
//Log.e(TAG,"ACTION_DOWN");
}else if (event.getAction() == MotionEvent.ACTION_MOVE){
final int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
//判断是否移动了
if (!isMove) {
isMove = Math.abs(downX - x) > slop || Math.abs(downY - y) > slop;
}
Log.d(TAG, String.format("onTouchEvent:ACTION_MOVE isMove %s, isbusy %s",isMove,PageFactory.busy()));
if(!PageFactory.busy())
if (isMove){
isMove = true;
mTouchListener.hideAdBeforeIni() ;
if (moveX == 0 && moveY ==0) {
Log.e(TAG,"isMoveing");
//判断翻得是上一页还是下一页
if (x - downX >0){
isNext = false;
}else{
isNext = true;
}
cancelPage = false;
if (isNext) {
Boolean isNext = mTouchListener.nextPage();
// calcCornerXY(downX,mScreenHeight);
mAnimationProvider.setDirection(AnimationProvider.Direction.next);
if (!isNext) {
noNext = true;
return true;
}
} else {
Boolean isPre = mTouchListener.prePage();
mAnimationProvider.setDirection(AnimationProvider.Direction.pre);
if (!isPre) {
noNext = true;
return true;
}
}
//Log.e(TAG,"isNext:" + isNext);
}else{
//判断是否取消翻页
if(mTouchListener.canCancel()) {
if (isNext) {
if (x - moveX > 0) {
cancelPage = true;
mAnimationProvider.setCancel(true);
} else {
cancelPage = false;
mAnimationProvider.setCancel(false);
}
} else {
if (x - moveX < 0) {
mAnimationProvider.setCancel(true);
cancelPage = true;
} else {
mAnimationProvider.setCancel(false);
cancelPage = false;
}
}
}else{
noNext=true;
}
// if(cancelPage)
//Log.e(TAG,"cancelPage:" + cancelPage);
}
moveX = x;
moveY = y;
isRuning = true;
this.postInvalidate();
}
}else if (event.getAction() == MotionEvent.ACTION_UP){
//Log.e(TAG,"ACTION_UP");
Log.d(TAG, String.format("onTouchEvent:ACTION_UP isMove %s, isbusy %s",isMove,PageFactory.busy()));
if (!isMove || PageFactory.busy()){
cancelPage = false;
//是否点击了中间
if (downX > mScreenWidth / 3 && downX < mScreenWidth * 2 / 3 && downY > mScreenHeight / 3 && downY < mScreenHeight * 2 / 3 ){
if (mTouchListener != null){
mTouchListener.center();
}
//Log.e(TAG,"center");
// mCornerX = 1; // 拖拽点对应的页脚
// mCornerY = 1;
// mTouch.x = 0.1f;
// mTouch.y = 0.1f;
return true;
}
else if (x < mScreenWidth / 2){
isNext = false;
}else{
isNext = true;
}
if (isNext) {
Boolean isNext = mTouchListener.nextPage();
mAnimationProvider.setDirection(AnimationProvider.Direction.next);
if (!isNext) {
return true;
}
} else {
Boolean isPre = mTouchListener.prePage();
mAnimationProvider.setDirection(AnimationProvider.Direction.pre);
if (!isPre) {
return true;
}
}
}
if(!PageFactory.busy()) {
if (cancelPage && mTouchListener != null) {
mTouchListener.cancel();
}
//Log.e(TAG, "isNext:" + isNext);
if (!noNext) {
isRuning = true;
Log.d(TAG, "onTouchEvent: startanimation");
mAnimationProvider.startAnimation(mScroller);
mTouchListener.showAdAfterIni();
this.postInvalidate();
}
}
}
return true;
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
float x = mScroller.getCurrX();
float y = mScroller.getCurrY();
mAnimationProvider.setTouchPoint(x,y);
if (mScroller.getFinalX() == x && mScroller.getFinalY() == y){
isRuning = false;
}
postInvalidate();
}
super.computeScroll();
}
public void abortAnimation() {
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
mAnimationProvider.setTouchPoint(mScroller.getFinalX(),mScroller.getFinalY());
postInvalidate();
}
}
public boolean isRunning(){
return isRuning;
}
public void setTouchListener(TouchListener mTouchListener){
this.mTouchListener = mTouchListener;
}
public interface TouchListener{
void center();
Boolean prePage();
Boolean nextPage();
void cancel();
Boolean canCancel();
void showAdAfterIni();
void hideAdBeforeIni();
}
}

View File

@ -0,0 +1,12 @@
<component name="libraryTable">
<library name="Gradle: com.github.bumptech.glide:glide:4.9.0@aar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/glide-4.9.0.aar/fb068771db043abe18998bdf8de08944/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/glide-4.9.0.aar/fb068771db043abe18998bdf8de08944/res" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.bumptech.glide/glide/4.9.0/5f95e3cc34b116a8024f2af42f66e257d2e28ccb/glide-4.9.0-sources.jar!/" />
</SOURCES>
</library>
</component>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<dbname value="book" ></dbname>
<version value="18" ></version>
<list>
<mapping class="com.novelbook.android.db.Chapter"></mapping>
<mapping class="com.novelbook.android.db.Novel"></mapping>
<mapping class="com.novelbook.android.db.BookMarks"></mapping>
<mapping class="com.novelbook.android.db.SiteRule"></mapping>
<mapping class="com.novelbook.android.db.DownloadTask"></mapping>
</list>
</litepal>

View File

@ -0,0 +1,11 @@
<component name="libraryTable">
<library name="Gradle: com.squareup.okio:okio:1.17.2@jar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup.okio/okio/1.17.2/78c7820b205002da4d2d137f6f312bd64b3d6049/okio-1.17.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.squareup.okio/okio/1.17.2/331ecaeba2fd87c06a0766e8ebe718e1e294f27d/okio-1.17.2-sources.jar!/" />
</SOURCES>
</library>
</component>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,357 @@
package com.novelbook.android.db;
import android.text.TextUtils;
import android.util.Log;
import com.novelbook.android.utils.Constants;
import org.litepal.LitePal;
import org.litepal.annotation.Column;
import org.litepal.crud.LitePalSupport;
import org.w3c.dom.Text;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
public class Novel extends LitePalSupport implements Serializable{
private int id;
//@Column(unique = true, defaultValue = "0")
private int novelId;
private String name;
private String infoUrl;
private String domain;
private String domainName;
private String muluUrl;
private String novelPath;
private long lastReadPos;
private int lastReadChapt=1;
private String charset;
private String novelType;
private String smallNovelType;
private String author;
private String cover;
private String chapterName;
private String desc;
private String progress;
private long lastUpdateTime;
private boolean isOnShelf; //是否入书架
private boolean isFinished; //是否完本
private boolean isUpdated;
private boolean isTop;//置顶
private long readtime; //阅读时间
private int chaptCnt; //总章数
private long lastVisit;//最近浏览,如何设置默认时间?
public int getChaptCnt() {
return chaptCnt;
}
public void setChaptCnt(int chaptCnt) {
this.chaptCnt = chaptCnt;
}
public long getReadtime() {
return readtime;
}
public void setReadtime(long readtime) {
this.readtime = readtime;
}
public String getDomainName() {
return domainName;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public long getLastVisit() {
return lastVisit;
}
public void setLastVisit(long lastVisit) {
this.lastVisit = lastVisit;
}
public boolean isTop() {
return isTop;
}
public void setTop(boolean top) {
isTop = top;
}
public boolean isUpdated() {
return isUpdated;
}
public void setUpdated(boolean updated) {
isUpdated = updated;
}
public String getInfoUrl() {
return infoUrl;
}
public void setInfoUrl(String infoUrl) {
this.infoUrl = infoUrl;
}
public String getSmallNovelType() {
return smallNovelType;
}
public void setSmallNovelType(String smallNovelType) {
this.smallNovelType = smallNovelType;
}
public String getChapterName() {
return chapterName;
}
public void setChapterName(String chapterName) {
this.chapterName = chapterName;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getProgress() {
return progress;
}
public void setProgress(String progress) {
this.progress = progress;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getNovelId() {
return novelId;
}
public void setNovelId(int novelId) {
this.novelId = novelId;
}
public String getName() {
return name;
}
public void setName(String novelName) {
this.name = novelName;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getMuluUrl() {
return muluUrl;
}
public void setMuluUrl(String muluUrl) {
this.muluUrl = muluUrl;
}
public String getNovelPath() {
return novelPath;
}
public void setNovelPath(String novelPath) {
this.novelPath = novelPath;
}
public long getLastReadPos() {
return lastReadPos;
}
public void setLastReadPos(long lastReadPos) {
this.lastReadPos = lastReadPos;
}
public int getLastReadChapt() {
// if(lastReadChapt<=0){lastReadChapt=1;}
return lastReadChapt;
}
public void setLastReadChapt(int lastReadChapt) {
// lastReadChapt = lastReadChapt >0 ? lastReadChapt :1;
this.lastReadChapt = lastReadChapt;
}
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
public String getNovelType() {
return novelType;
}
public void setNovelType(String novelType) {
this.novelType = novelType;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getCover() {
return cover;
}
public void setCover(String cover) {
this.cover = cover;
}
public long getLastUpdateTime() {
return lastUpdateTime;
}
public void setLastUpdateTime(long lastUpateTime) {
this.lastUpdateTime = lastUpateTime;
}
public boolean isOnShelf() {
return isOnShelf;
}
public void setOnShelf(boolean onShelf) {
isOnShelf = onShelf;
}
public boolean isFinished() {
return isFinished;
}
public void setFinished(boolean finished) {
isFinished = finished;
}
public boolean isLocalBook(){
return novelId==0;
}
public static Novel getNovelBySvrId(int novelId){
List<Novel> nvs = LitePal.where("novelId=?",novelId+"").limit(1).find(Novel.class);
if(nvs.size()>0){
return nvs.get(0);
}
return null;
}
public static List<Novel> getNovelsOnShelf(){
// return LitePal.where("isOnShelf=?","1").order("isTop desc,isUpdated desc,lastVisit desc,lastUpdateTime desc" ).find(Novel.class);
return LitePal.where("isOnShelf=?","1").order("isTop desc,lastUpdateTime desc" ).find(Novel.class);
}
public static List<Novel> getLocalNovels(){
return LitePal.where("novelPath !=? ","").find(Novel.class);
}
public static List<Novel> getNovelsHistory(){
return LitePal.where("lastVisit>0").order("lastVisit desc").limit(50).find(Novel.class);
}
/**
* 有没有新的更新
* @return
*/
/* public boolean isUpdated(){
return lastUpdateTime2 >0 && lastUpdateTime > lastUpdateTime2;
}
*/
private void setValues(){
lastVisit = new Date().getTime();
}
@Override
public boolean save(){
setValues();
return super.save();
}
@Override
public int update(long id){
setValues();
checkAndUpdate();
Log.d("checkshelf", String.format("checkshelf:novel %s going to update,isUpdated %s", getName() ,isUpdated));
/* try {
throw new Exception("check update");
}catch (Exception e){
Log.e("checkshelf", "checkshelf ", e);
}*/
try {
return super.update(id);
}catch (Exception e){
Log.e("NOVELDB", "update:error ", e);
}
return 0;
}
public void testUpdate(){
isUpdated=true;
super.update(id);
}
public int checkAndUpdate(){
Novel nv = getNovelBySvrId(novelId);
/* if(lastUpdateTime > nv.lastVisit && lastUpdateTime > nv.lastUpdateTime){
isUpdated =true;
}*/
isUpdated =lastUpdateTime > nv.lastVisit || lastUpdateTime > nv.lastUpdateTime;
Log.d("Novel", String.format("book %s server lastUpdateTime %s, local lastupdatetime %s, local lastvist %s" +
"is updated %s,diff1 %s,diff2 %s"
,name ,lastUpdateTime,nv.lastUpdateTime,nv.lastVisit,isUpdated,
lastUpdateTime - nv.lastVisit,
lastUpdateTime - nv.lastUpdateTime) );
if(!isUpdated){
setToDefault("isUpdated");
}
return super.update(nv.id);
}
public int getMaxAge(){
int maxAge = Constants.MAXAGE_MULU;
if( isFinished){
maxAge =Constants.MAXAGE_MAX;
}else if(isUpdated){
maxAge = 0;
}
return maxAge; // return 0;// maxAge;
}
}

View File

@ -0,0 +1,391 @@
package com.novelbook.android.db;
import android.text.TextUtils;
import android.util.Log;
import com.novelbook.android.utils.CommonUtil;
import com.novelbook.android.utils.Constants;
import org.litepal.LitePal;
import org.litepal.annotation.Column;
import org.litepal.crud.LitePalSupport;
import org.w3c.dom.Text;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
public class Novel extends LitePalSupport implements Serializable{
private int id;
//@Column(unique = true, defaultValue = "0")
private int novelId;
private String name;
private String infoUrl;
private String domain;
private String domainName;
private String muluUrl;
private String novelPath;
private long lastReadPos;
private int lastReadChapt=1;
private String charset;
private String novelType;
private String smallNovelType;
private String author;
private String cover;
private String chapterName;
private String desc;
private String progress;
private long lastUpdateTime;
private boolean isOnShelf; //是否入书架
private boolean isFinished; //是否完本
private boolean isUpdated;
private boolean isTop;//置顶
private long readtime; //阅读时间
private int chaptCnt; //总章数
private long lastVisit;//最近浏览,如何设置默认时间?
private String lastReadChaptName;
public int getChaptCnt() {
return chaptCnt;
}
public void setChaptCnt(int chaptCnt) {
this.chaptCnt = chaptCnt;
}
public long getReadtime() {
return readtime;
}
public void setReadtime(long readtime) {
this.readtime = readtime;
}
public String getDomainName() {
return domainName;
}
public void setDomainName(String domainName) {
this.domainName = domainName;
}
public long getLastVisit() {
return lastVisit;
}
public void setLastVisit(long lastVisit) {
this.lastVisit = lastVisit;
}
public boolean isTop() {
return isTop;
}
public void setTop(boolean top) {
isTop = top;
}
public boolean isUpdated() {
return isUpdated;
}
public void setUpdated(boolean updated) {
isUpdated = updated;
}
public String getInfoUrl() {
return infoUrl;
}
public void setInfoUrl(String infoUrl) {
this.infoUrl = infoUrl;
}
public String getSmallNovelType() {
return smallNovelType;
}
public void setSmallNovelType(String smallNovelType) {
this.smallNovelType = smallNovelType;
}
public String getChapterName() {
return chapterName;
}
public void setChapterName(String chapterName) {
this.chapterName = chapterName;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getProgress() {
return progress;
}
public void setProgress(String progress) {
this.progress = progress;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getNovelId() {
return novelId;
}
public void setNovelId(int novelId) {
this.novelId = novelId;
}
public String getName() {
return name;
}
public void setName(String novelName) {
this.name = novelName;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getMuluUrl() {
return muluUrl;
}
public void setMuluUrl(String muluUrl) {
this.muluUrl = muluUrl;
}
public String getNovelPath() {
return novelPath;
}
public void setNovelPath(String novelPath) {
this.novelPath = novelPath;
}
public long getLastReadPos() {
return lastReadPos;
}
public void setLastReadPos(long lastReadPos) {
this.lastReadPos = lastReadPos;
}
public int getLastReadChapt() {
// if(lastReadChapt<=0){lastReadChapt=1;}
return lastReadChapt;
}
public void setLastReadChapt(int lastReadChapt) {
// lastReadChapt = lastReadChapt >0 ? lastReadChapt :1;
this.lastReadChapt = lastReadChapt;
}
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
public String getNovelType() {
return novelType;
}
public void setNovelType(String novelType) {
this.novelType = novelType;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getCover() {
return cover;
}
public void setCover(String cover) {
this.cover = cover;
}
public long getLastUpdateTime() {
return lastUpdateTime;
}
public void setLastUpdateTime(long lastUpateTime) {
this.lastUpdateTime = lastUpateTime;
}
public boolean isOnShelf() {
return isOnShelf;
}
public void setOnShelf(boolean onShelf) {
isOnShelf = onShelf;
}
public boolean isFinished() {
return isFinished;
}
public void setFinished(boolean finished) {
isFinished = finished;
}
public boolean isLocalBook(){
return novelId==0;
}
public static Novel getNovelBySvrId(int novelId){
List<Novel> nvs = LitePal.where("novelId=?",novelId+"").limit(1).find(Novel.class);
if(nvs.size()>0){
return nvs.get(0);
}
return null;
}
public static List<Novel> getNovelsOnShelf(){
// return LitePal.where("isOnShelf=?","1").order("isTop desc,isUpdated desc,lastVisit desc,lastUpdateTime desc" ).find(Novel.class);
return LitePal.where("isOnShelf=?","1").order("isTop desc,lastUpdateTime desc" ).find(Novel.class);
}
public static List<Novel> getLocalNovels(){
return LitePal.where("novelPath !=? ","").find(Novel.class);
}
public static List<Novel> getNovelsHistory(){
return LitePal.where("lastVisit>0").order("lastVisit desc").limit(50).find(Novel.class);
}
/**
* 有没有新的更新
* @return
*/
/* public boolean isUpdated(){
return lastUpdateTime2 >0 && lastUpdateTime > lastUpdateTime2;
}
*/
private void setValues(){
lastVisit = new Date().getTime();
}
@Override
public boolean save(){
setValues();
return super.save();
}
@Override
public int update(long id){
setValues();
// checkAndUpdate();
Log.d("checkshelf", String.format("checkshelf:novel %s going to update,isUpdated %s,lastvist %s", getName() ,isUpdated, CommonUtil.getDateString(lastVisit )));
/* try {
throw new Exception("check update");
}catch (Exception e){
Log.e("checkshelf", "checkshelf ", e);
}*/
try {
return super.update(id);
}catch (Exception e){
Log.e("NOVELDB", "update:error ", e);
}
return 0;
}
public void testUpdate(){
isUpdated=true;
super.update(id);
}
public int checkAndUpdate(){
Novel nv = getNovelBySvrId(novelId);
if(nv==null){
return 0;
}
/* if(lastUpdateTime > nv.lastVisit && lastUpdateTime > nv.lastUpdateTime){
isUpdated =true;
}*/
// isUpdated = lastUpdateTime > nv.lastVisit && lastUpdateTime > nv.lastUpdateTime;
isUpdated = lastUpdateTime > nv.lastUpdateTime;
Log.d("Novel", String.format("book %s server lastUpdateTime %s, local lastupdatetime %s, local lastvist %s," +
"is updated %s, lastUpdateTime - nv.lastVisit %s,lastUpdateTime - nv.lastUpdateTime %s "
,name ,CommonUtil.getDateString(lastUpdateTime) ,CommonUtil.getDateString(nv.lastUpdateTime) ,CommonUtil.getDateString(nv.lastVisit) ,isUpdated,
lastUpdateTime - nv.lastVisit,
lastUpdateTime - nv.lastUpdateTime
) );
boolean isLastReadchaptUpdated = TextUtils.isEmpty(nv.lastReadChaptName) || !(chapterName.equals(nv.lastReadChaptName)); //没看过最新章节
boolean isLastChaptUpdated = !TextUtils.isEmpty(chapterName) && !TextUtils.isEmpty(nv.chapterName) && !(chapterName.equals(nv.chapterName));
Log.d("Novel", String.format( " server lastUpdateTime ,server chaptername %s,chaptername %s,lastreadchapt %s" , chapterName,nv.chapterName,nv.lastReadChaptName ) );
/*
isUpdated = isUpdated && isLastReadchaptUpdated || isLastChaptUpdated ;
boolean isLastChaptUpdated = !TextUtils.isEmpty(chapterName) && !TextUtils.isEmpty(nv.chapterName) && !(chapterName.equals(nv.chapterName));
*/
Log.d("Novel", String.format( " isupdated %s, server lastUpdateTime isLastReadchaptUpdated %s,isLastChaptUpdated %s" ,isUpdated,isLastReadchaptUpdated,isLastChaptUpdated ) );
Log.d("Novel", String.format( " server lastUpdateTime ,server chaptername %s,chaptername %s,lastreadchapt %s" , chapterName,nv.chapterName,nv.lastReadChaptName ) );
isUpdated = isUpdated && isLastChaptUpdated || lastUpdateTime > nv.lastVisit;
isUpdated = isUpdated && isLastReadchaptUpdated;
if(!isUpdated){
setToDefault("isUpdated");
}
return super.update(nv.id);
}
public int getMaxAge(){
int maxAge = Constants.MAXAGE_MULU;
if( isFinished){
maxAge =Constants.MAXAGE_MAX;
}else if(isUpdated){
maxAge = 0;
}
return maxAge; // return 0;// maxAge;
}
public String getLastReadChaptName() {
return lastReadChaptName;
}
public void setLastReadChaptName(String lastReadChaptName) {
this.lastReadChaptName = lastReadChaptName;
}
}

View File

@ -0,0 +1,396 @@
package com.novelbook.android.view;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Environment;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.animation.LinearInterpolator;
import android.widget.FrameLayout;
import android.widget.Scroller;
import android.widget.Toast;
import com.novelbook.android.utils.CommonUtil;
import com.novelbook.android.utils.PageFactory;
import com.novelbook.android.view.animation.AnimationProvider;
import com.novelbook.android.view.animation.CoverAnimation;
import com.novelbook.android.view.animation.NoneAnimation;
import com.novelbook.android.view.animation.SimulationAnimation;
import com.novelbook.android.view.animation.SlideAnimation;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import static com.novelbook.android.utils.Config.*;
public class PageWidget extends View {
private final static String TAG = "BookPageWidget";
private int mScreenWidth = 0; // 屏幕宽
private int mScreenHeight = 0; // 屏幕高
private Context mContext;
//是否移动了
private Boolean isMove = false;
//是否翻到下一页
private Boolean isNext = false;
//是否取消翻页
private Boolean cancelPage = false;
//是否没下一页或者上一页
private Boolean noNext = false;
private int downX = 0;
private int downY = 0;
private int moveX = 0;
private int moveY = 0;
//翻页动画是否在执行
private Boolean isRuning =false;
Bitmap mCurPageBitmap = null; // 当前页
Bitmap mNextPageBitmap = null;
private AnimationProvider mAnimationProvider;
Scroller mScroller;
private int mBgColor = 0xFFCEC29C;
private TouchListener mTouchListener;
public void setActivity(Activity activity) {
this.activity = activity;
}
public void setFrmContainer(FrameLayout frmContainer) {
this.frmContainer = frmContainer;
}
private FrameLayout frmContainer;
private Activity activity;
public PageWidget(Context context) {
this(context,null);
}
public PageWidget(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public PageWidget(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initPage();
mScroller = new Scroller(getContext(),new LinearInterpolator());
mAnimationProvider = new SimulationAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
}
private void initPage(){
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metric = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metric);
mScreenWidth = metric.widthPixels;
// mScreenHeight = metric.heightPixels;
// mScreenHeight = CommonUtil.getDpi(mContext);
mScreenHeight = CommonUtil.getScreenHeight(mContext);
mCurPageBitmap = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.RGB_565); //android:LargeHeap=true use in manifest application
mNextPageBitmap = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.RGB_565);
}
int mPageMode =0;
public void setPageMode(int pageMode){
mPageMode=pageMode;
switch (pageMode){
case PAGE_MODE_SIMULATION:
mAnimationProvider = new SimulationAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_COVER:
mAnimationProvider = new CoverAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_SLIDE:
mAnimationProvider = new SlideAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_NONE:
mAnimationProvider = new NoneAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
default:
mAnimationProvider = new SimulationAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
}
}
/* public void setPageMode2(int pageMode){
switch (pageMode){
case PAGE_MODE_SIMULATION:
mAnimationProvider = new SimulationAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_COVER:
mAnimationProvider = new CoverAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_SLIDE:
mAnimationProvider = new SlideAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
case PAGE_MODE_NONE:
mAnimationProvider = new NoneAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
break;
default:
mAnimationProvider = new SimulationAnimation(mCurPageBitmap,mNextPageBitmap,mScreenWidth,mScreenHeight);
}
}
private Bitmap getCurPageBitmap(){
return Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.RGB_565);
}
private Bitmap getNextPageBitmap(){
return mNextPageBitmap;
}*/
public Bitmap getCurPage(){
return mCurPageBitmap;
}
public void setetCurPage(Bitmap bitmap){
// mCurPageBitmap =bitmap;
mAnimationProvider.setetCurPage(bitmap);
}
public void setetNextPage(Bitmap bitmap){
// mCurPageBitmap =bitmap;
mAnimationProvider.setetNextPage(bitmap);
}
public Bitmap getNextPage(){
return mNextPageBitmap;
}
public void setBgColor(int color){
mBgColor = color;
}
@Override
protected void onDraw(Canvas canvas) {
// canvas.drawColor(0xFFAAAAAA);
canvas.drawColor(mBgColor);
// Log.e("pagewidget onDraw","isMoveing isNext:" + isNext + " isRuning:" + isRuning);
if (isRuning) {
mAnimationProvider.drawMove(canvas);
} else {
mAnimationProvider.drawStatic(canvas);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
if(!PageFactory.canTouch()){
return true;
}
/* if ( PageFactory.getStatus() != PageFactory.Status.FINISH){
return true;
}*/
int x = (int)event.getX();
int y = (int)event.getY();
// Log.d(TAG, String.format("onTouchEvent: x %s,y %s ",x,y));
mAnimationProvider.setTouchPoint(x,y);
if (event.getAction() == MotionEvent.ACTION_DOWN){ //mAnimationProvider.setCancel(false); https://github.com/PeachBlossom/treader/issues/4
downX = (int) event.getX();
downY = (int) event.getY();
moveX = 0;
moveY = 0;
isMove = false;
// cancelPage = false;
noNext = false;
isNext = false;
isRuning = false;
mAnimationProvider.setStartPoint(downX,downY);
abortAnimation();
mAnimationProvider.setCancel(false);
//Log.e(TAG,"ACTION_DOWN");
}else if (event.getAction() == MotionEvent.ACTION_MOVE){
final int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
//判断是否移动了
if (!isMove) {
isMove = Math.abs(downX - x) > slop || Math.abs(downY - y) > slop;
}
// Log.d(TAG, String.format("onTouchEvent:ACTION_MOVE isMove %s, isbusy %s",isMove,PageFactory.busy()));
if(!PageFactory.busy())
if (isMove){
isMove = true;
mTouchListener.hideAdBeforeIni() ;
if (moveX == 0 && moveY ==0) {
Log.e(TAG,"isMoveing");
//判断翻得是上一页还是下一页
if (x - downX >0){
isNext = false;
}else{
isNext = true;
}
cancelPage = false;
if (isNext) {
Boolean isNext = mTouchListener.nextPage();
// calcCornerXY(downX,mScreenHeight);
mAnimationProvider.setDirection(AnimationProvider.Direction.next);
if (!isNext) {
noNext = true;
return true;
}
} else {
Boolean isPre = mTouchListener.prePage();
mAnimationProvider.setDirection(AnimationProvider.Direction.pre);
if (!isPre) {
noNext = true;
return true;
}
}
//Log.e(TAG,"isNext:" + isNext);
}else{
//判断是否取消翻页
if(mTouchListener.canCancel()) {
if (isNext) {
if (x - moveX > 0) {
cancelPage = true;
mAnimationProvider.setCancel(true);
} else {
cancelPage = false;
mAnimationProvider.setCancel(false);
}
} else {
if (x - moveX < 0) {
mAnimationProvider.setCancel(true);
cancelPage = true;
} else {
mAnimationProvider.setCancel(false);
cancelPage = false;
}
}
}else{
noNext=true;
}
// if(cancelPage)
//Log.e(TAG,"cancelPage:" + cancelPage);
}
moveX = x;
moveY = y;
isRuning = true;
this.postInvalidate();
}
}else if (event.getAction() == MotionEvent.ACTION_UP){
//Log.e(TAG,"ACTION_UP");
// Log.d(TAG, String.format("onTouchEvent:ACTION_UP isMove %s, isbusy %s",isMove,PageFactory.busy()));
if (!isMove || PageFactory.busy()){
cancelPage = false;
//是否点击了中间
if (downX > mScreenWidth / 3 && downX < mScreenWidth * 2 / 3 && downY > mScreenHeight / 3 && downY < mScreenHeight * 2 / 3 ){
if (mTouchListener != null){
mTouchListener.center();
}
//Log.e(TAG,"center");
// mCornerX = 1; // 拖拽点对应的页脚
// mCornerY = 1;
// mTouch.x = 0.1f;
// mTouch.y = 0.1f;
return true;
}
else if (x < mScreenWidth / 2){
isNext = false;
}else{
isNext = true;
}
if (isNext) {
Boolean isNext = mTouchListener.nextPage();
mAnimationProvider.setDirection(AnimationProvider.Direction.next);
if (!isNext) {
return true;
}
} else {
Boolean isPre = mTouchListener.prePage();
mAnimationProvider.setDirection(AnimationProvider.Direction.pre);
if (!isPre) {
return true;
}
}
}
if(!PageFactory.busy()) {
if (cancelPage && mTouchListener != null) {
mTouchListener.cancel();
}
//Log.e(TAG, "isNext:" + isNext);
if (!noNext) {
isRuning = true;
// Log.d(TAG, "onTouchEvent: startanimation");
mAnimationProvider.startAnimation(mScroller);
mTouchListener.showAdAfterIni();
this.postInvalidate();
}
}
}
return true;
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
float x = mScroller.getCurrX();
float y = mScroller.getCurrY();
mAnimationProvider.setTouchPoint(x,y);
if (mScroller.getFinalX() == x && mScroller.getFinalY() == y){
isRuning = false;
}
postInvalidate();
}
super.computeScroll();
}
public void abortAnimation() {
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
mAnimationProvider.setTouchPoint(mScroller.getFinalX(),mScroller.getFinalY());
postInvalidate();
}
}
public boolean isRunning(){
return isRuning;
}
public void setTouchListener(TouchListener mTouchListener){
this.mTouchListener = mTouchListener;
}
public interface TouchListener{
void center();
Boolean prePage();
Boolean nextPage();
void cancel();
Boolean canCancel();
void showAdAfterIni();
void hideAdBeforeIni();
}
}

View File

@ -0,0 +1,82 @@
package com.novelbook.android.db;
import org.litepal.crud.LitePalSupport;
public class BookMarks extends LitePalSupport {
private int id ;
// private int page;
private int chapt;
private String chaptName;
private long begin; // 书签记录页面的结束点位置
// private int count;
private String text;
private String time;
private int novelId;
private String domain;
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getText() {
return this.text;
}
public void setText(String text) {
this.text = text;
}
public String getTime() {
return this.time;
}
public void setTime(String time) {
this.time = time;
}
public long getBegin() {
return this.begin;
}
public void setBegin(long begin) {
this.begin = begin;
}
public int getNovelId() {
return this.novelId;
}
public void setNovelId(int novelId ) {
this.novelId = novelId;
}
public String getChaptName() {
return chaptName;
}
public void setChaptName(String chaptName) {
this.chaptName = chaptName;
}
public int getChapt() {
return chapt;
}
public void setChapt(int chapt) {
this.chapt = chapt;
}
}

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M6,7h2.5L5,3.5 1.5,7L4,7v10L1.5,17L5,20.5 8.5,17L6,17L6,7zM10,5v2h12L22,5L10,5zM10,19h12v-2L10,17v2zM10,13h12v-2L10,11v2z"/>
</vector>

View File

@ -0,0 +1,446 @@
package com.novelbook.android;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
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.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.novelbook.android.Activity_base;
import com.novelbook.android.R;
import com.novelbook.android.adapter.BookListAdapter;
import com.novelbook.android.bean.Cataloge;
import com.novelbook.android.db.Chapter;
import com.novelbook.android.db.DownloadTask;
import com.novelbook.android.db.Novel;
import com.novelbook.android.service.ServiceDownload;
import com.novelbook.android.utils.FileUtils;
import com.novelbook.android.utils.Fileutil;
import com.novelbook.android.utils.ImageUtil;
import org.litepal.LitePal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
public class Activity_cache extends Activity_base {
public static final String TAG=Activity_cache.class.getSimpleName();
@BindView(R.id.recycleView)
RecyclerView mRecyclerView;
@BindView(R.id.tvMsg)
TextView tvMsg;
private List<DownloadTask> mData;
private CacheAdapter mAdapter;
// private String cacheSize;
@Override
public int getLayoutRes() {
return R.layout.activitycache;
}
@Override
protected void initViews() {
}
@Override
protected void setTitle() {
}
@Override
protected void initData() {
initiDownloadReceiver();
showProgressDialog(true,"正在加载...");
new Thread() {
@Override
public void run() {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
mData = LitePal.where("id >0").order("id desc").find(DownloadTask.class);//findAll(DownloadTask.class);
//cacheSize = FileUtils.getCachedSize();
/* mData.sort(new Comparator<DownloadTask>(){
public int compare(DownloadTask arg0, DownloadTask arg1) {
int i = arg0.getFinishedChpats()/arg0.getTotalChapts() > arg1.getFinishedChpats()/arg1.getTotalChapts() ?1:-1;
return i; }});*/
// }
handler.sendEmptyMessage(1);
}
}.start();
}
@Override
public void fillData() {
mAdapter = new CacheAdapter(this,mData,R.layout.recycle_list_item_cache,new OnItemClickLitener() {
@Override
public void onItemClick(View view, int position) {
Novel novel = LitePal.find(Novel.class,mData.get(position).getNovelId());
showBookDetail(novel);
}
@Override
public void onItemLongClick(View view, int position)
{
final AlertDialog.Builder normalDialog =
new AlertDialog.Builder(Activity_cache.this);
normalDialog.setTitle("删除此下载任务并清除缓存吗");
normalDialog.setMessage("确定删除吗?");
normalDialog.setPositiveButton("取消",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
normalDialog.setNegativeButton("删除",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
DownloadTask cl = mData.get(position);
cl.delete();
// Chapter.deleteByTask();
//TODO:clear cache ?
mAdapter.removeData(position);
}
});
normalDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
}
});
// 显示
normalDialog.show();
// mAdapter.removeData(position);
}
});
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setAdapter(mAdapter );
if( mData.size()>0){
tvMsg.setText(String.format("共有%s条下载记录",mData.size()));
}else{
tvMsg.setText(R.string.noRecord);
}
}
private IntentFilter filter;
DownloadProcessReceiver receiver;
void initiDownloadReceiver(){
filter = new IntentFilter("ServiceDownload.ChapterContent.finished");
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new DownloadProcessReceiver();
}
class DownloadProcessReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent){
int taskId =0;
int progress=0;
int status=0;
// tvMsg.setVisibility(View.GONE);
if( intent.hasExtra("network")){
String txt = intent.getStringExtra("network");
tvMsg.setText(txt);
tvMsg.setVisibility(View.VISIBLE);
return;
}
if( intent.hasExtra("progress")){
progress = intent.getIntExtra("progress",0);
}
if( intent.hasExtra("taskId")){
taskId = intent.getIntExtra("taskId",0);
}
if( intent.hasExtra("status")){
status = intent.getIntExtra("status",0);
}
Log.d(TAG, String.format("onReceive: taskId %s progress %s ",taskId,progress));
for(DownloadTask dt : mData){
if(taskId == dt.getId()){
dt.setFinishedChpats(progress);
if(status==1){
dt.setStatus(1);
dt.setDownSatus(DownloadTask.DownStatus.下载完成);
}else
if(dt.getDownSatus()!=DownloadTask.DownStatus.暂停下载) {
dt.setDownSatus(DownloadTask.DownStatus.正在下载);
dt.setStatus(0);
}
// dt = LitePal.find(DownloadTask.class,taskId);
}else{
if(dt.getDownSatus()==DownloadTask.DownStatus.正在下载) {
dt.setDownSatus(DownloadTask.DownStatus.排队中);
}
}
}
mAdapter.setData(mData);
}
}
private void startDownloadService(int taskId,boolean start) {
Intent serviceIntent = new Intent(this, ServiceDownload.class);
serviceIntent.putExtra("taskId",taskId);
serviceIntent.putExtra("start",start);
startService(serviceIntent);
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(receiver, filter);
}
@Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
class CacheAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int EMPTY_VIEW = 1;
private final int PROGRESS_VIEW = 2;
private final int IMAGE_VIEW = 3;
private Context context;
private List<DownloadTask> mDatas = new ArrayList<DownloadTask>();
private OnItemClickLitener mOnItemClickLitener;
private int listItemID;
// private String norecord ="还没有下载记录";
public CacheAdapter(Context context, List<DownloadTask> mDatas, int listItemID, OnItemClickLitener clickLitener) {
this.context = context;
this.mDatas = mDatas;
this.mOnItemClickLitener = clickLitener;
this.listItemID = listItemID;
}
public CacheAdapter(Context context, OnItemClickLitener clickLitener) {
this.context = context;
this.mOnItemClickLitener = clickLitener;
}
@Override
public int getItemViewType(int position) {
if (mDatas.size() == 0) {
return EMPTY_VIEW;
} else if (mDatas.get(position) == null) {
return PROGRESS_VIEW;
} else {
return super.getItemViewType(position);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType == EMPTY_VIEW){
EmptyViewHolder holder = new EmptyViewHolder (LayoutInflater.from(context).inflate(R.layout.recycle_list_empty_item, parent, false));
return holder;
}
CacheAdapter.MyViewHolder holder = new CacheAdapter.MyViewHolder(LayoutInflater.from(
context).inflate(listItemID, parent,
false));
return holder;
}
public void setParameters(List<DownloadTask> mDatas, int listItemID) {
this.mDatas = mDatas;
this.listItemID = listItemID;
}
public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) {
this.mOnItemClickLitener = mOnItemClickLitener;
}
@Override
public void onBindViewHolder( RecyclerView.ViewHolder hd, int position) {
if (hd instanceof EmptyViewHolder) {
EmptyViewHolder holder = ( EmptyViewHolder)hd;
holder.tvEmpty.setVisibility(View.VISIBLE);
holder.tvEmpty.setText(R.string.noRecord);
return;
}
MyViewHolder holder = ( MyViewHolder)hd;
holder.tvTitle.setText(mDatas.get(position).getNovelTitle());
holder.tvSource.setText(mDatas.get(position).getDomainName());
boolean finished = mData.get(position).getFinishedChpats() == mData.get(position).getTotalChapts();
holder.tvSize.setText( FileUtils.getCacheSizeK(mData.get(position).getNovelId()));
if( mData.get(position).getTotalChapts() >0) {
float progress = mData.get(position).getFinishedChpats() * 100 / mData.get(position).getTotalChapts();
holder.tvProgress.setText(String.format("%s/%s", mData.get(position).getFinishedChpats() > mData.get(position).getTotalChapts() ? mData.get(position).getTotalChapts() : mData.get(position).getFinishedChpats(), mData.get(position).getTotalChapts()));
holder.barProgress.setProgress((int) progress);
holder.tvStatus.setText(mData.get(position).getDownSatus() == DownloadTask.DownStatus.正在下载 ? "正在下载"
: mData.get(position).getDownSatus() == DownloadTask.DownStatus.暂停下载 ? "暂停下载" : "休眠中");
holder.tvStatus.setText(mData.get(position).getStatus() == 1 || mData.get(position).getFinishedChpats() >= mData.get(position).getTotalChapts()
? "下载完成" : holder.tvStatus.getText());
holder.tvStatus.setText(mData.get(position).getDownSatus() == DownloadTask.DownStatus.排队中 ? "排队中" : holder.tvStatus.getText());
int img = R.mipmap.play;
img = mData.get(position).getDownSatus() == DownloadTask.DownStatus.正在下载 ? R.mipmap.pause : R.mipmap.play;
holder.imgStart.setImageResource(img);
holder.imgStart.setEnabled(true);
if (mData.get(position).getStatus() == 1 || mData.get(position).getFinishedChpats() >= mData.get(position).getTotalChapts()) {
holder.tvStatus.setText("下载完成");
holder.imgStart.setEnabled(false);
holder.imgStart.setImageResource(R.mipmap.pause);
}
}
// holder.imgStart.setVisibility(View.GONE);
holder.imgStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = holder.getLayoutPosition();
if(mData.get(position).getDownSatus() != DownloadTask.DownStatus.正在下载) {
startDownloadService(mData.get(pos).getId(),true);
holder.imgStart.setImageResource( R.mipmap.pause);
mData.get(pos).setDownSatus(DownloadTask.DownStatus.排队中);
}else{
startDownloadService(mData.get(pos).getId(),false);
holder.imgStart.setImageResource( R.mipmap.play);
mData.get(pos).setDownSatus(DownloadTask.DownStatus.暂停下载);
}
mData.get(pos).update( mData.get(pos).getId());
}
});
// 如果设置了回调,则设置点击事件
if (mOnItemClickLitener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemClick(holder.itemView, pos);
}
});
}
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemLongClick(holder.itemView, pos);
return false;
}
});
}
@Override
public int getItemCount() {
return mDatas.size();
}
public void addData(int position) {
// mDatas.add(position, "Insert One");
// notifyItemInserted(position);
}
public void removeData(int position) {
mDatas.remove(position);
notifyItemRemoved(position);
notifyDataSetChanged();
}
public void setData(List<DownloadTask> data) {
mData = data;
notifyDataSetChanged();
}
class EmptyViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.tvLoadText)
TextView tvEmpty;
public EmptyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
class MyViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.tvTitle)
TextView tvTitle;
@BindView(R.id.tvProgress)
TextView tvProgress;
@BindView(R.id.tvStatus)
TextView tvStatus;
@BindView(R.id.barProgress)
ProgressBar barProgress;
@BindView(R.id.imgStart)
ImageView imgStart;
@BindView(R.id.tvSource)
TextView tvSource;
@BindView(R.id.tvSize)
TextView tvSize;
public MyViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
//tvTitle = (TextView) view.findViewById(R.id.title);
// tvAuthor = (TextView) view.findViewById(R.id.author);
}
}
}
interface OnItemClickLitener
{
void onItemClick(View view, int position);
void onItemLongClick(View itemView, int pos);
}
}

View File

@ -1,8 +1,8 @@
<component name="libraryTable">
<library name="Gradle: com.jakewharton:butterknife-runtime:9.0.0@aar">
<CLASSES>
<root url="file://$PROJECT_DIR$/caches/transforms-2/files-2.1/8bfd3eb30d40173d1eacfce343a47478/AndroidManifest.xml" />
<root url="jar://$PROJECT_DIR$/caches/transforms-2/files-2.1/8bfd3eb30d40173d1eacfce343a47478/jars/classes.jar!/" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/butterknife-runtime-9.0.0.aar/527e359511186877b4a934e7fc2865fb/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/butterknife-runtime-9.0.0.aar/527e359511186877b4a934e7fc2865fb/res" />
</CLASSES>
<JAVADOC />
<SOURCES>

View File

@ -0,0 +1,491 @@
package com.novelbook.android.Fragments;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.pdf.PdfDocument;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.Gson;
import com.novelbook.android.Activity_base;
import com.novelbook.android.Activity_paihangbang;
import com.novelbook.android.Activity_shudan;
import com.novelbook.android.BookActivity;
import com.novelbook.android.BuildConfig;
import com.novelbook.android.Main2Activity;
import com.novelbook.android.R;
import com.novelbook.android.ReadActivity;
import com.novelbook.android.adapter.BookListAdapter;
import com.novelbook.android.bean.NovelBlock;
import com.novelbook.android.db.Novel;
import com.novelbook.android.netsubscribe.BookSubscribe;
import com.novelbook.android.netutils.NetUtil;
import com.novelbook.android.netutils.OnSuccessAndFaultListener;
import com.novelbook.android.netutils.OnSuccessAndFaultSub;
import com.novelbook.android.utils.Constants;
import com.novelbook.android.utils.ImageUtil;
import com.novelbook.android.utils.MyImageLoader;
import com.novelbook.android.utils.OnItemClickListener;
import com.novelbook.android.utils.PageFactory;
import com.qq.e.ads.nativ.ADSize;
import com.qq.e.ads.nativ.NativeADUnifiedListener;
import com.qq.e.ads.nativ.NativeExpressAD;
import com.qq.e.ads.nativ.NativeExpressADView;
import com.qq.e.ads.nativ.NativeUnifiedAD;
import com.qq.e.ads.nativ.NativeUnifiedADData;
import com.qq.e.comm.constants.AdPatternType;
import com.qq.e.comm.util.AdError;
import com.qq.e.comm.util.GDTLogger;
import com.umeng.analytics.MobclickAgent;
import com.youth.banner.loader.ImageLoader;
import org.litepal.LitePal;
import org.w3c.dom.Text;
import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import static com.novelbook.android.bean.AdSetting.getAppID;
/**
* A simple {@link Fragment} subclass.
*/
public abstract class BasicFragment extends Fragment /*implements NativeADUnifiedListener,NativeExpressAD.NativeExpressADListener*/ {
private static String TAG = BasicFragment.class.getSimpleName();
protected View rootView;
protected int pageNo=1;
private int pageCount;
public int getPageCount() {
pageCount = pageCount >Constants.MAX_PAGE_CNT ? Constants.MAX_PAGE_CNT :pageCount;
return pageCount;
}
public void setPageCount(int pageCount) {
this.pageCount = pageCount;
}
protected abstract int getLayoutRes();
protected abstract void initData();
protected abstract void fillData();
protected void initListener(){}
protected abstract void initViews();
protected Gson gson = new Gson();
// protected MyImageLoader imgloader = new MyImageLoader();
// Main2Activity activity;
Activity_base activity;
@Nullable
@BindView(R.id.swipeLayout)
SwipeRefreshLayout mSwipeRefresh;
@Nullable
@BindView(R.id.banner_container)
FrameLayout mBannerContainer;
int MSG_INIT_TAB =99;
int error_try=0;
int error_try_max=5;
public BasicFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setFTag();
// Log.d(TAG,"fragment onCreate ");
// activity =(Main2Activity)getActivity();
activity = (Activity_base)getActivity();
processArguments();
// QLog.getLogger().e(dTAG,TAG+" "+ "onCreate");
// mediumFontSize = activity.getMiddleSizeFont();
}
protected abstract void processArguments();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG,"onCreateView");
View view = inflater.inflate(getLayoutRes(), container, false);
rootView = view;
// 初始化View注入
ButterKnife.bind(this,view);
initListener();
initData();
initViews();
initSwipeRefreshLayout();
if (mBannerContainer!=null && (!Constants.AD_SETTING.isShowAdsense() || !Constants.AD_SETTING.getFixBanner().isShow() )) {
if( mBannerContainer.getVisibility() !=View.GONE) {
mBannerContainer.setVisibility(View.GONE);
}
}
return view;
// Inflate the layout for this fragment
}
public String getCurrentTag() {
setFTag();
return TAG;
}
public void setFTag(){};
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.d(TAG, "prepare book handleMessage: msg" +msg.what);
hideProgress();
int wt = msg.what;
if (msg.what == 1) {
try {
fillData();
}catch (Exception e){
Log.e(TAG, "handleMessage: filldata error ", e);
}
} else if (msg.what == MSG_INIT_TAB) //
{
initTabs();
// Toast.makeText(getActivity(), "数据请求失败 ", Toast.LENGTH_LONG).show();
}
if(getActivity()!=null && !NetUtil.isNetworkConnected()){
Toast.makeText(getActivity(),"好像没有网络啦",Toast.LENGTH_LONG).show();
}
}
};
void initTabs(){
}
//--------------------------------------------------------------book list adapter------------------------------------------------
/* interface mOnItemClickListener
{
void onItemClick(View view, int position);
void onItemLongClick(View view , int position);
void onLinearOutClick(View view,int bookId);
}
*/
protected List<Novel> initData(List<Novel> mDatas, char x)
{
mDatas = new ArrayList<Novel>();
for (int i = 'A'; i < x; i++)
{
Novel bk = new Novel();
bk.setNovelId(i);
bk.setAuthor("金庸");
bk.setName("射雕英雄传" +(char)i);
bk.setNovelType("武侠");
bk.setDesc("南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事南宋时期的武林故事");
mDatas.add(bk);
}
return mDatas;
}
void showBookDetail(Novel book) {
Intent intent = new Intent(activity, BookActivity.class);
intent.putExtra(BookActivity.EXTRA_BOOK,book);
startActivity(intent);
}
void getBookInfo(Novel novel){
int novelId = novel.getNovelId();
long id = novel.getId();
Log.d(TAG, String.format("prepare book %s ,start to loading book info from host ",novel.getName()));
// showProgressDialog(false,"正在加载...");
PageFactory pageFactory =PageFactory.getInstance(activity ) ;
pageFactory.initBookUtil();
ReadActivity.openBook(novel ,activity);
BookSubscribe.getNovel(novel.getNovelId(),new OnSuccessAndFaultSub(new OnSuccessAndFaultListener() {
@Override
public void onSuccess(String result) {
//成功
Novel nv ;
nv = gson.fromJson(result,Novel.class);
if(id>0) {
nv.update(id);
// nv.checkAndUpdate();
nv= LitePal.find(Novel.class,id);
}else {
nv.save();
}
Log.d(TAG, String.format("prepare book %s ,start to loading book info from host -----------done",novel.getName()));
Log.d(TAG, String.format("prepare book %s ,lastchapt %s, last pos %s ,开始prepare.",nv.getName(),nv.getLastReadChapt(),nv.getLastReadPos()) );
// final Novel novel = nv;
/* new Thread(){
@Override
public void run() {
super.run();
}
}.start();*/
// ReadActivity.openBook(nv ,activity);
// PageFactory.getInstance(activity.getApplicationContext()).prepareBook(nv ); //打开本地小说内容
//PageFactory.getInstance(activity ).prepareBook(nv ); //打开本地小说内容
pageFactory.prepareBook(nv );
Log.d(TAG, String.format("prepare book %s 开始open book.",nv.getName()) );
handler.sendEmptyMessage(99);
}
@Override
public void onFault(String errorMsg) {
//失败
Toast.makeText(getActivity(),novel.getName() +" 信息请求失败" ,Toast.LENGTH_SHORT).show();
// PageFactory.getInstance(activity ).prepareBook(novel ); //打开本地小说内容
pageFactory.prepareBook(novel );
// ReadActivity.openBook(novel ,activity);
handler.sendEmptyMessage(99);
}
},getActivity()));
}
void showProgressDialog(boolean flag,String msg){
if(!Constants.showDialogOnUi){
return;
}
if(pageNo >1 && !Constants.showDialogOnUiPage){
return;
}
if(getActivity()==null){
return;
}
if(NetUtil.isNetworkConnected())
if(mSwipeRefresh ==null || !mSwipeRefresh.isRefreshing()) {
((Activity_base) getActivity()).showProgressDialog(flag,msg);
}
}
void hideProgress(){
if(getActivity()==null){
return;
}
if(mSwipeRefresh!=null && mSwipeRefresh.isRefreshing()) {
mSwipeRefresh.setRefreshing(false);
}
((Activity_base) getActivity()).hideProgress();
}
void initSwipeRefreshLayout(){
if(mSwipeRefresh==null){return;}
mSwipeRefresh.setColorSchemeResources(R.color.colorPrimary,R.color.colorPrimaryDark);
mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
// 开始刷新,设置当前为刷新状态
//swipeRefreshLayout.setRefreshing(true);
pageNo=1;
error_try=0;
initData();
// TODO 获取数据
}
});
}
void openBook(Novel book, BookListAdapter mAdapter) {
//从新从数据库抓取该书的最新阅读进度
Novel book1 = (Novel)LitePal.find(Novel.class,book.getId());
if(book1!=null) { //读取本地最新进度
book.setLastReadPos(book1.getLastReadPos());
book.setLastReadChapt(book1.getLastReadChapt());
}
// Toast.makeText(activity, book.getName() + "加载", Toast.LENGTH_SHORT).show();
if(!book.isLocalBook()){
getBookInfo(book);
/*
PageFactory pageFactory = PageFactory.getInstance();
showProgressDialog(false,"读取目录信息");
int slept = 0;
while(slept <100 || pageFactory.getChapters() == null || pageFactory.getChapters().size()==0){
try {
Thread.sleep(50);
slept++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
hideProgress();
*/
//ReadActivity.openBook(book ,activity);
return;
}
final String path = book.getNovelPath();
File file = new File(path);
if (!file.exists()){
new AlertDialog.Builder(activity)
.setTitle(activity.getString(R.string.app_name))
.setMessage(path + "文件不存在,是否删除该书本?")
.setPositiveButton("删除", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
LitePal.deleteAll(Novel.class, "id = ?", book.getId()+"");
if(mAdapter!=null) {mAdapter.setBookList( LitePal.where("isOnShelf=?","1").find(Novel.class));}
}
}).setCancelable(true).show();
return;
}
ReadActivity.openBook(book ,activity);
}
void showShudanDetail(int shuandanId){
Intent intent = new Intent(activity, Activity_shudan.class);
intent.putExtra("NAME",shuandanId);
startActivity(intent);
}
//-------------------------------------------------------------------------------------book list adapter end--------------------------------------------------
void showPaihangbang(Object obj) { //show paihangbang activity
NovelBlock nb = (NovelBlock) obj;
Intent intent = new Intent(activity, Activity_paihangbang.class);
String title = TextUtils.isEmpty(nb.getTitle()) ? nb.getName() : nb.getTitle() ;
intent.putExtra(Activity_paihangbang.EXTR_FN,nb.getFn() );
intent.putExtra(Activity_paihangbang.EXTR_TITLE,title );
startActivity(intent);
}
void showPaihangbang(NovelBlock nb) { //show paihangbang activity
Intent intent = new Intent(activity, Activity_paihangbang.class);
String title = TextUtils.isEmpty(nb.getTitle()) ? nb.getName() : nb.getTitle() ;
intent.putExtra(Activity_paihangbang.EXTR_CID,nb.getCid() );
intent.putExtra(Activity_paihangbang.EXTR_TITLE,title );
intent.putExtra(Activity_paihangbang.EXTR_BANGDAN,title );
startActivity(intent);
}
protected void loadImageView(String url, ImageView imageView){
ImageUtil.loadImage( getActivity(), url , imageView);
}
public void reload() {
loadData();
}
public void loadData() {
initData();
} //on tab changed
void retryErorr(int msg){
if(error_try<error_try_max){
error_try++;
initData();
}else {
handler.sendEmptyMessage(msg);
}
}
void initRetryCnt(){
error_try=0;
}
//---------banner ad------
public void showBanner( FrameLayout bannerContainer , int adHeight ) {
if(bannerContainer==null){
return;
}
if ( !Constants.AD_SETTING.isShowAdsense() || !Constants.AD_SETTING.getFixBanner().isShow() || !NetUtil.isNetworkConnected()) {
mBannerContainer.setVisibility(View.GONE);
return;
}
activity .loadBanner(bannerContainer, (int)(adHeight*5.9), adHeight);
if( mBannerContainer.getVisibility() !=View.VISIBLE)
mBannerContainer.setVisibility(View.VISIBLE);
}
void loadListAd( BookListAdapter adapter, int adCnt, boolean addFooter) {
activity.loadListAd(adapter,adCnt,addFooter);
}
@Override
public void onResume() {
super.onResume();
error_try=0;
showBanner(mBannerContainer,(int) getResources().getDimension(R.dimen.topBannerHeight) );
// MobclickAgent.onPageStart(TAG);
}
@Override
public void onPause(){
super.onPause();
hideProgress();
// MobclickAgent.onPageEnd(TAG);
}
}

View File

@ -0,0 +1,243 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#FF7F50</color>
<color name="colorPrimaryDark">#FF6347</color>
<color name="colorPrimary3">#008577</color>
<color name="colorPrimaryDark3">#00574B</color>
<color name="colorAccent">#D81B60</color>
<color name="black">#000000</color>
<color name="gray">#000000</color>
<color name="white">#ffffff</color>
<color name="blacktitle">#212121</color>
<color name="ivory">#FFFFF0</color> <!--象牙色 -->
<color name="lightyellow">#FFFFE0</color><!--亮黄色-->
<color name="yellow">#FFFF00</color><!--黄色 -->
<color name="snow">#FFFAFA</color><!--雪白色 -->
<color name="floralwhite">#FFFAF0</color><!--花白色 -->
<color name="lemonchiffon">#FFFACD</color><!--柠檬绸色 -->
<color name="cornsilk">#FFF8DC</color><!--米绸色 -->
<color name="seashell">#FFF5EE</color><!--海贝色 -->
<color name="lavenderblush">#FFF0F5</color><!--淡紫红 -->
<color name="papayawhip">#FFEFD5</color><!--番木色 -->
<color name="blanchedalmond">#FFEBCD</color><!--白杏色 -->
<color name="mistyrose">#FFE4E1</color><!--浅玫瑰色 -->
<color name="bisque">#FFE4C4</color><!--桔黄色 -->
<color name="moccasin">#FFE4B5</color><!--鹿皮色 -->
<color name="navajowhite">#FFDEAD</color><!--纳瓦白 -->
<color name="peachpuff">#FFDAB9</color><!--桃色 -->
<color name="gold">#FFD700</color><!--金色 -->
<color name="pink">#FFC0CB</color><!--粉红色 -->
<color name="lightpink">#FFB6C1</color><!--亮粉红色-->
<color name="orange">#FFA500</color><!--橙色 -->
<color name="lightsalmon">#FFA07A</color><!--亮肉色 -->
<color name="darkorange">#FF8C00</color><!--暗桔黄色 -->
<color name="coral">#FF7F50</color><!--珊瑚色 -->
<color name="hotpink">#FF69B4</color><!--热粉红色 -->
<color name="tomato">#FF6347</color><!--西红柿色 -->
<color name="orangered">#FF4500</color><!--红橙色 -->
<color name="deeppink">#FF1493</color><!--深粉红色 -->
<color name="fuchsia">#FF00FF</color><!--紫红色 -->
<color name="magenta">#FF00FF</color><!--红紫色 -->
<color name="red">#FF0000</color><!--红色 -->
<color name="oldlace">#FDF5E6</color><!--老花色 -->
<color name="lightgoldenrodyellow">#FAFAD2</color><!--亮金黄色 -->
<color name="linen">#FAF0E6</color><!--亚麻色 -->
<color name="antiquewhite">#FAEBD7</color><!--古董白 -->
<color name="salmon">#FA8072</color><!--鲜肉色 -->
<color name="ghostwhite">#F8F8FF</color><!--幽灵白 -->
<color name="mintcream">#F5FFFA</color><!--薄荷色 -->
<color name="whitesmoke">#F5F5F5</color><!--烟白色 -->
<color name="beige">#F5F5DC</color><!--米色 -->
<color name="wheat">#F5DEB3</color><!--浅黄色 -->
<color name="sandybrown">#F4A460</color><!--沙褐色-->
<color name="azure">#F0FFFF</color><!--天蓝色 -->
<color name="honeydew">#F0FFF0</color><!--蜜色 -->
<color name="aliceblue">#F0F8FF</color><!--艾利斯兰 -->
<color name="khaki">#F0E68C</color><!--黄褐色 -->
<color name="lightcoral">#F08080</color><!--亮珊瑚色 -->
<color name="palegoldenrod">#EEE8AA</color><!--苍麒麟色 -->
<color name="violet">#EE82EE</color><!--紫罗兰色 -->
<color name="darksalmon">#E9967A</color><!--暗肉色 -->
<color name="lavender">#E6E6FA</color><!--淡紫色 -->
<color name="lightcyan">#E0FFFF</color><!--亮青色 -->
<color name="burlywood">#DEB887</color><!--实木色 -->
<color name="plum">#DDA0DD</color><!--洋李色 -->
<color name="gainsboro">#DCDCDC</color><!--淡灰色 -->
<color name="crimson">#DC143C</color><!--暗深红色 -->
<color name="palevioletred">#DB7093</color><!--苍紫罗兰色 -->
<color name="goldenrod">#DAA520</color><!--金麒麟色 -->
<color name="orchid">#DA70D6</color><!--淡紫色 -->
<color name="thistle">#D8BFD8</color><!--蓟色 -->
<color name="lightgray">#D3D3D3</color><!--亮灰色 -->
<color name="tan">#D2B48C</color><!--茶色 -->
<color name="chocolate">#D2691E</color><!--巧可力色 -->
<color name="peru">#CD853F</color><!--秘鲁色 -->
<color name="indianred">#CD5C5C</color><!--印第安红 -->
<color name="mediumvioletred">#C71585</color><!--中紫罗兰色 -->
<color name="silver">#C0C0C0</color><!--银色 -->
<color name="darkkhaki">#BDB76B</color><!--暗黄褐色 -->
<color name="rosybrown">#BC8F8F</color> <!--褐玫瑰红 -->
<color name="mediumorchid">#BA55D3</color><!--中粉紫色 -->
<color name="darkgoldenrod">#B8860B</color><!--暗金黄色 -->
<color name="firebrick">#B22222</color><!--火砖色 -->
<color name="powderblue">#B0E0E6</color><!--粉蓝色 -->
<color name="lightsteelblue">#B0C4DE</color><!--亮钢兰色 -->
<color name="paleturquoise">#AFEEEE</color><!--苍宝石绿 -->
<color name="greenyellow">#ADFF2F</color><!--黄绿色 -->
<color name="lightblue">#ADD8E6</color><!--亮蓝色 -->
<color name="darkgray">#A9A9A9</color><!--暗灰色 -->
<color name="darkgrey">#A9A9A9</color><!--暗灰色 -->
<color name="brown">#A52A2A</color><!--褐色 -->
<color name="sienna">#A0522D</color><!--赭色 -->
<color name="darkorchid">#9932CC</color><!--暗紫色-->
<color name="palegreen">#98FB98</color><!--苍绿色 -->
<color name="darkviolet">#9400D3</color><!--暗紫罗兰色 -->
<color name="mediumpurple">#9370DB</color><!--中紫色 -->
<color name="lightgreen">#90EE90</color><!--亮绿色 -->
<color name="darkseagreen">#8FBC8F</color><!--暗海兰色 -->
<color name="saddlebrown">#8B4513</color><!--重褐色 -->
<color name="darkmagenta">#8B008B</color><!--暗洋红 -->
<color name="darkred">#8B0000</color><!--暗红色 -->
<color name="blueviolet">#8A2BE2</color><!--紫罗兰蓝色 -->
<color name="lightskyblue">#87CEFA</color><!--亮天蓝色 -->
<color name="skyblue">#87CEEB</color><!--天蓝色 -->
<color name="grey">#808080</color><!--灰色 -->
<color name="olive">#808000</color><!--橄榄色 -->
<color name="purple">#800080</color><!--紫色 -->
<color name="maroon">#800000</color><!--粟色 -->
<color name="aquamarine">#7FFFD4</color><!--碧绿色-->
<color name="chartreuse">#7FFF00</color><!--黄绿色 -->
<color name="lawngreen">#7CFC00</color><!--草绿色 -->
<color name="mediumslateblue">#7B68EE</color><!--中暗蓝色 -->
<color name="lightslategray">#778899</color><!--亮蓝灰 -->
<color name="lightslategrey">#778899</color><!--亮蓝灰 -->
<color name="slategray">#708090</color><!--灰石色 -->
<color name="slategrey">#708090</color><!--灰石色 -->
<color name="olivedrab">#6B8E23</color><!--深绿褐色 -->
<color name="slateblue">#6A5ACD</color><!--石蓝色 -->
<color name="dimgray">#696969</color><!--暗灰色 -->
<color name="dimgrey">#696969</color><!--暗灰色 -->
<color name="mediumaquamarine">#66CDAA</color><!--中绿色 -->
<color name="cornflowerblue">#6495ED</color><!--菊兰色 -->
<color name="cadetblue">#5F9EA0</color><!--军兰色 -->
<color name="darkolivegreen">#556B2F</color><!--暗橄榄绿 -->
<color name="indigo">#4B0082</color><!--靛青色 -->
<color name="mediumturquoise">#48D1CC</color><!--中绿宝石 -->
<color name="darkslateblue">#483D8B</color><!--暗灰蓝色 -->
<color name="steelblue">#4682B4</color><!--钢兰色 -->
<color name="royalblue">#4169E1</color><!--皇家蓝 -->
<color name="turquoise">#40E0D0</color><!--青绿色 -->
<color name="mediumseagreen">#3CB371</color><!--中海蓝 -->
<color name="limegreen">#32CD32</color><!--橙绿色 -->
<color name="darkslategray">#2F4F4F</color><!--暗瓦灰色 -->
<color name="darkslategrey">#2F4F4F</color><!--暗瓦灰色 -->
<color name="seagreen">#2E8B57</color><!--海绿色 -->
<color name="forestgreen">#228B22</color><!--森林绿 -->
<color name="lightseagreen">#20B2AA</color><!--亮海蓝色 -->
<color name="dodgerblue">#1E90FF</color><!--闪兰色 -->
<color name="midnightblue">#191970</color><!--中灰兰色 -->
<color name="aqua">#00FFFF</color><!--浅绿色 -->
<color name="cyan">#00FFFF</color><!--青色 -->
<color name="springgreen">#00FF7F</color><!--春绿色-->
<color name="lime">#00FF00</color><!--酸橙色 -->
<color name="mediumspringgreen">#00FA9A</color><!--中春绿色 -->
<color name="darkturquoise">#00CED1</color><!--暗宝石绿 -->
<color name="deepskyblue">#00BFFF</color><!--深天蓝色 -->
<color name="darkcyan">#008B8B</color><!--暗青色 -->
<color name="teal">#008080</color><!--水鸭色 -->
<color name="green">#008000</color><!--绿色 -->
<color name="darkgreen">#006400</color><!--暗绿色 -->
<color name="blue">#0000FF</color><!--蓝色 -->
<color name="mediumblue">#0000CD</color><!--中兰色 -->
<color name="darkblue">#00008B</color><!--暗蓝色 -->
<color name="navy">#000080</color><!--海军色 -->
<!-- chart colors -->
<color name="color1">#56ADDB</color><!--浅蓝色 -->
<color name="color2">#F59331</color><!--暗绿色 -->
<color name="color3">#73C83C</color><!--蓝色 -->
<color name="color4">#948D8B</color><!--中兰色 -->
<color name="color5">#E54273</color><!--暗蓝色 -->
<color name="color6">#FFD34E</color><!--海军色 -->
<color name="color7">#2A86D6</color><!--蓝色 -->
<color name="color8">#00BFC0</color><!--中兰色 -->
<color name="color9">#95AC5F</color><!--暗蓝色 -->
<color name="color10">#FF8497</color><!--海军色 -->
<!-- button text -->
<drawable name="font_active">#2F4F4F</drawable>
<drawable name="font_pressed">#ffffff</drawable>
<drawable name="font_inactive">#808080</drawable>
<!-- progressbar -->
<color name="default_screen_bg">#20324a</color>
<color name="rounded_container_bg">#80000000</color>
<color name="rounded_container_border">#3b3f44</color>
<color name="light_gray_header_color">#646663</color>
<color name="black_overlay">#66000000</color>
<!-- colors from zijie-->
<color name="halfColorPrimary">#aa2C2C2C</color>
<color name="dark_red">#ff8c1c1c</color>
<color name="transparent">#00000000</color>
<color name="light_gray">#ffececec</color>
<color name="light_yellow">#fffff99e</color>
<color name="dark_gray">#ff999999</color>
<color name="full_transparent">#00000000</color>
<color name="half_transparent">#aa000000</color>
<color name="background_color">#eeeeee</color>
<color name="list_item_divider">#F5F5F5</color>
<color name="divider">#9c9c9c</color>
<color name="text_color">#000000</color>
<color name="text_color_pressed">#ffffff</color>
<color name="text_title_color">#444444</color>
<color name="menu_background">#d3d7d4</color>
<color name="toolpop_background">#b0000000</color>
<color name="shelf_background">#DA955A</color>
<color name="shelf_myNavigationColor">#86471B</color>
<!-- Reader Color -->
<color name="reader_default_bg_toolbar">#CC000000</color>
<color name="reader_default_bg_yellow">#CFBEB6</color>
<color name="reader_default_bg_black">#090C13</color>
<color name="reader_default_text_light">#32414E</color>
<color name="reader_default_text_dark">#444444</color>
<color name="read_background">#FAF9DE</color>
<color name="read_background_paperYellow">#D4C5A3</color>
<color name="read_textColor">#3B3A38</color>
<color name="read_dialog_bg">#2C2C2C</color>
<color name="read_dialog_button_select">#E25754</color>
<color name="read_bg_default">#CEC29C</color>
<color name="read_bg_1">#CCEBCC</color>
<color name="read_bg_2">#37342F</color>
<color name="read_bg_3">#D1CEC5</color>
<color name="read_bg_4">#001C27</color>
<color name="read_font_default">#2C2C2C</color>
<color name="read_font_1">#2F332D</color>
<color name="read_font_2">#92918C</color>
<color name="read_font_3">#383429</color>
<color name="read_font_4">#627176</color>
<color name="lineColor">#60d3d3d3</color>
<!-- UI Color -->
<color name="myPrimaryColor">#4284F5</color>
<color name="myPrimaryDarkColor">#3870d0</color>
<color name="myAccentColor">#fe5151</color>
<color name="myDrawerBackground">#F2F2F2</color>
<color name="myWindowBackground">#F5F5F5</color>
<color name="myTextPrimaryColor">#FFFFFF</color>
<color name="mySearchToggleColor">#7F7F7F</color>
<!-- Navigation Color is 30% black mask attack to primary color -->
<color name="myNavigationColor">#2E5CAB</color>
<color name="myNavigationColorWhite">#B2B2B2</color>
<color name="tabSelected">#FF6347</color>
</resources>

View File

@ -0,0 +1,10 @@
<component name="libraryTable">
<library name="Gradle: com.google.android.gms:play-services-tasks:16.0.1@aar">
<CLASSES>
<root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/play-services-tasks-16.0.1.aar/c05355a86430d460d91f4a335962c12b/res" />
<root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/play-services-tasks-16.0.1.aar/c05355a86430d460d91f4a335962c12b/jars/classes.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -0,0 +1,99 @@
package com.novelbook.android;
import android.content.Intent;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.View;
import com.novelbook.android.Fragments.Fragment_shudan_list;
import com.flyco.tablayout.SlidingTabLayout;
import java.util.ArrayList;
import butterknife.BindView;
public class Activity_shudan_my extends Activity_base {
public static String TAG ="com.novelbook.android.Activity_shudan_my";
@BindView(R.id.viewpager)
ViewPager mViewpager;
@BindView(R.id.tab_layout)
SlidingTabLayout tabLayout;
@BindView(R.id.fab)
FloatingActionButton fab;
private ArrayList<Fragment> mFragments;
ArrayList<View> mList;
String[] mTitle;
@Override
public int getLayoutRes() {
return R.layout.activity_shudan_my;
}
@Override
protected void initViews() {
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(Activity_shudan_my.this, Activity_createShudan.class);
intent.putExtra("SHUDANID",0);
startActivity(intent);
}
});
initTabs();
}
@Override
protected void setTitle() {
setTitle("我的书单");
}
@Override
protected void initData() {
}
@Override
public void fillData() {
}
void initTabs() {
if(mFragments ==null || mFragments.size() ==0){
mTitle = new String[]{"已发布", "草稿", "收藏"};
mFragments = new ArrayList<>();
mFragments.add(new Fragment_shudan_list());
mFragments.add(new Fragment_shudan_list());
mFragments.add(new Fragment_shudan_list());
Log.d(TAG,"initial fragments in tabs ");
}
Log.d(TAG,"set viewPager adapter ");
// FragmentPagerAdapter mAdapter = new FragmentPagerAdapter(activity.getSupportFragmentManager()) { 第一次进入没问题再次进入ViewPager的fragment时里面内容就没了,数据丢失 https://blog.csdn.net/allan_bst/article/details/64920076
FragmentPagerAdapter mAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
//ViewPager与TabLayout绑定后这里获取到PageTitle就是Tab的Text
@Override
public CharSequence getPageTitle(int position) {
return mTitle[position];
}
};
mViewpager.setAdapter(mAdapter);
tabLayout.setViewPager(mViewpager);
// tabLayout.setViewPager(mViewpager, mTitle, activity, mFragments);
mViewpager.setCurrentItem(0);
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 这个下载路径不可以修改,必须是 GDTDOWNLOAD -->
<external-path name="gdt_sdk_download_path" path="GDTDOWNLOAD" />
</paths>

View File

@ -0,0 +1,128 @@
package com.novelbook.android;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.provider.SyncStateContract;
import android.util.Log;
import com.bytedance.sdk.openadsdk.TTAdConfig;
import com.bytedance.sdk.openadsdk.TTAdConstant;
import com.bytedance.sdk.openadsdk.TTAdSdk;
import com.google.gson.Gson;
import com.novelbook.android.AD.toutiao.TTAdManagerHolder;
import com.novelbook.android.bean.AdSetting;
import com.novelbook.android.netutils.HttpMethods;
import com.novelbook.android.netutils.NetUtil;
import com.novelbook.android.utils.Config;
import com.novelbook.android.utils.Constants;
import com.novelbook.android.utils.LogcatHelper;
import com.novelbook.android.utils.PageFactory;
import com.novelbook.android.AD.SplashAdManager;
import com.umeng.analytics.MobclickAgent;
import com.umeng.commonsdk.UMConfigure;
import org.litepal.LitePal;
import java.util.ArrayList;
import java.util.List;
public class MyApp extends Application {
public static volatile Context applicationContext = null;
SplashAdManager splashAdManager;
private List<Activity> oList;//用于存放所有启动的Activity的集合
@Override
public void onCreate() {
super.onCreate();
oList = new ArrayList<Activity>();
applicationContext = getApplicationContext();
HttpMethods.USERAGENT = NetUtil.getUserAgent();
HttpMethods.LOCALUSERAGENT = NetUtil.getUserAgent(applicationContext);
initialConstants();
PageFactory.createPageFactory(this);
LogcatHelper.getInstance(this).start();
// BlurKit.init(this);
LitePal.initialize(this);
splashAdManager = new SplashAdManager(this);
initUmengApi();
initAD();
}
private void initialConstants(){
Config config= Config.createConfig(this);
Constants.SEX = config.getSexOption();
Constants.PRE_LOAD_CHAPT =config.isPreLoadChapter();
Gson gson = new Gson();
Constants.AD_SETTING = gson.fromJson(config.getAdSetting(), AdSetting.class);
if(Constants.AD_SETTING==null){
Constants.AD_SETTING = new AdSetting();
}
Constants.SHOW_NOVEL_CHAPTER_URL =config.isShowChatpUrl();
Constants.DECLARE = config.getDeclare();
Constants.ONE_DP_SIZE = (int)applicationContext.getResources().getDimension(R.dimen.one_dp);
}
private void initUmengApi(){
UMConfigure.init(applicationContext,UMConfigure.DEVICE_TYPE_PHONE,null);
MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO);
}
private void initAD(){
initAD_ChuanShanJia();
}
private void initAD_ChuanShanJia(){
TTAdManagerHolder.init(applicationContext);
}
public boolean exit() {
System.exit(-1);
removeALLActivity_();
return true;
}
/**
* 添加Activity
*/
public void addActivity_(Activity activity) {
// 判断当前集合中不存在该Activity
if (!oList.contains(activity)) {
oList.add(activity);//把当前Activity添加到集合中
}
currentAct=activity;
}
private static Activity currentAct =null;
public static Activity getCurrentActivity(){
return currentAct;
}
/**
* 销毁单个Activity
*/
public void removeActivity_(Activity activity) {
//判断当前集合中存在该Activity
if (oList.contains(activity)) {
oList.remove(activity);//从集合中移除
activity.finish();//销毁当前Activity
}
}
/**
* 销毁所有的Activity
*/
public void removeALLActivity_() {
//通过循环把集合中的所有Activity销毁
Log.d("MyApp", "removeALLActivity_: total activities to finish: " + oList.size());
for (Activity activity : oList) {
Log.d("MyApp", "removeALLActivity_: " + activity.getLocalClassName());
activity.finish();
}
}
public List<Activity> getActivityList(){
return oList;
}
}

View File

@ -0,0 +1,9 @@
package com.novelbook.android.utils;
import android.view.View;
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongClick(View view , int position);
void onLinearOutClick(View view,int position,int llid);
}

View File

@ -0,0 +1,292 @@
package com.novelbook.android.AD.qq;
import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.novelbook.android.Main2Activity;
import com.novelbook.android.R;
import com.novelbook.android.utils.Constants;
import com.qq.e.ads.splash.SplashAD;
import com.qq.e.ads.splash.SplashADListener;
import com.qq.e.comm.util.AdError;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.novelbook.android.bean.AdSetting.getAppID;
/**
* 这是demo工程的入口Activity在这里会首次调用广点通的SDK。
*
* 在调用SDK之前如果您的App的targetSDKVersion >= 23那么一定要把"READ_PHONE_STATE"、"WRITE_EXTERNAL_STORAGE"、"ACCESS_FINE_LOCATION"这几个权限申请到否则SDK将不会工作。
*/
public class SplashActivity extends Activity implements SplashADListener {
private SplashAD splashAD;
private ViewGroup container;
private TextView skipView;
//private ImageView splashHolder;
private TextView splashHolder;
private TextView tvTitle;
private static final String SKIP_TEXT = "点击跳过 %d";
public boolean canJump = false;
/**
* 为防止无广告时造成视觉上类似于"闪退"的情况设定无广告时页面跳转根据需要延迟一定时间demo
* 给出的延时逻辑是从拉取广告开始算开屏最少持续多久仅供参考开发者可自定义延时逻辑如果开发者采用demo
* 中给出的延时逻辑也建议开发者考虑自定义minSplashTimeWhenNoAD的值单位ms
**/
private int minSplashTimeWhenNoAD = 2000;
/**
* 记录拉取广告的时间
*/
private long fetchSplashADTime = 0;
private Handler handler = new Handler(Looper.getMainLooper());
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ad_qq_activity_splash );
container = (ViewGroup) this.findViewById(R.id.splash_container);
skipView = (TextView) findViewById(R.id.skip_view);
tvTitle = (TextView) findViewById(R.id.textTile);
splashHolder = (TextView) findViewById(R.id.splash_holder);
tvTitle.setText(R.string.app_name);
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
| View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
// | View.SYSTEM_UI_FLAG_IMMERSIVE
);
/* boolean needLogo = getIntent().getBooleanExtra("need_logo", true);
needStartDemoList = getIntent().getBooleanExtra("need_start_demo_list", true);
if (!needLogo) {
findViewById(R.id.app_logo).setVisibility(View.GONE);
}*/
// 如果targetSDKVersion >= 23就要申请好权限。如果您的App没有适配到Android6.0即targetSDKVersion < 23那么只需要在这里直接调用fetchSplashAD接口。
if (Build.VERSION.SDK_INT >= 23) {
checkAndRequestPermission();
} else {
// 如果是Android6.0以下的机器默认在安装时获得了所有权限可以直接调用SDK
fetchSplashAD(this, container, skipView, getAppID(Constants.AD_TENCENT_QQ), getPosId(), this, 0);
}
}
private String getPosId() {
return Constants.AD_SETTING.getSplash().getSlotId(Constants.AD_TENCENT_QQ);
}
/**
*
* ----------非常重要----------
*
* Android6.0以上的权限适配简单示例:
*
* 如果targetSDKVersion >= 23那么必须要申请到所需要的权限再调用广点通SDK否则广点通SDK不会工作。
*
* Demo代码里是一个基本的权限申请示例请开发者根据自己的场景合理地编写这部分代码来实现权限申请。
* 注意:下面的`checkSelfPermission`和`requestPermissions`方法都是在Android6.0的SDK中增加的API如果您的App还没有适配到Android6.0以上则不需要调用这些方法直接调用广点通SDK即可。
*/
@TargetApi(Build.VERSION_CODES.M)
private void checkAndRequestPermission() {
List<String> lackedPermission = new ArrayList<String>();
if (!(checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED)) {
lackedPermission.add(Manifest.permission.READ_PHONE_STATE);
}
if (!(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) {
lackedPermission.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
if (!(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)) {
lackedPermission.add(Manifest.permission.ACCESS_FINE_LOCATION);
}
// 权限都已经有了那么直接调用SDK
if (lackedPermission.size() == 0) {
fetchSplashAD(this, container, skipView, getAppID(Constants.AD_TENCENT_QQ), getPosId(), this, 0);
} else {
// 请求所缺少的权限在onRequestPermissionsResult中再看是否获得权限如果获得权限就可以调用SDK否则不要调用SDK。
String[] requestPermissions = new String[lackedPermission.size()];
lackedPermission.toArray(requestPermissions);
requestPermissions(requestPermissions, 1024);
}
}
private boolean hasAllPermissionsGranted(int[] grantResults) {
for (int grantResult : grantResults) {
if (grantResult == PackageManager.PERMISSION_DENIED) {
return false;
}
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1024 && hasAllPermissionsGranted(grantResults)) {
fetchSplashAD(this, container, skipView, getAppID(Constants.AD_TENCENT_QQ), getPosId(), this, 0);
} else {
// 如果用户没有授权,那么应该说明意图,引导用户去设置里面授权。
Toast.makeText(this, "应用缺少必要的权限!请点击\"权限\",打开所需要的权限。", Toast.LENGTH_LONG).show();
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
finish();
}
}
/**
* 拉取开屏广告开屏广告的构造方法有3种详细说明请参考开发者文档。
*
* @param activity 展示广告的activity
* @param adContainer 展示广告的大容器
* @param skipContainer 自定义的跳过按钮传入该view给SDK后SDK会自动给它绑定点击跳过事件。SkipView的样式可以由开发者自由定制其尺寸限制请参考activity_splash.xml或者接入文档中的说明。
* @param appId 应用ID
* @param posId 广告位ID
* @param adListener 广告状态监听器
* @param fetchDelay 拉取广告的超时时长:取值范围[3000, 5000]设为0表示使用广点通SDK默认的超时时长。
*/
private void fetchSplashAD(Activity activity, ViewGroup adContainer, View skipContainer,
String appId, String posId, SplashADListener adListener, int fetchDelay) {
fetchSplashADTime = System.currentTimeMillis();
Map<String, String> tags = new HashMap<>();
tags.put("tag_s1", "value_s1");
tags.put("tag_s2", "value_s2");
splashAD = new SplashAD(activity, adContainer, skipContainer, appId, posId, adListener,
fetchDelay, tags);
// 如果不需要传tag使用如下构造函数
// splashAD = new SplashAD(activity, adContainer, skipContainer, appId, posId, adListener, fetchDelay);
}
@Override
public void onADPresent() {
Log.i("AD_DEMO", "SplashADPresent");
splashHolder.setVisibility(View.INVISIBLE); // 广告展示后一定要把预设的开屏图片隐藏起来
}
@Override
public void onADClicked() {
Log.i("AD_DEMO", "SplashADClicked clickUrl: "
+ (splashAD.getExt() != null ? splashAD.getExt().get("clickUrl") : ""));
}
/**
* 倒计时回调,返回广告还将被展示的剩余时间。
* 通过这个接口,开发者可以自行决定是否显示倒计时提示,或者还剩几秒的时候显示倒计时
*
* @param millisUntilFinished 剩余毫秒数
*/
@Override
public void onADTick(long millisUntilFinished) {
Log.i("AD_DEMO", "SplashADTick " + millisUntilFinished + "ms");
skipView.setText(String.format(SKIP_TEXT, Math.round(millisUntilFinished / 1000f)));
}
@Override
public void onADExposure() {
Log.i("AD_DEMO", "SplashADExposure");
}
@Override
public void onADDismissed() {
Log.i("AD_DEMO", "SplashADDismissed");
next();
}
@Override
public void onNoAD(AdError error) {
Log.i(
"AD_DEMO",
String.format("LoadSplashADFail, eCode=%d, errorMsg=%s", error.getErrorCode(),
error.getErrorMsg()));
/**
* 为防止无广告时造成视觉上类似于"闪退"的情况设定无广告时页面跳转根据需要延迟一定时间demo
* 给出的延时逻辑是从拉取广告开始算开屏最少持续多久仅供参考开发者可自定义延时逻辑如果开发者采用demo
* 中给出的延时逻辑也建议开发者考虑自定义minSplashTimeWhenNoAD的值
**/
long alreadyDelayMills = System.currentTimeMillis() - fetchSplashADTime;//从拉广告开始到onNoAD已经消耗了多少时间
long shouldDelayMills = alreadyDelayMills > minSplashTimeWhenNoAD ? 0 : minSplashTimeWhenNoAD
- alreadyDelayMills;//为防止加载广告失败后立刻跳离开屏可能造成的视觉上类似于"闪退"的情况根据设置的minSplashTimeWhenNoAD
// 计算出还需要延时多久
handler.postDelayed(new Runnable() {
@Override
public void run() {
SplashActivity.this.finish();
}
}, shouldDelayMills);
}
/**
* 设置一个变量来控制当前开屏页面是否可以跳转当开屏广告为普链类广告时点击会打开一个广告落地页此时开发者还不能打开自己的App主页。当从广告落地页返回以后
* 才可以跳转到开发者自己的App主页当开屏广告是App类广告时只会下载App。
*/
private void next() {
if (canJump) {
this.finish();
} else {
canJump = true;
}
}
@Override
protected void onPause() {
super.onPause();
canJump = false;
}
@Override
protected void onResume() {
super.onResume();
if (canJump) {
next();
}
canJump = true;
}
@Override
protected void onDestroy() {
super.onDestroy();
handler.removeCallbacksAndMessages(null);
}
/** 开屏页一定要禁止用户对返回按钮的控制否则将可能导致用户手动退出了App而广告无法正常曝光和计费 */
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME) {
return true;
}
return super.onKeyDown(keyCode, event);
}
}

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<!--
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="@+id/tvTitle"
style="@style/TitleText"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ImageButton
android:id="@+id/btnSort"
android:layout_weight="0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_format_line_spacing_black_24dp"
style="@style/buttonCates"/>
</LinearLayout>-->
<TextView
android:id="@+id/tvChapts"
style="@style/TextViewNovelTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/lv_catalogue"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="@color/list_item_divider"
android:dividerHeight="1dp" />
</android.support.v4.widget.SwipeRefreshLayout>
<Button
android:id="@+id/btnRefresh"
android:layout_width="100dp"
android:layout_height="wrap_content"
style="@style/buttonRound"
android:layout_gravity="center"
android:text="@string/refresh"
android:visibility="gone"
/>
</FrameLayout>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
android:orientation="vertical">
<LinearLayout
android:id="@+id/activty_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/message3"
android:layout_width="159dp"
android:layout_height="92dp"
android:text="书单" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>

View File

@ -0,0 +1,11 @@
<component name="libraryTable">
<library name="Gradle: com.google.code.gson:gson:2.8.5@jar">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.8.5/f645ed69d595b24d4cf8b3fbb64cc505bede8829/gson-2.8.5.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.8.5/c5b4c491aecb72e7c32a78da0b5c6b9cda8dee0f/gson-2.8.5-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<com.czp.searchmlist.mSearchLayout
android:layout_marginTop="35dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/msearchlayout"
app:search_hint="小说搜索"
app:search_baground="@drawable/search_baground_shap"
/>
<LinearLayout style="@style/llGraySplit" />
<FrameLayout
android:gravity="bottom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/banner_container"/>
</LinearLayout>

View File

@ -0,0 +1,322 @@
package com.novelbook.android.utils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
* Created by 眼神 on 2018/3/27.
* 类描述:处理压缩数据的工具
*/
public class CompressUtils {
private static final int BUFFER_LENGTH = 400;
//压缩字节最小长度,小于这个长度的字节数组不适合压缩,压缩完会更大
public static final int BYTE_MIN_LENGTH = 50;
//字节数组是否压缩标志位
public static final byte FLAG_GBK_STRING_UNCOMPRESSED_BYTEARRAY = 0;
public static final byte FLAG_GBK_STRING_COMPRESSED_BYTEARRAY = 1;
public static final byte FLAG_UTF8_STRING_COMPRESSED_BYTEARRAY = 2;
public static final byte FLAG_NO_UPDATE_INFO = 3;
/**
* 数据压缩
*
* @param is
* @param os
* @throws Exception
*/
public static void compress(InputStream is, OutputStream os) throws Exception {
GZIPOutputStream gos = new GZIPOutputStream(os);
int count;
byte data[] = new byte[BUFFER_LENGTH];
while ((count = is.read(data, 0, BUFFER_LENGTH)) != -1) {
gos.write(data, 0, count);
}
gos.finish();
gos.flush();
gos.close();
}
/**
* 数据解压缩
*
* @param is
* @param os
* @throws Exception
*/
public static void decompress(InputStream is, OutputStream os) throws Exception {
GZIPInputStream gis = new GZIPInputStream(is);
int count;
byte data[] = new byte[BUFFER_LENGTH];
while ((count = gis.read(data, 0, BUFFER_LENGTH)) != -1) {
os.write(data, 0, count);
}
gis.close();
}
/**
* 数据解压缩
*
* @param is
* @throws Exception return 返回解析好的json字符串
*/
public static String decompress(InputStream is) throws Exception {
GZIPInputStream gis = new GZIPInputStream(is);
ByteArrayOutputStream os = new ByteArrayOutputStream();
int count;
byte data[] = new byte[BUFFER_LENGTH];
while ((count = gis.read(data, 0, BUFFER_LENGTH)) != -1) {
os.write(data, 0, count);
}
os.close();
gis.close();
return new String(os.toByteArray());
}
/**
* 数据压缩
*
* @param data
* @return
* @throws Exception
*/
public static byte[] byteCompress(byte[] data) throws Exception {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 压缩
compress(bais, baos);
byte[] output = baos.toByteArray();
baos.flush();
baos.close();
bais.close();
return output;
}
/**
* 数据解压缩
*
* @param data
* @return
* @throws Exception
*/
public static byte[] byteDecompress(byte[] data) throws Exception {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// 解压缩
decompress(bais, baos);
data = baos.toByteArray();
baos.flush();
baos.close();
bais.close();
return data;
}
/**
* 压缩文件
*
* @param src
* @param dest
* @throws IOException
*/
public static void zip(String src, String dest) throws IOException {
//提供了一个数据项压缩成一个ZIP归档输出流
ZipOutputStream out = null;
try {
File outFile = new File(dest);//源文件或者目录
File fileOrDirectory = new File(src);//压缩文件路径
out = new ZipOutputStream(new FileOutputStream(outFile));
//如果此文件是一个文件否则为false。
if (fileOrDirectory.isFile()) {
zipFileOrDirectory(out, fileOrDirectory, "");
} else {
//返回一个文件或空阵列。
File[] entries = fileOrDirectory.listFiles();
for (int i = 0; i < entries.length; i++) {
// 递归压缩更新curPaths
zipFileOrDirectory(out, entries[i], "");
}
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
//关闭输出流
if (out != null) {
try {
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
/**
* 压缩文件
*
* @param out
* @param fileOrDirectory
* @param curPath
* @throws IOException
*/
private static void zipFileOrDirectory(ZipOutputStream out,
File fileOrDirectory, String curPath) throws IOException {
//从文件中读取字节的输入流
FileInputStream in = null;
try {
//如果此文件是一个目录否则返回false。
if (!fileOrDirectory.isDirectory()) {
// 压缩文件
byte[] buffer = new byte[4096];
int bytes_read;
in = new FileInputStream(fileOrDirectory);
//实例代表一个条目内的ZIP归档
ZipEntry entry = new ZipEntry(curPath
+ fileOrDirectory.getName());
//条目的信息写入底层流
out.putNextEntry(entry);
while ((bytes_read = in.read(buffer)) != -1) {
out.write(buffer, 0, bytes_read);
}
out.closeEntry();
} else {
// 压缩目录
File[] entries = fileOrDirectory.listFiles();
for (int i = 0; i < entries.length; i++) {
// 递归压缩更新curPaths
zipFileOrDirectory(out, entries[i], curPath
+ fileOrDirectory.getName() + "/");
}
}
} catch (IOException ex) {
ex.printStackTrace();
// throw ex;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
/**
* 解压
*
* @param zipFileName 压缩文件的文件名
* @param outputDirectory 解压后的路径
* @throws IOException
*/
@SuppressWarnings("unchecked")
public static void unzip(String zipFileName, String outputDirectory)
throws IOException {
ZipFile zipFile = null;
try {
zipFile = new ZipFile(zipFileName);
Enumeration e = zipFile.entries();
ZipEntry zipEntry = null;
File dest = new File(outputDirectory);
dest.mkdirs();
while (e.hasMoreElements()) {
zipEntry = (ZipEntry) e.nextElement();
String entryName = zipEntry.getName();
InputStream in = null;
FileOutputStream out = null;
try {
if (zipEntry.isDirectory()) {
String name = zipEntry.getName();
name = name.substring(0, name.length() - 1);
File f = new File(outputDirectory + File.separator
+ name);
f.mkdirs();
} else {
int index = entryName.lastIndexOf("\\");
if (index != -1) {
File df = new File(outputDirectory + File.separator
+ entryName.substring(0, index));
df.mkdirs();
}
index = entryName.lastIndexOf("/");
if (index != -1) {
File df = new File(outputDirectory + File.separator
+ entryName.substring(0, index));
df.mkdirs();
}
File f = new File(outputDirectory + File.separator
+ zipEntry.getName());
// f.createNewFile();
in = zipFile.getInputStream(zipEntry);
out = new FileOutputStream(f);
int c;
byte[] by = new byte[1024];
while ((c = in.read(by)) != -1) {
out.write(by, 0, c);
}
out.flush();
}
} catch (IOException ex) {
ex.printStackTrace();
throw new IOException("解压失败:" + ex.toString());
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ex) {
}
}
if (out != null) {
try {
out.close();
} catch (IOException ex) {
}
}
}
}
} catch (IOException ex) {
ex.printStackTrace();
throw new IOException("解压失败:" + ex.toString());
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch (IOException ex) {
}
}
}
}
}

View File

@ -0,0 +1,22 @@
package com.novelbook.android.bean;
public class NovelSites {
private String novelId;
private Site[] sites;
public String getNovelId() {
return novelId;
}
public void setNovelId(String novelId) {
this.novelId = novelId;
}
public Site[] getSites() {
return sites;
}
public void setSites(Site[] sites) {
this.sites = sites;
}
}

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
</vector>

View File

@ -0,0 +1,13 @@
<component name="libraryTable">
<library name="Gradle: com.android.support:support-compat:28.0.0@aar">
<ANNOTATIONS>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-compat-28.0.0.aar/5a493baa212e05d3f8c353948f2d4307/annotations.zip!/" />
</ANNOTATIONS>
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-compat-28.0.0.aar/5a493baa212e05d3f8c353948f2d4307/jars/classes.jar!/" />
<root url="file://$USER_HOME$/.gradle/caches/transforms-1/files-1.1/support-compat-28.0.0.aar/5a493baa212e05d3f8c353948f2d4307/res" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@ -0,0 +1,489 @@
package com.novelbook.android.dialog;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.SeekBar;
import android.widget.TextView;
import com.novelbook.android.utils.CommonUtil;
import com.novelbook.android.utils.Config;
import com.novelbook.android.R;
import com.novelbook.android.utils.DisplayUtils;
import com.novelbook.android.view.CircleImageView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class SettingDialog extends Dialog {
@BindView(R.id.tv_dark)
TextView tv_dark;
@BindView(R.id.sb_brightness)
SeekBar sb_brightness;
@BindView(R.id.tv_bright)
TextView tv_bright;
@BindView(R.id.tv_xitong)
TextView tv_xitong;
@BindView(R.id.tv_subtract)
TextView tv_subtract;
@BindView(R.id.tv_size)
TextView tv_size;
@BindView(R.id.tv_add)
TextView tv_add;
@BindView(R.id.tv_qihei)
TextView tv_qihei;
@BindView(R.id.tv_default)
TextView tv_default;
@BindView(R.id.iv_bg_default)
CircleImageView iv_bg_default;
@BindView(R.id.iv_bg_1)
CircleImageView iv_bg1;
@BindView(R.id.iv_bg_2)
CircleImageView iv_bg2;
@BindView(R.id.iv_bg_3)
CircleImageView iv_bg3;
@BindView(R.id.iv_bg_4)
CircleImageView iv_bg4;
@BindView(R.id.tv_size_default)
TextView tv_size_default;
@BindView(R.id.tv_fzxinghei)
TextView tv_fzxinghei;
@BindView(R.id.tv_fzkatong)
TextView tv_fzkatong;
@BindView(R.id.tv_bysong)
TextView tv_bysong;
@BindView(R.id.tv_lhsize)
TextView tv_lineSpace;
@BindView(R.id.tv_lhsize_default)
TextView tv_lhsize_default;
private Config config;
private Boolean isSystem;
private SettingListener mSettingListener;
private int FONT_SIZE_MIN;
private int FONT_SIZE_MAX;
private int currentFontSize;
private int LINE_SPACE_MIN;
private int LINE_SPACE_MAX;
private int currentLineSpace;
Context mContext;
private SettingDialog(Context context, boolean flag, OnCancelListener listener) {
super(context, flag, listener);
mContext =context;
}
public SettingDialog(Context context) {
this(context, R.style.setting_dialog);
}
public SettingDialog(Context context, int themeResId) {
super(context, themeResId);
mContext=context;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setGravity(Gravity.BOTTOM);
setContentView(R.layout.zdialog_setting);
// 初始化View注入
ButterKnife.bind(this);
WindowManager m = getWindow().getWindowManager();
Display d = m.getDefaultDisplay();
WindowManager.LayoutParams p = getWindow().getAttributes();
p.width = d.getWidth();
// p.height = CommonUtil.getDpi(mContext);
getWindow().setAttributes(p);
FONT_SIZE_MIN = (int) getContext().getResources().getDimension(R.dimen.reading_min_text_size);
FONT_SIZE_MAX = (int) getContext().getResources().getDimension(R.dimen.reading_max_text_size);
LINE_SPACE_MAX =60;
LINE_SPACE_MIN =10;
config = Config.getInstance();
//初始化亮度
isSystem = config.isSystemLight();
setTextViewSelect(tv_xitong, isSystem);
setBrightness(config.getLight());
//初始化字体大小
currentFontSize = (int) config.getFontSize();
tv_size.setText(currentFontSize + "");
setTextViewSelect(tv_size_default, currentFontSize ==60);
//初始化行间距
currentLineSpace =(int) config.getLineSpace();
tv_lineSpace.setText(currentLineSpace+"");
setTextViewSelect(tv_lhsize_default, currentLineSpace==45);
//初始化字体
tv_default.setTypeface(config.getTypeface(Config.FONTTYPE_DEFAULT));
tv_qihei.setTypeface(config.getTypeface(Config.FONTTYPE_QIHEI));
// tv_fzxinghei.setTypeface(config.getTypeface(Config.FONTTYPE_FZXINGHEI));
// tv_fzkatong.setTypeface(config.getTypeface(Config.FONTTYPE_FZKATONG));
// tv_bysong.setTypeface(config.getTypeface(Config.FONTTYPE_BYSONG));
// tv_xinshou.setTypeface(config.getTypeface(Config.FONTTYPE_XINSHOU));
// tv_wawa.setTypeface(config.getTypeface(Config.FONTTYPE_WAWA));
selectTypeface(config.getTypefacePath());
selectBg(config.getBookBgType());
sb_brightness.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (progress > 10) {
changeBright(false, progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
//选择背景
private void selectBg(int type) {
switch (type) {
case Config.BOOK_BG_DEFAULT:
iv_bg_default.setBorderWidth(DisplayUtils.dp2px(getContext(), 2));
iv_bg1.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg2.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg3.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg4.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
break;
case Config.BOOK_BG_1:
iv_bg_default.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg1.setBorderWidth(DisplayUtils.dp2px(getContext(), 2));
iv_bg2.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg3.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg4.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
break;
case Config.BOOK_BG_2:
iv_bg_default.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg1.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg2.setBorderWidth(DisplayUtils.dp2px(getContext(), 2));
iv_bg3.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg4.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
break;
case Config.BOOK_BG_3:
iv_bg_default.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg1.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg2.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg3.setBorderWidth(DisplayUtils.dp2px(getContext(), 2));
iv_bg4.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
break;
case Config.BOOK_BG_4:
iv_bg_default.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg1.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg2.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg3.setBorderWidth(DisplayUtils.dp2px(getContext(), 0));
iv_bg4.setBorderWidth(DisplayUtils.dp2px(getContext(), 2));
break;
}
}
//设置字体
public void setBookBg(int type) {
config.setBookBg(type);
if (mSettingListener != null) {
mSettingListener.changeBookBg(type);
}
}
//选择字体
private void selectTypeface(String typeface) {
if (typeface.equals(Config.FONTTYPE_DEFAULT)) {
setTextViewSelect(tv_default, true);
setTextViewSelect(tv_qihei, false);
setTextViewSelect(tv_fzxinghei, false);
setTextViewSelect(tv_fzkatong, false);
setTextViewSelect(tv_bysong, false);
// setTextViewSelect(tv_xinshou, false);
// setTextViewSelect(tv_wawa, false);
} else if (typeface.equals(Config.FONTTYPE_QIHEI)) {
setTextViewSelect(tv_default, false);
setTextViewSelect(tv_qihei, true);
setTextViewSelect(tv_fzxinghei, false);
setTextViewSelect(tv_fzkatong, false);
setTextViewSelect(tv_bysong, false);
// setTextViewSelect(tv_xinshou, false);
// setTextViewSelect(tv_wawa, false);
} else if (typeface.equals(Config.FONTTYPE_FZXINGHEI)) {
setTextViewSelect(tv_default, false);
setTextViewSelect(tv_qihei, false);
setTextViewSelect(tv_fzxinghei, true);
setTextViewSelect(tv_fzkatong, false);
setTextViewSelect(tv_bysong, false);
// setTextViewSelect(tv_xinshou, true);
// setTextViewSelect(tv_wawa, false);
} else if (typeface.equals(Config.FONTTYPE_FZKATONG)) {
setTextViewSelect(tv_default, false);
setTextViewSelect(tv_qihei, false);
setTextViewSelect(tv_fzxinghei, false);
setTextViewSelect(tv_fzkatong, true);
setTextViewSelect(tv_bysong, false);
// setTextViewSelect(tv_xinshou, false);
// setTextViewSelect(tv_wawa, true);
} else if (typeface.equals(Config.FONTTYPE_BYSONG)) {
setTextViewSelect(tv_default, false);
setTextViewSelect(tv_qihei, false);
setTextViewSelect(tv_fzxinghei, false);
setTextViewSelect(tv_fzkatong, false);
setTextViewSelect(tv_bysong, true);
// setTextViewSelect(tv_xinshou, false);
// setTextViewSelect(tv_wawa, true);
}
}
//设置字体
public void setTypeface(String typeface) {
try {
config.setTypeface(typeface);
Typeface tface = config.getTypeface(typeface);
if (mSettingListener != null) {
mSettingListener.changeTypeFace(tface);
}
}catch (Exception e){
Log.e("SettingDialog", "setTypeface: ",e );
}
}
//设置亮度
public void setBrightness(float brightness) {
sb_brightness.setProgress((int) (brightness * 100));
}
//设置按钮选择的背景
private void setTextViewSelect(TextView textView, Boolean isSelect) {
if (isSelect) {
textView.setBackgroundDrawable(getContext().getResources().getDrawable(R.drawable.button_select_bg));
textView.setTextColor(getContext().getResources().getColor(R.color.read_dialog_button_select));
} else {
textView.setBackgroundDrawable(getContext().getResources().getDrawable(R.drawable.button_bg));
textView.setTextColor(getContext().getResources().getColor(R.color.white));
}
}
private void applyCompat() {
if (Build.VERSION.SDK_INT < 19) {
return;
}
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);//去掉信息栏
}
public Boolean isShow() {
return isShowing();
}
@OnClick({R.id.tv_dark, R.id.tv_bright, R.id.tv_xitong, R.id.tv_subtract, R.id.tv_add, R.id.tv_size_default, R.id.tv_qihei, R.id.tv_fzxinghei, R.id.tv_fzkatong,R.id.tv_bysong,
R.id.tv_default, R.id.iv_bg_default, R.id.iv_bg_1, R.id.iv_bg_2, R.id.iv_bg_3, R.id.iv_bg_4,R.id.tv_lhadd,R.id.tv_lhreduct,R.id.tv_lhsize_default})
public void onClick(View view) {
switch (view.getId()) {
case R.id.tv_dark:
break;
case R.id.tv_bright:
break;
case R.id.tv_xitong:
isSystem = !isSystem;
changeBright(isSystem, sb_brightness.getProgress());
break;
case R.id.tv_subtract:
subtractFontSize();
break;
case R.id.tv_add:
addFontSize();
break;
case R.id.tv_size_default:
defaultFontSize();
break;
case R.id.tv_qihei:
selectTypeface(Config.FONTTYPE_QIHEI);
setTypeface(Config.FONTTYPE_QIHEI);
break;
case R.id.tv_fzxinghei:
selectTypeface(Config.FONTTYPE_QIHEI);
setTypeface(Config.FONTTYPE_QIHEI);
// selectTypeface(Config.FONTTYPE_FZXINGHEI);
// setTypeface(Config.FONTTYPE_FZXINGHEI);
break;
case R.id.tv_fzkatong:
selectTypeface(Config.FONTTYPE_QIHEI);
setTypeface(Config.FONTTYPE_QIHEI);
//selectTypeface(Config.FONTTYPE_FZKATONG);
//setTypeface(Config.FONTTYPE_FZKATONG);
break;
case R.id.tv_bysong:
// selectTypeface(Config.FONTTYPE_BYSONG);
// setTypeface(Config.FONTTYPE_BYSONG);
selectTypeface(Config.FONTTYPE_QIHEI);
setTypeface(Config.FONTTYPE_QIHEI);
break;
// case R.id.tv_xinshou:
// selectTypeface(Config.FONTTYPE_XINSHOU);
// setTypeface(Config.FONTTYPE_XINSHOU);
// break;
// case R.id.tv_wawa:
// selectTypeface(Config.FONTTYPE_WAWA);
// setTypeface(Config.FONTTYPE_WAWA);
// break;
case R.id.tv_default:
selectTypeface(Config.FONTTYPE_DEFAULT);
setTypeface(Config.FONTTYPE_DEFAULT);
break;
case R.id.iv_bg_default:
setBookBg(Config.BOOK_BG_DEFAULT);
selectBg(Config.BOOK_BG_DEFAULT);
config.setDayOrNight(false);
break;
case R.id.iv_bg_1:
setBookBg(Config.BOOK_BG_1);
selectBg(Config.BOOK_BG_1); config.setDayOrNight(false);
break;
case R.id.iv_bg_2:
setBookBg(Config.BOOK_BG_2);
selectBg(Config.BOOK_BG_2); config.setDayOrNight(false);
break;
case R.id.iv_bg_3:
setBookBg(Config.BOOK_BG_3);
selectBg(Config.BOOK_BG_3); config.setDayOrNight(false);
break;
case R.id.iv_bg_4:
setBookBg(Config.BOOK_BG_4);
selectBg(Config.BOOK_BG_4); config.setDayOrNight(false);
break;
case R.id.tv_lhadd:
addLineSpace();
break;
case R.id.tv_lhreduct:
subtractLineSpace();
break;
case R.id.tv_lhsize_default:
defaultLineSpace();
break;
}
}
//变大行间距
private void addLineSpace() {
if (currentLineSpace < LINE_SPACE_MAX) {
currentLineSpace += 1;
tv_lineSpace.setText(currentLineSpace + "");
setTextViewSelect(tv_lhsize_default,false);
config.setLineSpace(currentLineSpace);
if (mSettingListener != null) {
mSettingListener.changeLineHeight(currentLineSpace);
}
}
}
//默认行间距
private void defaultLineSpace() {
currentLineSpace = (int) getContext().getResources().getDimension(R.dimen.reading_line_spacing);
tv_lineSpace.setText(currentLineSpace + "");
setTextViewSelect(tv_lhsize_default,true);
config.setLineSpace(currentLineSpace);
if (mSettingListener != null) {
mSettingListener.changeLineHeight(currentLineSpace);
}
}
//变小行间距
private void subtractLineSpace() {
if (currentLineSpace > LINE_SPACE_MIN) {
currentLineSpace -= 1;
setTextViewSelect(tv_lhsize_default,false);
tv_lineSpace.setText(currentLineSpace + "");
config.setLineSpace(currentLineSpace);
if (mSettingListener != null) {
mSettingListener.changeLineHeight(currentLineSpace);
}
}
}
//变大书本字体
private void addFontSize() {
if (currentFontSize < FONT_SIZE_MAX) {
currentFontSize += 1;
tv_size.setText(currentFontSize + "");
setTextViewSelect(tv_size_default,false);
config.setFontSize(currentFontSize);
if (mSettingListener != null) {
mSettingListener.changeFontSize(currentFontSize);
}
}
}
private void defaultFontSize() {
currentFontSize = (int) getContext().getResources().getDimension(R.dimen.reading_default_text_size);
tv_size.setText(currentFontSize + "");
setTextViewSelect(tv_size_default,true);
config.setFontSize(currentFontSize);
if (mSettingListener != null) {
mSettingListener.changeFontSize(currentFontSize);
}
}
//变小书本字体
private void subtractFontSize() {
if (currentFontSize > FONT_SIZE_MIN) {
currentFontSize -= 1;
setTextViewSelect(tv_size_default,false);
tv_size.setText(currentFontSize + "");
config.setFontSize(currentFontSize);
if (mSettingListener != null) {
mSettingListener.changeFontSize(currentFontSize);
}
}
}
//改变亮度
public void changeBright(Boolean isSystem, int brightness) {
float light = (float) (brightness / 100.0);
setTextViewSelect(tv_xitong, isSystem);
config.setSystemLight(isSystem);
config.setLight(light);
if (mSettingListener != null) {
mSettingListener.changeSystemBright(isSystem, light);
}
}
public void setSettingListener(SettingListener settingListener) {
this.mSettingListener = settingListener;
}
public interface SettingListener {
void changeSystemBright(Boolean isSystem, float brightness);
void changeFontSize(int fontSize);
void changeTypeFace(Typeface typeface);
void changeBookBg(int type);
void changeLineHeight(int lineHeight);
}
}

View File

@ -0,0 +1,116 @@
package com.novelbook.android.utils;
import java.util.ArrayList;
import java.util.List;
public class TRPage {
private long begin;
private long end;
private int pageNo;
private int chapterNo;
private boolean isLastPage;
private boolean isFirstPage;
private List<String> lines = new ArrayList<>();
private int bannerHeight=0;
private int nativeBannerStartLine=0;
private int nativeBannerHeight=0;
public TRPage( ){
}
public TRPage(String line){
lines.add(line);
}
public int getBannerHeight() {
return bannerHeight;
}
public void setBannerHeight(int bannerHeight) {
this.bannerHeight = bannerHeight;
}
public int getChapterNo() {
return chapterNo;
}
public void setChapterNo(int chapterNo) {
this.chapterNo = chapterNo;
}
public boolean isLastPage() {
return isLastPage;
}
public void setLastPage(boolean lastPage) {
isLastPage = lastPage;
}
public boolean isFirstPage() {
return isFirstPage;
}
public void setFirstPage(boolean firstPage) {
isFirstPage = firstPage;
}
public int getNativeBannerStartLine() {
return nativeBannerStartLine;
}
public void setNativeBannerStartLine(int nativeBannerStartLine) {
this.nativeBannerStartLine = nativeBannerStartLine;
}
public int getNativeBannerHeight() {
return nativeBannerHeight;
}
public void setNativeBannerHeight(int nativeBannerHeight) {
this.nativeBannerHeight = nativeBannerHeight;
}
public int getPageNo() {
return pageNo;
}
public void setPageNo(int pageNo) {
this.pageNo = pageNo;
}
public long getBegin() {
return begin;
}
public void setBegin(long begin) {
this.begin = begin;
}
public long getEnd() {
return end;
}
public void setEnd(long end) {
this.end = end;
}
public List<String> getLines() {
return lines;
}
public String getLineToString(){
String text ="";
if (lines != null){
for (String line : lines){
text += line;
}
}
return text;
}
public void setLines(List<String> lines) {
this.lines = lines;
}
}

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M17,3L7,3c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3L19,5c0,-1.1 -0.9,-2 -2,-2zM17,18l-5,-2.18L7,18L7,5h10v13z"/>
</vector>

View File

@ -0,0 +1,209 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.novelbook.android">
<!-- To access Google+ APIs: -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" /> <!-- <uses-permission android:name="android.permission.VIBRATE" /> -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- chanshanjia-->
<uses-permission android:name="android.permission.GET_TASKS"/>
<!--<uses-permission android:name="android.permission.WAKE_LOCK" />-->
<application
android:name=".MyApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:launchMode="singleInstance"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/ToolBarTheme"
android:usesCleartextTraffic="true">
<activity android:name=".ActivityAnounce" android:label="@string/title_annouce"></activity>
<activity
android:name=".Activity_cate_books"
android:label="@string/title_activity_cate_books"
android:launchMode="singleTask"
android:parentActivityName=".activity_cates"
android:screenOrientation="portrait"
android:theme="@style/ToolBarTheme.NoActionBar" />
<activity
android:name=".Activity_Search"
android:screenOrientation="portrait"
android:label="@string/title_activity_cates"
android:launchMode="singleTask"
android:parentActivityName=".Main2Activity"
android:theme="@style/ToolBarTheme.NoActionBar" />
<activity
android:name=".Activity_paihangbang"
android:screenOrientation="portrait"
android:label="@string/title_activity_paihangbang"
android:parentActivityName=".Main2Activity"
android:theme="@style/ToolBarTheme.NoActionBar" />
<activity
android:name=".Activity_ChgSource"
android:screenOrientation="portrait"
android:label="@string/title_Activity_ChgSource" />
<activity
android:name=".BookActivity"
android:label="@string/title_activity_book"
android:screenOrientation="portrait"
android:launchMode="standard"
android:theme="@style/ToolBarTheme.NoActionBar" />
<activity
android:name=".ReadActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:theme="@style/ToolBarTheme.NoActionBar" />
<activity
android:name=".Main2Activity"
android:launchMode="singleTop"
android:screenOrientation="portrait"
android:theme="@style/ToolBarTheme.NoActionBar">
</activity>
<activity
android:name=".AD.SplashActivity"
android:configChanges="keyboard|orientation|screenSize"
android:screenOrientation="portrait"
android:theme="@style/Theme.Splash">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".FileActivity"
android:screenOrientation="portrait"
android:label="@string/app_name"
android:theme="@style/ToolBarTheme.NoActionBar" />
<activity
android:name=".MarkActivity"
android:screenOrientation="portrait"
android:label="@string/app_name"
android:theme="@style/ToolBarTheme.NoActionBar" />
<activity
android:name=".filechooser.FileChooserActivity"
android:screenOrientation="portrait"
android:label="@string/app_name"
android:theme="@style/ToolBarTheme.NoActionBar" />
<activity
android:name=".Activity_cache"
android:screenOrientation="portrait"
android:label="@string/title_download"
android:theme="@style/ToolBarTheme.NoActionBar" />
<activity
android:name=".AD.AdvertisementViewActivity"
android:screenOrientation="portrait"
android:label="@string/title_ad"
android:theme="@style/ToolBarTheme.NoActionBar" />
<activity
android:name=".ActivitySetup"
android:screenOrientation="portrait"
android:label="@string/title_setup"
android:theme="@style/ToolBarTheme.NoActionBar" />
<service
android:name=".service.ServiceDownload"
android:exported="false" />
<!-- qq ad -->
<!-- chuanshanjia ad -->
<!-- <activity
android:name=".AD.qq.SplashActivity"
android:configChanges="keyboard|orientation|screenSize"
android:screenOrientation="portrait"
android:theme="@style/Theme.Splash">
</activity>-->
<service
android:name="com.qq.e.comm.DownloadService"
android:exported="false" />
<activity
android:name="com.qq.e.ads.ADActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize" />
<activity
android:name="com.qq.e.ads.PortraitADActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="portrait" />
<activity
android:name="com.qq.e.ads.LandscapeADActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:screenOrientation="landscape" />
<uses-library
android:name="org.apache.http.legacy"
android:required="false" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/gdt_file_path" />
</provider> <!-- qq ad end -->
<!-- chuanshanjia ad -->
<!--<activity
android:name=".AD.toutiao.SplashActivity"
android:configChanges="keyboard|orientation|screenSize"
android:screenOrientation="portrait"
android:theme="@style/Theme.Splash">
</activity>
-->
<!-- <uses-library
android:name="org.apache.http.legacy"
android:required="false" />
<provider
android:name="com.bytedance.sdk.openadsdk.TTFileProvider"
android:authorities="${applicationId}.TTFileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
<provider
android:name="com.bytedance.sdk.openadsdk.multipro.TTMultiProvider"
android:authorities="${applicationId}.TTMultiProvider"
android:exported="false" />-->
<!-- chuanshanjia ad end-->
<!--
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
-->
<!-- UMENG -->
<meta-data
android:name="UMENG_APPKEY"
android:value="5cd6238a570df375c3000cc9" /> <!-- <meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}"/> -->
<!--<meta-data android:name="UMENG_CHANNEL" android:value="debug" />-->
<meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}" />
<!-- google ad-->
<!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="${MOBAPPID}"/>
</application>
</manifest>

Some files were not shown because too many files have changed in this diff Show More