Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
android_book
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
android
android_book
Commits
b6ce8584
Commit
b6ce8584
authored
Sep 26, 2024
by
jyx
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加分页
parent
31277fae
Changes
43
Hide whitespace changes
Inline
Side-by-side
Showing
43 changed files
with
4544 additions
and
59 deletions
+4544
-59
build.gradle
book/app/build.gradle
+8
-3
AndroidManifest.xml
book/app/src/main/AndroidManifest.xml
+4
-0
litepal.xml
book/app/src/main/assets/litepal.xml
+32
-0
MintsApplication.java
...src/main/java/com/mints/enjoyboxjia/MintsApplication.java
+7
-1
Constant.kt
...pp/src/main/java/com/mints/enjoyboxjia/common/Constant.kt
+7
-3
BookChapterBean.java
...java/com/mints/enjoyboxjia/mvp/model/BookChapterBean.java
+62
-0
BookContentBean.java
...java/com/mints/enjoyboxjia/mvp/model/BookContentBean.java
+105
-13
LoanService.java
.../src/main/java/com/mints/enjoyboxjia/net/LoanService.java
+12
-0
AnimType.java
...pp/src/main/java/com/mints/enjoyboxjia/read/AnimType.java
+15
-0
BookManager.java
...src/main/java/com/mints/enjoyboxjia/read/BookManager.java
+260
-0
Constants.java
...p/src/main/java/com/mints/enjoyboxjia/read/Constants.java
+40
-0
Direction.java
...p/src/main/java/com/mints/enjoyboxjia/read/Direction.java
+5
-0
FileUtils.java
...p/src/main/java/com/mints/enjoyboxjia/read/FileUtils.java
+279
-0
NetworkPageLoader.java
...in/java/com/mints/enjoyboxjia/read/NetworkPageLoader.java
+335
-0
PageLoader.java
.../src/main/java/com/mints/enjoyboxjia/read/PageLoader.java
+653
-0
YPageView.java
...p/src/main/java/com/mints/enjoyboxjia/read/YPageView.java
+260
-0
AlikeAnim.java
.../main/java/com/mints/enjoyboxjia/read/anim/AlikeAnim.java
+795
-0
ContentScaleAnimation.java
...om/mints/enjoyboxjia/read/anim/ContentScaleAnimation.java
+63
-0
CoverAnim.java
.../main/java/com/mints/enjoyboxjia/read/anim/CoverAnim.java
+49
-0
NoneAnim.java
...c/main/java/com/mints/enjoyboxjia/read/anim/NoneAnim.java
+153
-0
PageAnim.java
...c/main/java/com/mints/enjoyboxjia/read/anim/PageAnim.java
+140
-0
Rotate3DAnimation.java
...va/com/mints/enjoyboxjia/read/anim/Rotate3DAnimation.java
+111
-0
SlideAnim.java
.../main/java/com/mints/enjoyboxjia/read/anim/SlideAnim.java
+230
-0
BookModel.java
...ain/java/com/mints/enjoyboxjia/read/models/BookModel.java
+126
-0
BookRecordModel.java
...va/com/mints/enjoyboxjia/read/models/BookRecordModel.java
+70
-0
ChapterInfoBean.java
...va/com/mints/enjoyboxjia/read/models/ChapterInfoBean.java
+27
-0
TxtChapterModel.java
...va/com/mints/enjoyboxjia/read/models/TxtChapterModel.java
+179
-0
TxtPageModel.java
.../java/com/mints/enjoyboxjia/read/models/TxtPageModel.java
+13
-0
BookReadActivity.kt
...va/com/mints/enjoyboxjia/ui/activitys/BookReadActivity.kt
+2
-5
BookSearchActivity.kt
.../com/mints/enjoyboxjia/ui/activitys/BookSearchActivity.kt
+7
-2
LongBookReadActivity.kt
...om/mints/enjoyboxjia/ui/activitys/LongBookReadActivity.kt
+173
-0
MainActivity.kt
...n/java/com/mints/enjoyboxjia/ui/activitys/MainActivity.kt
+5
-1
WatchRecordActivity.kt
...com/mints/enjoyboxjia/ui/activitys/WatchRecordActivity.kt
+2
-1
BookCityFragment.kt
...ava/com/mints/enjoyboxjia/ui/fragment/BookCityFragment.kt
+4
-4
BookListFragment.kt
...ava/com/mints/enjoyboxjia/ui/fragment/BookListFragment.kt
+2
-2
BookShelfFragment.kt
...va/com/mints/enjoyboxjia/ui/fragment/BookShelfFragment.kt
+9
-7
MyFragment.kt
...main/java/com/mints/enjoyboxjia/ui/fragment/MyFragment.kt
+4
-1
StringUtils.java
...rc/main/java/com/mints/enjoyboxjia/utils/StringUtils.java
+128
-0
Utils.java
book/app/src/main/java/com/mints/library/utils/Utils.java
+1
-1
activity_long_book_read.xml
book/app/src/main/res/layout/activity_long_book_read.xml
+153
-0
item_bookshelf.xml
book/app/src/main/res/layout/item_bookshelf.xml
+7
-7
item_hotbook.xml
book/app/src/main/res/layout/item_hotbook.xml
+5
-6
item_list_count.xml
book/app/src/main/res/layout/item_list_count.xml
+2
-2
No files found.
book/app/build.gradle
View file @
b6ce8584
...
@@ -178,8 +178,10 @@ dependencies {
...
@@ -178,8 +178,10 @@ dependencies {
// 网络请求
// 网络请求
implementation
'com.squareup.retrofit2:retrofit:2.7.1'
implementation
'com.squareup.retrofit2:retrofit:2.7.1'
implementation
'com.squareup.retrofit2:adapter-rxjava:2.1.0'
implementation
'com.squareup.retrofit2:adapter-rxjava:2.1.0'
implementation
'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
// 异步
// 异步
implementation
"io.reactivex.rxjava2:rxjava:2.2.6"
implementation
"io.reactivex.rxjava2:rxjava:2.2.10"
implementation
'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation
'io.reactivex:rxandroid:1.2.1'
implementation
'io.reactivex:rxandroid:1.2.1'
// 状态栏适配
// 状态栏适配
implementation
'com.readystatesoftware.systembartint:systembartint:1.0.3'
implementation
'com.readystatesoftware.systembartint:systembartint:1.0.3'
...
@@ -233,8 +235,8 @@ dependencies {
...
@@ -233,8 +235,8 @@ dependencies {
// 三方接入
// 三方接入
// talkingdata接入
// talkingdata接入
// 友盟统计SDK
// 友盟统计SDK
implementation
'com.umeng.umsdk:common:9.6.3'
// 必选
implementation
'com.umeng.umsdk:common:9.6.3'
// 必选
implementation
'com.umeng.umsdk:asms:1.8.0'
// 必选
implementation
'com.umeng.umsdk:asms:1.8.0'
// 必选
implementation
'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'
implementation
'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'
// 支付
// 支付
api
project
(
':rxpay'
)
api
project
(
':rxpay'
)
...
@@ -249,6 +251,9 @@ dependencies {
...
@@ -249,6 +251,9 @@ dependencies {
implementation
'com.squareup:javawriter:2.1.1'
implementation
'com.squareup:javawriter:2.1.1'
// umeng
// umeng
// 数据库
implementation
'org.litepal.guolindev:core:3.1.1'
// 穿山甲聚合 接入【穿山甲、快手】
// 穿山甲聚合 接入【穿山甲、快手】
implementation
"com.pangle.cn:mediation-sdk:6.1.2.5"
implementation
"com.pangle.cn:mediation-sdk:6.1.2.5"
// 穿山甲Applog 上报组件(必须)
// 穿山甲Applog 上报组件(必须)
...
...
book/app/src/main/AndroidManifest.xml
View file @
b6ce8584
...
@@ -117,6 +117,10 @@
...
@@ -117,6 +117,10 @@
android:name=
".ui.activitys.BookReadActivity"
android:name=
".ui.activitys.BookReadActivity"
android:exported=
"false"
android:exported=
"false"
android:screenOrientation=
"portrait"
/>
android:screenOrientation=
"portrait"
/>
<activity
android:name=
".ui.activitys.LongBookReadActivity"
android:exported=
"false"
android:screenOrientation=
"portrait"
/>
<activity
<activity
android:name=
".ui.activitys.WxLoginActivity"
android:name=
".ui.activitys.WxLoginActivity"
android:configChanges=
"orientation|screenSize|keyboardHidden"
android:configChanges=
"orientation|screenSize|keyboardHidden"
...
...
book/app/src/main/assets/litepal.xml
0 → 100644
View file @
b6ce8584
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<!--
Define the database name of your application.
By default each database name should be end with .db.
If you didn't name your database end with .db,
LitePal would plus the suffix automatically for you.
For example:
<dbname value="demo" />
-->
<dbname
value=
"bookRepository"
/>
<!--
Define the version of your database. Each time you want
to upgrade your database, the version tag would helps.
Modify the models you defined in the mapping tag, and just
make the version value plus one, the upgrade of database
will be processed automatically without concern.
For example:
<version value="1" />
-->
<version
value=
"1"
/>
<list>
<mapping
class=
"com.mints.enjoyboxjia.read.models.BookModel"
/>
<mapping
class=
"com.mints.enjoyboxjia.read.models.TxtChapterModel"
/>
<mapping
class=
"com.mints.enjoyboxjia.read.models.BookRecordModel"
/>
</list>
</litepal>
\ No newline at end of file
book/app/src/main/java/com/mints/enjoyboxjia/MintsApplication.java
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
;
package
com
.
mints
.
enjoyboxjia
;
import
android.app.Application
;
import
android.content.Context
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.Intent
;
...
@@ -26,7 +27,6 @@ import com.orhanobut.logger.FormatStrategy;
...
@@ -26,7 +27,6 @@ import com.orhanobut.logger.FormatStrategy;
import
com.orhanobut.logger.Logger
;
import
com.orhanobut.logger.Logger
;
import
com.orhanobut.logger.PrettyFormatStrategy
;
import
com.orhanobut.logger.PrettyFormatStrategy
;
import
com.tencent.bugly.crashreport.CrashReport
;
import
com.tencent.bugly.crashreport.CrashReport
;
import
com.umeng.commonsdk.UMConfigure
;
import
rx.Scheduler
;
import
rx.Scheduler
;
import
rx.schedulers.Schedulers
;
import
rx.schedulers.Schedulers
;
...
@@ -39,6 +39,7 @@ import rx.schedulers.Schedulers;
...
@@ -39,6 +39,7 @@ import rx.schedulers.Schedulers;
public
class
MintsApplication
extends
MultiDexApplication
{
public
class
MintsApplication
extends
MultiDexApplication
{
private
static
Context
mContext
;
private
static
Context
mContext
;
private
static
MintsApplication
mApplication
;
public
static
String
OAID
=
""
;
public
static
String
OAID
=
""
;
private
static
LocalBroadcastManager
mLocalBroadcatManager
;
private
static
LocalBroadcastManager
mLocalBroadcatManager
;
private
Scheduler
defaultSubscribeScheduler
;
private
Scheduler
defaultSubscribeScheduler
;
...
@@ -52,9 +53,14 @@ public class MintsApplication extends MultiDexApplication {
...
@@ -52,9 +53,14 @@ public class MintsApplication extends MultiDexApplication {
return
mContext
;
return
mContext
;
}
}
public
static
MintsApplication
getApplication
()
{
return
mApplication
;
}
@Override
@Override
public
void
onCreate
()
{
public
void
onCreate
()
{
super
.
onCreate
();
super
.
onCreate
();
mApplication
=
this
;
mContext
=
this
.
getApplicationContext
();
mContext
=
this
.
getApplicationContext
();
// 友盟SDK预初始化函数
// 友盟SDK预初始化函数
...
...
book/app/src/main/java/com/mints/enjoyboxjia/common/Constant.kt
View file @
b6ce8584
...
@@ -18,8 +18,12 @@ object Constant {
...
@@ -18,8 +18,12 @@ object Constant {
const
val
PAGE_SIZE
=
10
const
val
PAGE_SIZE
=
10
const
val
ROUTE_BOOK_ID
=
"BOOK_ID"
// 协议地址
// 协议地址
var
REGISTER_URL
=
BuildConfig
.
MainIp
+
"/agreements/${VersionUtils.getEndPkg()}/yhxy.html"
//注册协议
var
REGISTER_URL
=
var
PRIVACY_URL
=
BuildConfig
.
MainIp
+
"/agreements/${VersionUtils.getEndPkg()}/syzc.html"
//隐私协议
BuildConfig
.
MainIp
+
"/agreements/${VersionUtils.getEndPkg()}/yhxy.html"
//注册协议
var
MEMBERS_URL
=
BuildConfig
.
MainIp
+
"/agreements/${VersionUtils.getEndPkg()}/gmxy.html"
//会员付费服务协议
var
PRIVACY_URL
=
BuildConfig
.
MainIp
+
"/agreements/${VersionUtils.getEndPkg()}/syzc.html"
//隐私协议
var
MEMBERS_URL
=
BuildConfig
.
MainIp
+
"/agreements/${VersionUtils.getEndPkg()}/gmxy.html"
//会员付费服务协议
}
}
\ No newline at end of file
book/app/src/main/java/com/mints/enjoyboxjia/mvp/model/BookChapterBean.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
mvp
.
model
;
import
java.io.Serializable
;
/**
* @author Assen
* @date 2024/9/25
* @desc
*/
public
class
BookChapterBean
implements
Serializable
{
/**
* id : 408212
* chapterId : 407740
* content :
* 女儿来到这个世界上的第五年。
* 出门上班前,我照常给了她一个告别吻。
* 女儿神色呆滞,没有任何回应。
* 我有些失望地把头放回冰箱,或许,下次放在烤箱里,这个吻会更有温度。
* contentMd :
* 女儿来到这个世界上的第五年。
* 出门上班前,我照常给了她一个告别吻。
* 女儿神色呆滞,没有任何回应。
* 我有些失望地把头放回冰箱,或许,下次放在烤箱里,这个吻会更有温度。
*/
private
String
id
;
private
String
chapterId
;
private
String
content
;
private
String
contentMd
;
public
String
getId
()
{
return
id
;
}
public
void
setId
(
String
id
)
{
this
.
id
=
id
;
}
public
String
getChapterId
()
{
return
chapterId
;
}
public
void
setChapterId
(
String
chapterId
)
{
this
.
chapterId
=
chapterId
;
}
public
String
getContent
()
{
return
content
;
}
public
void
setContent
(
String
content
)
{
this
.
content
=
content
;
}
public
String
getContentMd
()
{
return
contentMd
;
}
public
void
setContentMd
(
String
contentMd
)
{
this
.
contentMd
=
contentMd
;
}
}
book/app/src/main/java/com/mints/enjoyboxjia/mvp/model/BookContentBean.java
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
mvp
.
model
;
package
com
.
mints
.
enjoyboxjia
.
mvp
.
model
;
import
com.mints.enjoyboxjia.read.models.TxtChapterModel
;
import
java.io.Serializable
;
import
java.io.Serializable
;
import
java.util.List
;
public
class
BookContentBean
implements
Serializable
{
public
class
BookContentBean
implements
Serializable
{
/**
/**
...
@@ -44,13 +47,13 @@ public class BookContentBean implements Serializable {
...
@@ -44,13 +47,13 @@ public class BookContentBean implements Serializable {
private
int
id
;
private
int
id
;
private
String
userId
;
private
String
userId
;
private
Object
username
;
private
String
username
;
private
String
title
;
private
String
title
;
private
String
avatar
;
private
String
avatar
;
private
String
author
;
private
String
author
;
private
String
summary
;
private
String
summary
;
private
Object
content
;
private
String
content
;
private
Object
contentMd
;
private
String
contentMd
;
private
String
free
;
private
String
free
;
private
String
freeMd
;
private
String
freeMd
;
private
String
charge
;
private
String
charge
;
...
@@ -59,7 +62,7 @@ public class BookContentBean implements Serializable {
...
@@ -59,7 +62,7 @@ public class BookContentBean implements Serializable {
private
int
isStick
;
private
int
isStick
;
private
int
isPublish
;
private
int
isPublish
;
private
int
isOriginal
;
private
int
isOriginal
;
private
String
originalUrl
;
private
String
originalUrl
;
private
int
readType
;
private
int
readType
;
private
int
bookLegumes
;
private
int
bookLegumes
;
private
int
quantity
;
private
int
quantity
;
...
@@ -76,7 +79,7 @@ public class BookContentBean implements Serializable {
...
@@ -76,7 +79,7 @@ public class BookContentBean implements Serializable {
private
int
collectCount
;
private
int
collectCount
;
private
boolean
activeReadType
;
private
boolean
activeReadType
;
private
int
freeNum
;
private
int
freeNum
;
private
Object
articleChapterList
;
private
List
<
ArticleChapterList
>
articleChapterList
;
public
int
getId
()
{
public
int
getId
()
{
return
id
;
return
id
;
...
@@ -98,7 +101,7 @@ public class BookContentBean implements Serializable {
...
@@ -98,7 +101,7 @@ public class BookContentBean implements Serializable {
return
username
;
return
username
;
}
}
public
void
setUsername
(
Object
username
)
{
public
void
setUsername
(
String
username
)
{
this
.
username
=
username
;
this
.
username
=
username
;
}
}
...
@@ -134,19 +137,19 @@ public class BookContentBean implements Serializable {
...
@@ -134,19 +137,19 @@ public class BookContentBean implements Serializable {
this
.
summary
=
summary
;
this
.
summary
=
summary
;
}
}
public
Object
getContent
()
{
public
String
getContent
()
{
return
content
;
return
content
;
}
}
public
void
setContent
(
Object
content
)
{
public
void
setContent
(
String
content
)
{
this
.
content
=
content
;
this
.
content
=
content
;
}
}
public
Object
getContentMd
()
{
public
String
getContentMd
()
{
return
contentMd
;
return
contentMd
;
}
}
public
void
setContentMd
(
Object
contentMd
)
{
public
void
setContentMd
(
String
contentMd
)
{
this
.
contentMd
=
contentMd
;
this
.
contentMd
=
contentMd
;
}
}
...
@@ -214,7 +217,7 @@ public class BookContentBean implements Serializable {
...
@@ -214,7 +217,7 @@ public class BookContentBean implements Serializable {
this
.
isOriginal
=
isOriginal
;
this
.
isOriginal
=
isOriginal
;
}
}
public
String
getOriginalUrl
()
{
public
String
getOriginalUrl
()
{
return
originalUrl
;
return
originalUrl
;
}
}
...
@@ -350,11 +353,100 @@ public class BookContentBean implements Serializable {
...
@@ -350,11 +353,100 @@ public class BookContentBean implements Serializable {
this
.
freeNum
=
freeNum
;
this
.
freeNum
=
freeNum
;
}
}
public
Object
getArticleChapterList
()
{
public
List
<
ArticleChapterList
>
getArticleChapterList
()
{
return
articleChapterList
;
return
articleChapterList
;
}
}
public
void
setArticleChapterList
(
Object
articleChapterList
)
{
public
void
setArticleChapterList
(
List
<
ArticleChapterList
>
articleChapterList
)
{
this
.
articleChapterList
=
articleChapterList
;
this
.
articleChapterList
=
articleChapterList
;
}
}
public
static
class
ArticleChapterList
implements
Serializable
{
/**
* id : 407740
* bookId : 80670
* chapterNum : 1
* chapterName : 导语
* wordCount : null
* isVip : 0
* createTime : null
* updateTime : null
*/
private
int
id
;
private
int
bookId
;
private
int
chapterNum
;
private
String
chapterName
;
private
Object
wordCount
;
private
int
isVip
;
private
Object
createTime
;
private
Object
updateTime
;
public
int
getId
()
{
return
id
;
}
public
void
setId
(
int
id
)
{
this
.
id
=
id
;
}
public
int
getBookId
()
{
return
bookId
;
}
public
void
setBookId
(
int
bookId
)
{
this
.
bookId
=
bookId
;
}
public
int
getChapterNum
()
{
return
chapterNum
;
}
public
void
setChapterNum
(
int
chapterNum
)
{
this
.
chapterNum
=
chapterNum
;
}
public
String
getChapterName
()
{
return
chapterName
;
}
public
void
setChapterName
(
String
chapterName
)
{
this
.
chapterName
=
chapterName
;
}
public
Object
getWordCount
()
{
return
wordCount
;
}
public
void
setWordCount
(
Object
wordCount
)
{
this
.
wordCount
=
wordCount
;
}
public
int
getIsVip
()
{
return
isVip
;
}
public
void
setIsVip
(
int
isVip
)
{
this
.
isVip
=
isVip
;
}
public
Object
getCreateTime
()
{
return
createTime
;
}
public
void
setCreateTime
(
Object
createTime
)
{
this
.
createTime
=
createTime
;
}
public
Object
getUpdateTime
()
{
return
updateTime
;
}
public
void
setUpdateTime
(
Object
updateTime
)
{
this
.
updateTime
=
updateTime
;
}
}
}
}
book/app/src/main/java/com/mints/enjoyboxjia/net/LoanService.java
View file @
b6ce8584
...
@@ -6,6 +6,7 @@ import com.google.gson.JsonObject;
...
@@ -6,6 +6,7 @@ import com.google.gson.JsonObject;
import
com.mints.enjoyboxjia.BuildConfig
;
import
com.mints.enjoyboxjia.BuildConfig
;
import
com.mints.enjoyboxjia.mvp.model.BannerList
;
import
com.mints.enjoyboxjia.mvp.model.BannerList
;
import
com.mints.enjoyboxjia.mvp.model.BaseResponse
;
import
com.mints.enjoyboxjia.mvp.model.BaseResponse
;
import
com.mints.enjoyboxjia.mvp.model.BookChapterBean
;
import
com.mints.enjoyboxjia.mvp.model.BookList2Bean
;
import
com.mints.enjoyboxjia.mvp.model.BookList2Bean
;
import
com.mints.enjoyboxjia.mvp.model.HotBookTypeList
;
import
com.mints.enjoyboxjia.mvp.model.HotBookTypeList
;
import
com.mints.enjoyboxjia.mvp.model.BookContentBean
;
import
com.mints.enjoyboxjia.mvp.model.BookContentBean
;
...
@@ -21,10 +22,12 @@ import com.orhanobut.logger.Logger;
...
@@ -21,10 +22,12 @@ import com.orhanobut.logger.Logger;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
import
io.reactivex.Single
;
import
okhttp3.OkHttpClient
;
import
okhttp3.OkHttpClient
;
import
okhttp3.logging.HttpLoggingInterceptor
;
import
okhttp3.logging.HttpLoggingInterceptor
;
import
retrofit2.Retrofit
;
import
retrofit2.Retrofit
;
import
retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
;
import
retrofit2.adapter.rxjava.RxJavaCallAdapterFactory
;
import
retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
;
import
retrofit2.http.Body
;
import
retrofit2.http.Body
;
import
retrofit2.http.POST
;
import
retrofit2.http.POST
;
import
rx.Observable
;
import
rx.Observable
;
...
@@ -210,6 +213,14 @@ public interface LoanService {
...
@@ -210,6 +213,14 @@ public interface LoanService {
@POST
(
"api/book/info"
)
@POST
(
"api/book/info"
)
Observable
<
BaseResponse
<
BookContentBean
>>
getBookDetail
(
@Body
Map
<
String
,
Object
>
vo
);
Observable
<
BaseResponse
<
BookContentBean
>>
getBookDetail
(
@Body
Map
<
String
,
Object
>
vo
);
/**
* 获取章节数据
*
* @return
*/
@POST
(
"api/book/chapterinfo"
)
Single
<
BaseResponse
<
BookChapterBean
>>
getChapterInfo
(
@Body
Map
<
String
,
Object
>
vo
);
/**
/**
* 添加阅读记录
* 添加阅读记录
*
*
...
@@ -276,6 +287,7 @@ public interface LoanService {
...
@@ -276,6 +287,7 @@ public interface LoanService {
.
baseUrl
(
BuildConfig
.
MainIp
)
.
baseUrl
(
BuildConfig
.
MainIp
)
.
addConverterFactory
(
GsonConverterFactory
.
create
())
.
addConverterFactory
(
GsonConverterFactory
.
create
())
.
addCallAdapterFactory
(
RxJavaCallAdapterFactory
.
create
())
.
addCallAdapterFactory
(
RxJavaCallAdapterFactory
.
create
())
.
addCallAdapterFactory
(
RxJava2CallAdapterFactory
.
create
())
.
build
();
.
build
();
...
...
book/app/src/main/java/com/mints/enjoyboxjia/read/AnimType.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
;
public
enum
AnimType
{
NONE
(
0
),
SLIDE
(
1
),
COVER
(
2
),
ALIKE
(
3
);
final
int
type
;
AnimType
(
int
type
)
{
this
.
type
=
type
;
}
public
int
getType
()
{
return
type
;
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/BookManager.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
;
import
com.mints.enjoyboxjia.read.models.BookModel
;
import
com.mints.enjoyboxjia.read.models.TxtChapterModel
;
import
org.litepal.LitePal
;
import
java.io.File
;
import
java.lang.ref.WeakReference
;
import
java.util.HashMap
;
import
java.util.Map
;
import
io.reactivex.Single
;
import
io.reactivex.SingleEmitter
;
import
io.reactivex.SingleOnSubscribe
;
public
class
BookManager
{
private
static
final
String
TAG
=
"BookManager"
;
private
String
chapterName
;
private
String
bookId
;
private
long
chapterLen
;
private
long
position
;
private
Map
<
String
,
Cache
>
cacheMap
=
new
HashMap
<>();
private
static
volatile
BookManager
sInstance
;
public
static
BookManager
getInstance
(){
if
(
sInstance
==
null
){
synchronized
(
BookManager
.
class
){
if
(
sInstance
==
null
){
sInstance
=
new
BookManager
();
}
}
}
return
sInstance
;
}
public
boolean
openChapter
(
String
bookId
,
String
chapterName
){
return
openChapter
(
bookId
,
chapterName
,
0
);
}
public
boolean
openChapter
(
String
bookId
,
String
chapterName
,
long
position
){
//如果文件不存在,则打开失败
File
file
=
new
File
(
Constants
.
BOOK_CACHE_PATH
+
bookId
+
File
.
separator
+
chapterName
+
FileUtils
.
SUFFIX_NB
);
if
(!
file
.
exists
()){
return
false
;
}
this
.
bookId
=
bookId
;
this
.
chapterName
=
chapterName
;
this
.
position
=
position
;
createCache
();
return
true
;
}
private
void
createCache
(){
//创建Cache
if
(!
cacheMap
.
containsKey
(
chapterName
)){
Cache
cache
=
new
Cache
();
File
file
=
getBookFile
(
bookId
,
chapterName
);
//TODO:数据加载默认utf-8(以后会增加判断),FileUtils采用Reader获取数据的,可能用byte会更好一点
char
[]
array
=
FileUtils
.
getFileContent
(
file
).
toCharArray
();
WeakReference
<
char
[]>
charReference
=
new
WeakReference
<
char
[]>(
array
);
cache
.
size
=
array
.
length
;
cache
.
data
=
charReference
;
cacheMap
.
put
(
chapterName
,
cache
);
chapterLen
=
cache
.
size
;
}
else
{
chapterLen
=
cacheMap
.
get
(
chapterName
).
getSize
();
}
}
public
void
setPosition
(
long
position
){
this
.
position
=
position
;
}
public
long
getPosition
(){
return
position
;
}
//获取上一段
public
String
getPrevPara
(){
//首先判断是否Position已经达到起始位置,已经越界
if
(
position
<
0
){
return
null
;
}
//初始化从后向前获取的起始点,终止点,文本
int
end
=
(
int
)
position
;
int
begin
=
end
;
char
[]
array
=
getContent
();
while
(
begin
>=
0
)
{
//判断指针是否达到章节的起始位置
char
character
=
array
[
begin
];
//获取当前指针下的字符
//判断当前字符是否为换行,如果为换行,就代表获取到了一个段落,并退出。
//有可能发生初始指针指的就是换行符的情况。
if
((
character
+
""
).
equals
(
"\n"
)
&&
begin
!=
end
)
{
position
=
begin
;
//当当前指针指向换行符的时候向后退一步
begin
++;
break
;
}
//向前进一步
begin
--;
}
//最后end获取到段落的起始点,begin是段落的终止点。
//当越界的时候,保证begin在章节内
if
(
begin
<
0
){
begin
=
0
;
//在章节内
position
=
-
1
;
//越界
}
int
size
=
end
+
1
-
begin
;
return
new
String
(
array
,
begin
,
size
);
}
//获取下一段
public
String
getNextPara
(){
//首先判断是否Position已经达到终点位置
if
(
position
>=
chapterLen
){
return
null
;
}
//初始化起始点,终止点。
int
begin
=
(
int
)
position
;
int
end
=
begin
;
char
[]
array
=
getContent
();
while
(
end
<
chapterLen
)
{
//判断指针是否在章节的末尾位置
char
character
=
array
[
end
];
//获取当前指针下的字符
//判断当前字符是否为换行,如果为换行,就代表获取到了一个段落,并退出。
//有可能发生初始指针指的就是换行符的情况。
//这里当遇到\n的时候,不需要回退
if
((
character
+
""
).
equals
(
"\n"
)
&&
begin
!=
end
){
++
end
;
//指向下一字段
position
=
end
;
break
;
}
//指向下一字段
end
++;
}
//所要获取的字段的长度
int
size
=
end
-
begin
;
return
new
String
(
array
,
begin
,
size
);
}
//获取章节的内容
public
char
[]
getContent
()
{
if
(
cacheMap
.
size
()
==
0
){
return
new
char
[
1
];
}
char
[]
block
=
cacheMap
.
get
(
chapterName
).
getData
().
get
();
if
(
block
==
null
)
{
File
file
=
getBookFile
(
bookId
,
chapterName
);
block
=
FileUtils
.
getFileContent
(
file
).
toCharArray
();
Cache
cache
=
cacheMap
.
get
(
chapterName
);
cache
.
data
=
new
WeakReference
<
char
[]>(
block
);
}
return
block
;
}
public
long
getChapterLen
(){
return
chapterLen
;
}
public
void
clear
(){
cacheMap
.
clear
();
position
=
0
;
chapterLen
=
0
;
}
/**
* 创建或获取存储文件
* @param folderName
* @param fileName
* @return
*/
public
static
File
getBookFile
(
String
folderName
,
String
fileName
){
return
FileUtils
.
getFile
(
Constants
.
BOOK_CACHE_PATH
+
folderName
+
File
.
separator
+
fileName
+
FileUtils
.
SUFFIX_NB
);
}
public
static
long
getBookSize
(
String
folderName
){
return
FileUtils
.
getDirSize
(
FileUtils
.
getFolder
(
Constants
.
BOOK_CACHE_PATH
+
folderName
));
}
/**
* 根据文件名判断是否被缓存过 (因为可能数据库显示被缓存过,但是文件中却没有的情况,所以需要根据文件判断是否被缓存
* 过)
* @param folderName : bookId
* @param fileName: chapterName
* @return
*/
public
static
boolean
isChapterCached
(
String
folderName
,
String
fileName
){
File
file
=
new
File
(
Constants
.
BOOK_CACHE_PATH
+
folderName
+
File
.
separator
+
fileName
+
FileUtils
.
SUFFIX_NB
);
return
file
.
exists
();
}
public
class
Cache
{
private
long
size
;
private
WeakReference
<
char
[]>
data
;
public
WeakReference
<
char
[]>
getData
()
{
return
data
;
}
public
void
setData
(
WeakReference
<
char
[]>
data
)
{
this
.
data
=
data
;
}
public
long
getSize
()
{
return
size
;
}
public
void
setSize
(
long
size
)
{
this
.
size
=
size
;
}
}
public
Single
<
Void
>
deleteCollBookInRx
(
BookModel
bean
)
{
return
Single
.
create
(
new
SingleOnSubscribe
<
Void
>()
{
@Override
public
void
subscribe
(
SingleEmitter
<
Void
>
e
)
throws
Exception
{
//查看文本中是否存在删除的数据
LitePal
.
delete
(
BookModel
.
class
,
bean
.
getId
());
//删除任务
// deleteDownloadTask(bean.get_id());
//删除目录
LitePal
.
delete
(
TxtChapterModel
.
class
,
bean
.
getId
());
//删除CollBook
}
});
}
public
BookModel
getCollectedBook
(
String
bookId
){
return
LitePal
.
where
(
"id=?"
,
bookId
).
findFirst
(
BookModel
.
class
);
}
//存储已收藏书籍
public
void
saveCollBookWithAsync
(
BookModel
bean
){
//启动异步存储
boolean
resuly
=
bean
.
save
();
// mSession.startAsyncSession()
// .runInTx(
// () -> {
// if (bean.getBookChapters() != null){
// // 存储BookChapterBean
// mSession.getBookChapterBeanDao()
// .insertOrReplaceInTx(bean.getBookChapters());
// }
// //存储CollBook (确保先后顺序,否则出错)
// mCollBookDao.insertOrReplace(bean);
// }
// );
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/Constants.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
;
import
java.io.File
;
public
class
Constants
{
public
static
String
IP_ADDRESS
=
"10.129.82.19"
;
//阅读界面 默认字体大小
public
static
int
DEFAULT_TEXT_SIZE
=
18
;
//时间格式
public
static
final
String
FORMAT_TIME
=
"HH:mm"
;
public
static
final
String
FORMAT_DATE
=
"YYYY-MM-DD"
;
public
static
final
String
FORMAT_BOOK_DATE
=
"yyyy-MM-dd'T'HH:mm:ss"
;
//回调代码
public
static
final
int
MAINACTIVITY_REQUEST_CODE
=
1
;
public
static
final
int
FILESELECTOR_RESULT_CODE
=
2
;
public
static
final
String
READBOOK_KEY
=
"readBookKey"
;
public
static
final
String
FIELSELECTOR_RESULT_KEY
=
"fileSelectorResultKey"
;
//SharedPreference
public
static
final
String
IS_FIRST
=
"isFirst"
;
public
static
final
String
FIRST_KEY
=
"firstKey"
;
public
static
final
String
COOKIE_DATA
=
"cookieData"
;
public
static
final
String
COOKIE_KEY
=
"Authorization"
;
public
static
final
String
CACHE_PATH_KEY
=
"cachePath"
;
//BookCachePath (因为getCachePath引用了Context,所以必须是静态变量,不能够是静态常量)
public
static
String
BOOK_CACHE_PATH
=
FileUtils
.
getCachePath
()+
File
.
separator
+
"book_cache"
+
File
.
separator
;
//URL_BASE
// public static final String API_BASE_URL = "http://api.zhuishushenqi.com";
public
static
final
String
API_BASE_URL
=
"http://"
+
IP_ADDRESS
+
":8080"
;
public
static
final
String
IMG_BASE_URL
=
"http://statics.zhuishushenqi.com"
;
}
book/app/src/main/java/com/mints/enjoyboxjia/read/Direction.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
;
public
enum
Direction
{
NONE
,
NEXT
,
PRE
}
book/app/src/main/java/com/mints/enjoyboxjia/read/FileUtils.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
;
import
android.os.Environment
;
import
com.mints.enjoyboxjia.MintsApplication
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedReader
;
import
java.io.Closeable
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileNotFoundException
;
import
java.io.FileReader
;
import
java.io.IOException
;
import
java.io.Reader
;
import
java.nio.charset.Charset
;
import
java.text.DecimalFormat
;
import
java.util.ArrayList
;
import
java.util.List
;
import
io.reactivex.Single
;
import
io.reactivex.SingleEmitter
;
import
io.reactivex.SingleOnSubscribe
;
public
class
FileUtils
{
//采用自己的格式去设置文件,防止文件被系统文件查询到
public
static
final
String
SUFFIX_NB
=
".nb"
;
public
static
final
String
SUFFIX_TXT
=
".txt"
;
public
static
final
String
SUFFIX_EPUB
=
".epub"
;
public
static
final
String
SUFFIX_PDF
=
".pdf"
;
//获取文件夹
public
static
File
getFolder
(
String
filePath
){
File
file
=
new
File
(
filePath
);
//如果文件夹不存在,就创建它
if
(!
file
.
exists
()){
file
.
mkdirs
();
}
return
file
;
}
//获取文件
public
static
synchronized
File
getFile
(
String
filePath
){
File
file
=
new
File
(
filePath
);
try
{
if
(!
file
.
exists
()){
//创建父类文件夹
getFolder
(
file
.
getParent
());
//创建文件
file
.
createNewFile
();
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
file
;
}
//获取Cache文件夹
public
static
String
getCachePath
(){
if
(
isSdCardExist
()){
return
MintsApplication
.
getContext
()
.
getExternalCacheDir
()
.
getAbsolutePath
();
}
else
{
return
MintsApplication
.
getContext
()
.
getCacheDir
()
.
getAbsolutePath
();
}
}
public
static
long
getDirSize
(
File
file
){
//判断文件是否存在
if
(
file
.
exists
())
{
//如果是目录则递归计算其内容的总大小
if
(
file
.
isDirectory
())
{
File
[]
children
=
file
.
listFiles
();
long
size
=
0
;
for
(
File
f
:
children
)
size
+=
getDirSize
(
f
);
return
size
;
}
else
{
return
file
.
length
();
}
}
else
{
return
0
;
}
}
public
static
String
getFileSize
(
long
size
)
{
if
(
size
<=
0
)
return
"0"
;
final
String
[]
units
=
new
String
[]{
"b"
,
"kb"
,
"M"
,
"G"
,
"T"
};
//计算单位的,原理是利用lg,公式是 lg(1024^n) = nlg(1024),最后 nlg(1024)/lg(1024) = n。
int
digitGroups
=
(
int
)
(
Math
.
log10
(
size
)
/
Math
.
log10
(
1024
));
//计算原理是,size/单位值。单位值指的是:比如说b = 1024,KB = 1024^2
return
new
DecimalFormat
(
"#,##0.##"
).
format
(
size
/
Math
.
pow
(
1024
,
digitGroups
))
+
" "
+
units
[
digitGroups
];
}
/**
* 本来是获取File的内容的。但是为了解决文本缩进、换行的问题
* 这个方法就是专门用来获取书籍的...
*
* 应该放在BookRepository中。。。
* @param file
* @return
*/
public
static
String
getFileContent
(
File
file
){
Reader
reader
=
null
;
String
str
=
null
;
StringBuilder
sb
=
new
StringBuilder
();
try
{
reader
=
new
FileReader
(
file
);
BufferedReader
br
=
new
BufferedReader
(
reader
);
while
((
str
=
br
.
readLine
())
!=
null
){
//过滤空语句
if
(!
str
.
equals
(
""
)){
//由于sb会自动过滤\n,所以需要加上去
sb
.
append
(
" "
+
str
+
"\n"
);
}
}
}
catch
(
FileNotFoundException
e
)
{
e
.
printStackTrace
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
finally
{
close
(
reader
);
}
return
sb
.
toString
();
}
//判断是否挂载了SD卡
public
static
boolean
isSdCardExist
(){
if
(
Environment
.
MEDIA_MOUNTED
.
equals
(
Environment
.
getExternalStorageState
())){
return
true
;
}
return
false
;
}
//递归删除文件夹下的数据
public
static
synchronized
void
deleteFile
(
String
filePath
){
File
file
=
new
File
(
filePath
);
if
(!
file
.
exists
())
return
;
if
(
file
.
isDirectory
()){
File
[]
files
=
file
.
listFiles
();
for
(
File
subFile
:
files
){
String
path
=
subFile
.
getPath
();
deleteFile
(
path
);
}
}
//删除文件
file
.
delete
();
}
//由于递归的耗时问题,取巧只遍历内部三层
//获取txt文件
public
static
List
<
File
>
getTxtFiles
(
String
filePath
,
int
layer
){
List
txtFiles
=
new
ArrayList
();
File
file
=
new
File
(
filePath
);
//如果层级为 3,则直接返回
if
(
layer
==
3
){
return
txtFiles
;
}
//获取文件夹
File
[]
dirs
=
file
.
listFiles
(
pathname
->
{
if
(
pathname
.
isDirectory
()
&&
!
pathname
.
getName
().
startsWith
(
"."
))
{
return
true
;
}
//获取txt文件
else
if
(
pathname
.
getName
().
endsWith
(
".txt"
)){
txtFiles
.
add
(
pathname
);
return
false
;
}
else
{
return
false
;
}
}
);
//遍历文件夹
for
(
File
dir
:
dirs
){
//递归遍历txt文件
txtFiles
.
addAll
(
getTxtFiles
(
dir
.
getPath
(),
layer
+
1
));
}
return
txtFiles
;
}
//由于遍历比较耗时
public
static
Single
<
List
<
File
>>
getSDTxtFile
(){
//外部存储卡路径
String
rootPath
=
Environment
.
getExternalStorageDirectory
().
getPath
();
return
Single
.
create
(
new
SingleOnSubscribe
<
List
<
File
>>()
{
@Override
public
void
subscribe
(
SingleEmitter
<
List
<
File
>>
e
)
throws
Exception
{
List
<
File
>
files
=
getTxtFiles
(
rootPath
,
0
);
e
.
onSuccess
(
files
);
}
});
}
//获取文件的编码格式
public
static
Charset
getCharset
(
String
fileName
)
{
BufferedInputStream
bis
=
null
;
Charset
charset
=
Charset
.
forName
(
"GBK "
);;
byte
[]
first3Bytes
=
new
byte
[
3
];
try
{
boolean
checked
=
false
;
bis
=
new
BufferedInputStream
(
new
FileInputStream
(
fileName
));
bis
.
mark
(
0
);
int
read
=
bis
.
read
(
first3Bytes
,
0
,
3
);
if
(
read
==
-
1
)
return
charset
;
if
(
first3Bytes
[
0
]
==
(
byte
)
0xEF
&&
first3Bytes
[
1
]
==
(
byte
)
0xBB
&&
first3Bytes
[
2
]
==
(
byte
)
0xBF
)
{
charset
=
Charset
.
forName
(
"utf8"
);
checked
=
true
;
}
/*
* 不支持 UTF16LE 和 UTF16BE
else if (first3Bytes[0] == (byte) 0xFF && first3Bytes[1] == (byte) 0xFE) {
charset = Charset.UTF16LE;
checked = true;
} else if (first3Bytes[0] == (byte) 0xFE
&& first3Bytes[1] == (byte) 0xFF) {
charset = Charset.UTF16BE;
checked = true;
} else */
bis
.
mark
(
0
);
if
(!
checked
)
{
while
((
read
=
bis
.
read
())
!=
-
1
)
{
if
(
read
>=
0xF0
)
break
;
if
(
0x80
<=
read
&&
read
<=
0xBF
)
// 单独出现BF以下的,也算是GBK
break
;
if
(
0xC0
<=
read
&&
read
<=
0xDF
)
{
read
=
bis
.
read
();
if
(
0x80
<=
read
&&
read
<=
0xBF
)
// 双字节 (0xC0 - 0xDF)
// (0x80 - 0xBF),也可能在GB编码内
continue
;
else
break
;
}
else
if
(
0xE0
<=
read
&&
read
<=
0xEF
)
{
// 也有可能出错,但是几率较小
read
=
bis
.
read
();
if
(
0x80
<=
read
&&
read
<=
0xBF
)
{
read
=
bis
.
read
();
if
(
0x80
<=
read
&&
read
<=
0xBF
)
{
charset
=
Charset
.
forName
(
"utf8"
);
break
;
}
else
break
;
}
else
break
;
}
}
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
finally
{
close
(
bis
);
}
return
charset
;
}
static
void
close
(
Closeable
closeable
){
if
(
closeable
==
null
)
return
;
try
{
closeable
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
//close error
}
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/NetworkPageLoader.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
;
import
android.util.Log
;
import
com.mints.enjoyboxjia.MintsApplication
;
import
com.mints.enjoyboxjia.manager.AppHttpManager
;
import
com.mints.enjoyboxjia.mvp.model.BaseResponse
;
import
com.mints.enjoyboxjia.mvp.model.BookChapterBean
;
import
com.mints.enjoyboxjia.mvp.model.BookContentBean
;
import
com.mints.enjoyboxjia.read.models.BookModel
;
import
com.mints.enjoyboxjia.read.models.TxtChapterModel
;
import
com.mints.library.net.neterror.BaseSubscriber
;
import
com.mints.library.net.neterror.Throwable
;
import
org.reactivestreams.Subscriber
;
import
org.reactivestreams.Subscription
;
import
java.io.BufferedReader
;
import
java.io.BufferedWriter
;
import
java.io.Closeable
;
import
java.io.File
;
import
java.io.FileReader
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.io.Reader
;
import
java.io.Writer
;
import
java.util.ArrayDeque
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
io.reactivex.Flowable
;
import
io.reactivex.Single
;
import
io.reactivex.android.schedulers.AndroidSchedulers
;
import
io.reactivex.schedulers.Schedulers
;
public
class
NetworkPageLoader
extends
PageLoader
{
private
Subscription
mChapterSub
;
private
boolean
isSkip
=
false
;
public
NetworkPageLoader
(
YPageView
pageView
,
BookModel
bookModel
)
{
super
(
pageView
,
bookModel
);
}
@Override
public
void
initData
()
{
loadCurrentChapter
(
curChapterIndex
);
}
@Override
public
BufferedReader
getChapterReader
(
TxtChapterModel
chapterModel
)
throws
IOException
{
File
file
=
new
File
(
Constants
.
BOOK_CACHE_PATH
+
bookModel
.
getBookId
()
+
File
.
separator
+
chapterModel
.
title
+
FileUtils
.
SUFFIX_NB
);
if
(!
file
.
exists
())
return
null
;
Reader
reader
=
new
FileReader
(
file
);
return
new
BufferedReader
(
reader
);
}
//加载章节列表
@Override
public
void
loadChapters
()
{
//已缓存
if
(
mChapterList
!=
null
&&
!
mChapterList
.
isEmpty
())
return
;
Map
<
String
,
Object
>
params
=
new
HashMap
<>();
params
.
put
(
"id"
,
bookModel
.
getBookId
());
MintsApplication
application
=
MintsApplication
.
getApplication
();
AppHttpManager
.
getInstance
(
application
).
call
(
application
.
getLoanService
().
getBookDetail
(
params
),
new
BaseSubscriber
<
BaseResponse
<
BookContentBean
>>()
{
@Override
public
void
onNext
(
BaseResponse
<
BookContentBean
>
baseResponse
)
{
List
<
BookContentBean
.
ArticleChapterList
>
articleChapterList
=
baseResponse
.
getData
().
getArticleChapterList
();
for
(
BookContentBean
.
ArticleChapterList
chapterList
:
articleChapterList
)
{
TxtChapterModel
txtChapterModel
=
new
TxtChapterModel
();
txtChapterModel
.
setChapterId
(
""
+
chapterList
.
getId
());
txtChapterModel
.
setBook_id
(
bookModel
.
getId
());
txtChapterModel
.
setTitle
(
"第"
+
chapterList
.
getChapterNum
()
+
"章节"
);
mChapterList
.
add
(
txtChapterModel
);
}
chapterChangeListener
.
finishedLoadChapters
(
mChapterList
);
}
@Override
public
void
onCompleted
()
{
}
@Override
public
void
onError
(
Throwable
e
)
{
}
}
);
}
@Override
public
void
loadNextChapters
()
{
loadNextChapter
();
}
@Override
public
void
loadPreChapters
()
{
loadPrevChapter
();
}
@Override
public
void
preChapter
()
{
super
.
preChapter
();
loadPrevChapter
();
}
@Override
public
void
nextChapter
()
{
super
.
nextChapter
();
loadNextChapter
();
}
@Override
public
void
skipToChapter
(
int
pos
)
{
if
(
Math
.
abs
(
pos
-
curChapterIndex
)
>
1
)
{
curChapterIndex
=
pos
;
isSkip
=
true
;
loadCurrentChapter
(
pos
);
}
else
{
skipToChapterReal
(
pos
);
}
}
private
void
skipToChapterReal
(
int
pos
)
{
super
.
skipToChapter
(
pos
);
loadCurrentChapter
(
pos
);
}
/**
* 加载当前页的前面两个章节
*/
private
void
loadPrevChapter
()
{
if
(
chapterChangeListener
!=
null
)
{
int
end
=
curChapterIndex
;
int
begin
=
end
-
2
;
if
(
begin
<
0
)
{
begin
=
0
;
}
requestChapters
(
begin
,
end
);
}
}
/**
* 加载前一页,当前页,后一页。
*/
private
void
loadCurrentChapter
(
int
cur
)
{
if
(
chapterChangeListener
!=
null
)
{
int
begin
=
cur
;
int
end
=
cur
;
// 是否当前不是最后一章
if
(
end
<
mChapterList
.
size
())
{
end
=
end
+
1
;
if
(
end
>=
mChapterList
.
size
())
{
end
=
mChapterList
.
size
()
-
1
;
}
}
// 如果当前不是第一章
if
(
begin
!=
0
)
{
begin
=
begin
-
1
;
if
(
begin
<
0
)
{
begin
=
0
;
}
}
requestChapters
(
begin
,
end
);
}
}
/**
* 加载当前页的后两个章节
*/
private
void
loadNextChapter
()
{
if
(
chapterChangeListener
!=
null
)
{
// 提示加载后两章
int
begin
=
curChapterIndex
+
1
;
int
end
=
begin
+
1
;
// 判断是否大于最后一章
if
(
begin
>=
mChapterList
.
size
())
{
// 如果下一章超出目录了,就没有必要加载了
return
;
}
if
(
end
>
mChapterList
.
size
())
{
end
=
mChapterList
.
size
()
-
1
;
}
requestChapters
(
begin
,
end
);
}
}
private
void
requestChapters
(
int
start
,
int
end
)
{
// 检验输入值
if
(
start
<
0
)
{
start
=
0
;
}
if
(
end
>=
mChapterList
.
size
())
{
end
=
mChapterList
.
size
()
-
1
;
}
List
<
TxtChapterModel
>
chapters
=
new
ArrayList
<>();
// 过滤,哪些数据已经加载了
for
(
int
i
=
start
;
i
<=
end
;
++
i
)
{
TxtChapterModel
txtChapter
=
mChapterList
.
get
(
i
);
if
(!
hasChapterData
(
txtChapter
))
{
chapters
.
add
(
txtChapter
);
}
}
if
(!
chapters
.
isEmpty
())
{
chapterChangeListener
.
requestChapters
(
chapters
);
loadChapter
(
String
.
valueOf
(
bookModel
.
getBookId
()),
chapters
);
}
else
{
if
(
isSkip
)
isSkip
=
!
isSkip
;
pageView
.
showContent
();
}
}
private
boolean
hasChapterData
(
TxtChapterModel
chapter
)
{
return
BookManager
.
isChapterCached
(
String
.
valueOf
(
bookModel
.
getBookId
()),
chapter
.
title
);
}
//加载章节具体内容
private
void
loadChapter
(
String
bookId
,
List
<
TxtChapterModel
>
bookChapters
)
{
int
size
=
bookChapters
.
size
();
//取消上次的任务,防止多次加载
if
(
mChapterSub
!=
null
)
{
mChapterSub
.
cancel
();
}
List
<
Single
<
BaseResponse
<
BookChapterBean
>>>
chapterInfos
=
new
ArrayList
<>(
size
);
ArrayDeque
<
String
>
titles
=
new
ArrayDeque
<>(
size
);
for
(
int
i
=
0
;
i
<
size
;
++
i
)
{
TxtChapterModel
bookChapter
=
bookChapters
.
get
(
i
);
Log
.
v
(
"yzll"
,
"缓存章节:"
+
bookChapter
.
getTitle
());
Map
<
String
,
Object
>
params
=
new
HashMap
<>();
params
.
put
(
"articleId"
,
bookModel
.
getBookId
());
params
.
put
(
"chapterId"
,
bookChapter
.
getChapterId
());
Single
<
BaseResponse
<
BookChapterBean
>>
chapterInfoSingle
=
MintsApplication
.
getApplication
().
getLoanService
().
getChapterInfo
(
params
).
map
(
bean
->
bean
);
chapterInfos
.
add
(
chapterInfoSingle
);
titles
.
add
(
bookChapter
.
getTitle
());
}
new
Thread
(()
->
{
Flowable
<
BaseResponse
<
BookChapterBean
>>
concat
=
Single
.
concat
(
chapterInfos
);
concat
.
subscribeOn
(
Schedulers
.
io
());
concat
.
observeOn
(
AndroidSchedulers
.
mainThread
());
concat
.
subscribe
(
new
Subscriber
<
BaseResponse
<
BookChapterBean
>>()
{
String
title
=
titles
.
poll
();
@Override
public
void
onSubscribe
(
Subscription
s
)
{
s
.
request
(
Integer
.
MAX_VALUE
);
mChapterSub
=
s
;
}
@Override
public
void
onNext
(
BaseResponse
<
BookChapterBean
>
bookChapterBean
)
{
//存储数据
saveChapterInfo
(
bookId
,
title
,
bookChapterBean
.
getData
().
getContent
());
//将获取到的数据进行存储
title
=
titles
.
poll
();
}
@Override
public
void
onError
(
java
.
lang
.
Throwable
t
)
{
}
@Override
public
void
onComplete
()
{
if
(
isSkip
)
{
isSkip
=
!
isSkip
;
skipToChapterReal
(
curChapterIndex
);
}
else
{
pageView
.
showContent
();
}
}
});
}).
start
();
}
/**
* 存储章节
*
* @param folderName
* @param fileName
* @param content
*/
public
void
saveChapterInfo
(
String
folderName
,
String
fileName
,
String
content
)
{
File
file
=
BookManager
.
getBookFile
(
folderName
,
fileName
);
//获取流并存储
Writer
writer
=
null
;
try
{
writer
=
new
BufferedWriter
(
new
FileWriter
(
file
));
writer
.
write
(
content
);
writer
.
flush
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
close
(
writer
);
}
}
//关闭数据流
private
void
close
(
Closeable
closeable
)
{
if
(
closeable
==
null
)
return
;
try
{
closeable
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/PageLoader.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.graphics.Color
;
import
android.graphics.Paint
;
import
android.graphics.Rect
;
import
android.graphics.RectF
;
import
android.graphics.Typeface
;
import
android.text.TextPaint
;
import
com.mints.enjoyboxjia.read.models.BookModel
;
import
com.mints.enjoyboxjia.read.models.TxtChapterModel
;
import
com.mints.enjoyboxjia.read.models.TxtPageModel
;
import
com.mints.enjoyboxjia.utils.StringUtils
;
import
com.mints.library.utils.Utils
;
import
java.io.BufferedReader
;
import
java.io.FileNotFoundException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.List
;
public
abstract
class
PageLoader
{
//显示容器
public
YPageView
pageView
;
//加载的书籍
BookModel
bookModel
;
// 当前书籍章节列表
public
List
<
TxtChapterModel
>
mChapterList
;
// 当前显示的页
private
TxtPageModel
mCurPage
;
// 被遮盖的页,或者认为被取消显示的页
private
TxtPageModel
mCancelPage
;
// 上一章的页面列表缓存
private
List
<
TxtPageModel
>
mPrePageList
;
// 当前章节的页面列表
private
List
<
TxtPageModel
>
mCurPageList
;
// 下一章的页面列表缓存
private
List
<
TxtPageModel
>
mNextPageList
;
//当前章节位置
int
curChapterIndex
=
0
;
//上一章节位置
int
lastChapterIndex
=
0
;
//当前页面位置
int
curPageIndex
=
0
;
//行间距
private
int
mTextInterval
;
//标题的行间距
private
int
mTitleInterval
;
//书籍绘制区域的宽高
private
int
mVisibleWidth
;
private
int
mVisibleHeight
;
//应用的宽高
private
int
mDisplayWidth
;
private
int
mDisplayHeight
;
//电池的百分比
private
int
mBatteryLevel
=
80
;
//间距
private
int
mMarginWidth
;
private
int
mMarginHeight
;
//标题画笔
Paint
mTitleTextPaint
;
//内容画笔
Paint
mContentTextPaint
;
// 绘制电池的画笔
private
Paint
mBatteryPaint
;
// 绘制提示的画笔
private
Paint
mTipPaint
;
//字体大小 单位dp
int
mTextSize
=
18
;
//背景颜色
int
bgColor
=
0xFFCEC29C
;
//字体颜色
int
textColor
=
Color
.
BLACK
;
//记录上一次颜色 用于恢复
int
lastBgColor
;
int
lastTextColor
;
//页面变换监听者
OnChapterChangeListener
chapterChangeListener
;
public
PageLoader
(
YPageView
pageView
,
BookModel
bookModel
)
{
this
.
pageView
=
pageView
;
this
.
bookModel
=
bookModel
;
initPaint
();
// initDimens();
//initData();
}
//初始化数据
public
void
initData
()
{
if
(
curChapterIndex
>
0
)
mPrePageList
=
loadPageList
(
curChapterIndex
-
1
);
mCurPageList
=
loadPageList
(
curChapterIndex
);
if
(
curChapterIndex
<
mChapterList
.
size
()
-
1
)
mNextPageList
=
loadPageList
(
curChapterIndex
+
1
);
mCurPage
=
mCurPageList
.
get
(
curPageIndex
);
updateCurPage
();
}
//初始化尺寸
public
void
initDimens
()
{
mMarginWidth
=
40
;
mMarginHeight
=
50
;
mDisplayHeight
=
pageView
.
getHeight
();
mDisplayWidth
=
pageView
.
getWidth
();
mVisibleWidth
=
pageView
.
getWidth
()
-
mMarginWidth
*
2
;
mVisibleHeight
=
pageView
.
getHeight
()
-
mMarginHeight
;
mTitleInterval
=
(
int
)
(
mTitleTextPaint
.
getTextSize
()
/
2
);
mTextInterval
=
(
int
)
(
mContentTextPaint
.
getTextSize
()
/
2
);
}
//初始化画笔
private
void
initPaint
()
{
// 绘制页面内容的画笔
mContentTextPaint
=
new
TextPaint
();
mContentTextPaint
.
setColor
(
Color
.
BLACK
);
mContentTextPaint
.
setTextSize
(
dp2px
(
mTextSize
));
mContentTextPaint
.
setAntiAlias
(
true
);
mContentTextPaint
.
setSubpixelText
(
true
);
// 绘制标题的画笔
mTitleTextPaint
=
new
TextPaint
();
mTitleTextPaint
.
setColor
(
Color
.
BLACK
);
mTitleTextPaint
.
setTextSize
(
dp2px
(
mTextSize
+
5
));
mTitleTextPaint
.
setStyle
(
Paint
.
Style
.
FILL_AND_STROKE
);
mTitleTextPaint
.
setTypeface
(
Typeface
.
DEFAULT_BOLD
);
mTitleTextPaint
.
setAntiAlias
(
true
);
// 绘制提示的画笔
mTipPaint
=
new
Paint
();
mTipPaint
.
setColor
(
textColor
);
mTipPaint
.
setTextAlign
(
Paint
.
Align
.
LEFT
);
// 绘制的起始点
mTipPaint
.
setTextSize
(
dp2px
(
12
));
// Tip默认的字体大小
mTipPaint
.
setAntiAlias
(
true
);
mTipPaint
.
setSubpixelText
(
true
);
// 绘制电池的画笔
mBatteryPaint
=
new
Paint
();
mBatteryPaint
.
setAntiAlias
(
true
);
mBatteryPaint
.
setDither
(
true
);
}
public
void
reloadPageList
()
{
if
(
curChapterIndex
>
0
)
mPrePageList
=
loadPageList
(
curChapterIndex
-
1
);
mCurPageList
=
loadPageList
(
curChapterIndex
);
if
(
curChapterIndex
<
mChapterList
.
size
()
-
1
)
mNextPageList
=
loadPageList
(
curChapterIndex
+
1
);
mCurPage
=
mCurPageList
.
get
(
0
);
updateCurPage
();
}
//加载某章内容
public
List
<
TxtPageModel
>
loadPageList
(
int
chapterIndex
)
{
if
(
mChapterList
.
isEmpty
())
return
null
;
TxtChapterModel
chapterModel
=
mChapterList
.
get
(
chapterIndex
);
List
<
TxtPageModel
>
pageList
=
null
;
try
{
BufferedReader
br
=
getChapterReader
(
chapterModel
);
if
(
br
!=
null
)
{
pageList
=
loadPages
(
chapterModel
,
br
);
}
else
{
// reloadPageList();
}
}
catch
(
FileNotFoundException
e
)
{
e
.
printStackTrace
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
pageList
;
}
//根据章节模型将数据封装成页
private
List
<
TxtPageModel
>
loadPages
(
TxtChapterModel
chapter
,
BufferedReader
br
)
{
//章节的所有页面
List
<
TxtPageModel
>
pageLists
=
new
ArrayList
<>();
//每页的行
List
<
String
>
lines
=
new
ArrayList
<>();
int
readHeight
=
mVisibleHeight
;
boolean
showTitle
=
true
;
String
paragraph
=
chapter
.
getTitle
();
//默认展示标题
int
titleLinesCount
=
0
;
//流式读取书籍数据
try
{
while
(
showTitle
||
(
paragraph
=
br
.
readLine
())
!=
null
)
{
//一行的字数
int
wordCount
=
0
;
//一行的内容
paragraph
=
paragraph
.
replace
(
" "
,
" "
)
.
replace
(
"<br/>"
,
" "
)
.
replace
(
"<br />"
,
" "
)
.
replace
(
";"
,
" "
);
String
lineContent
=
null
;
while
(
paragraph
.
length
()
>
0
)
{
//检查是否能一行的高度
if
(
showTitle
)
{
readHeight
-=
mTitleTextPaint
.
getTextSize
();
}
else
{
readHeight
-=
mContentTextPaint
.
getTextSize
();
}
// 一页已经填充满了,创建 TextPage
if
(
readHeight
<=
0
)
{
// 创建Page
TxtPageModel
page
=
new
TxtPageModel
();
page
.
position
=
pageLists
.
size
();
page
.
title
=
chapter
.
getTitle
();
page
.
lines
=
new
ArrayList
<>(
lines
);
page
.
titleLines
=
titleLinesCount
;
pageLists
.
add
(
page
);
// 重置Lines
lines
.
clear
();
readHeight
=
mVisibleHeight
;
titleLinesCount
=
0
;
continue
;
}
//一页未填满 测量每行的字数
if
(
showTitle
)
{
wordCount
=
mTitleTextPaint
.
breakText
(
paragraph
,
true
,
mVisibleWidth
,
null
);
}
else
{
wordCount
=
mContentTextPaint
.
breakText
(
paragraph
,
true
,
mVisibleWidth
,
null
);
}
//截取一行的内容
lineContent
=
paragraph
.
substring
(
0
,
wordCount
);
if
(!
lineContent
.
equals
(
"\n"
))
{
//一行不为空则加入数组
lines
.
add
(
lineContent
);
//设置段落间距
if
(
showTitle
)
{
titleLinesCount
+=
1
;
readHeight
-=
mTitleInterval
;
showTitle
=
false
;
}
else
{
readHeight
-=
mTextInterval
;
}
}
//裁剪
paragraph
=
paragraph
.
substring
(
wordCount
);
}
//增加段落的间距
// if (!showTitle && lines.size() != 0) {
// readHeight = readHeight - mTextInterval;
// }
if
(
showTitle
)
{
readHeight
=
readHeight
-
mTitleInterval
;
showTitle
=
false
;
}
}
//处理尾页
if
(
lines
.
size
()
!=
0
)
{
//创建Page
TxtPageModel
page
=
new
TxtPageModel
();
page
.
position
=
pageLists
.
size
();
page
.
title
=
chapter
.
getTitle
();
page
.
lines
=
new
ArrayList
<>(
lines
);
page
.
titleLines
=
titleLinesCount
;
pageLists
.
add
(
page
);
//重置Lines
lines
.
clear
();
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
finally
{
try
{
if
(
br
!=
null
)
br
.
close
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
return
pageLists
;
}
//绘制页面
public
void
drawPage
(
Bitmap
bitmap
)
{
Canvas
canvas
=
new
Canvas
(
bitmap
);
drawBG
(
canvas
);
drawContent
(
canvas
);
pageView
.
invalidate
();
}
//绘制背景
private
void
drawBG
(
Canvas
canvas
)
{
int
tipMarginHeight
=
Utils
.
dpToPx
(
pageView
.
getContext
(),
3
);
canvas
.
drawColor
(
bgColor
);
/******绘制电池********/
int
visibleRight
=
mDisplayWidth
-
mMarginWidth
;
int
visibleBottom
=
mDisplayHeight
-
tipMarginHeight
;
int
outFrameWidth
=
(
int
)
mTipPaint
.
measureText
(
"xxx"
);
int
outFrameHeight
=
(
int
)
mTipPaint
.
getTextSize
();
int
polarHeight
=
Utils
.
dpToPx
(
pageView
.
getContext
(),
6
);
int
polarWidth
=
Utils
.
dpToPx
(
pageView
.
getContext
(),
2
);
int
border
=
1
;
int
innerMargin
=
1
;
//电极的制作
int
polarLeft
=
visibleRight
-
polarWidth
;
int
polarTop
=
visibleBottom
-
(
outFrameHeight
+
polarHeight
)
/
2
;
Rect
polar
=
new
Rect
(
polarLeft
,
polarTop
,
visibleRight
,
polarTop
+
polarHeight
-
Utils
.
dpToPx
(
pageView
.
getContext
(),
2
));
mBatteryPaint
.
setStyle
(
Paint
.
Style
.
FILL
);
canvas
.
drawRect
(
polar
,
mBatteryPaint
);
//外框的制作
int
outFrameLeft
=
polarLeft
-
outFrameWidth
;
int
outFrameTop
=
visibleBottom
-
outFrameHeight
;
int
outFrameBottom
=
visibleBottom
-
Utils
.
dpToPx
(
pageView
.
getContext
(),
2
);
Rect
outFrame
=
new
Rect
(
outFrameLeft
,
outFrameTop
,
polarLeft
,
outFrameBottom
);
mBatteryPaint
.
setStyle
(
Paint
.
Style
.
STROKE
);
mBatteryPaint
.
setStrokeWidth
(
border
);
canvas
.
drawRect
(
outFrame
,
mBatteryPaint
);
//内框的制作
float
innerWidth
=
(
outFrame
.
width
()
-
innerMargin
*
2
-
border
)
*
(
mBatteryLevel
/
100.0f
);
RectF
innerFrame
=
new
RectF
(
outFrameLeft
+
border
+
innerMargin
,
outFrameTop
+
border
+
innerMargin
,
outFrameLeft
+
border
+
innerMargin
+
innerWidth
,
outFrameBottom
-
border
-
innerMargin
);
mBatteryPaint
.
setStyle
(
Paint
.
Style
.
FILL
);
canvas
.
drawRect
(
innerFrame
,
mBatteryPaint
);
/******绘制当前时间********/
//底部的字显示的位置Y
float
y
=
mDisplayHeight
-
mTipPaint
.
getFontMetrics
().
bottom
-
tipMarginHeight
;
String
time
=
StringUtils
.
dateConvert
(
System
.
currentTimeMillis
(),
Constants
.
FORMAT_TIME
);
float
x
=
outFrameLeft
-
mTipPaint
.
measureText
(
time
)
-
Utils
.
dpToPx
(
pageView
.
getContext
(),
4
);
canvas
.
drawText
(
time
,
x
,
y
,
mTipPaint
);
canvas
.
drawText
(
String
.
format
(
"%d/%d页"
,
curPageIndex
+
1
,
mCurPageList
==
null
?
0
:
mCurPageList
.
size
()),
dp2px
(
10
),
y
,
mTipPaint
);
}
//绘制内容
private
void
drawContent
(
Canvas
canvas
)
{
if
(
mCurPage
==
null
)
return
;
float
top
=
mMarginHeight
;
String
str
=
null
;
//确定距离
int
contentInterval
=
(
int
)
mContentTextPaint
.
getTextSize
()
+
mTextInterval
;
int
titleInterval
=
(
int
)
mTitleTextPaint
.
getTextSize
()
+
mTitleInterval
;
//对标题进行绘制
for
(
int
i
=
0
;
i
<
mCurPage
.
titleLines
;
++
i
)
{
str
=
mCurPage
.
lines
.
get
(
i
);
//设置顶部间距
if
(
i
==
0
)
{
top
+=
10
;
}
//计算文字显示的起始点
int
start
=
(
int
)
(
mVisibleWidth
-
mTitleTextPaint
.
measureText
(
str
))
/
2
;
//进行绘制
canvas
.
drawText
(
str
,
start
,
top
,
mTitleTextPaint
);
// canvas.drawText(str, 50, 100, mTitleTextPaint);
//设置尾部间距
if
(
i
==
mCurPage
.
titleLines
-
1
)
{
top
+=
titleInterval
;
}
else
{
top
+=
titleInterval
;
}
}
//对内容进行绘制
for
(
int
i
=
mCurPage
.
titleLines
;
i
<
mCurPage
.
lines
.
size
();
++
i
)
{
str
=
mCurPage
.
lines
.
get
(
i
);
canvas
.
drawText
(
str
,
mMarginWidth
,
top
,
mContentTextPaint
);
if
(
str
.
endsWith
(
"\n"
))
{
top
+=
contentInterval
+
10
;
}
else
{
//行间距
top
+=
contentInterval
;
}
}
}
//上一页
public
boolean
prePage
()
{
if
(
curPageIndex
>
0
)
{
curPageIndex
--;
}
else
{
List
<
TxtPageModel
>
tempPageList
=
loadPageList
(
curChapterIndex
-
1
);
if
(
tempPageList
==
null
)
{
loadPreChapters
();
return
false
;
}
if
(
curChapterIndex
==
0
)
return
false
;
lastChapterIndex
=
curChapterIndex
--;
mNextPageList
=
mCurPageList
;
mCurPageList
=
mPrePageList
;
if
(
curChapterIndex
>
0
)
mPrePageList
=
tempPageList
;
curPageIndex
=
mCurPageList
.
size
()
-
1
;
if
(
chapterChangeListener
!=
null
)
{
chapterChangeListener
.
onChapterChange
(
curChapterIndex
);
}
}
mCancelPage
=
mCurPage
;
mCurPage
=
mCurPageList
.
get
(
curPageIndex
);
pageView
.
drawNextPage
();
return
true
;
}
//下一页
public
boolean
nextPage
()
{
if
(
curPageIndex
>=
0
&&
curPageIndex
<
mCurPageList
.
size
()
-
1
)
{
curPageIndex
++;
}
else
{
List
<
TxtPageModel
>
tempPageList
=
loadPageList
(
curChapterIndex
+
1
);
if
(
tempPageList
==
null
)
{
loadNextChapters
();
return
false
;
}
if
(
curChapterIndex
>=
mChapterList
.
size
()
-
1
)
return
false
;
lastChapterIndex
=
curChapterIndex
++;
mPrePageList
=
mCurPageList
;
mCurPageList
=
mNextPageList
;
if
(
curChapterIndex
<
mChapterList
.
size
()
-
1
)
mNextPageList
=
loadPageList
(
curChapterIndex
+
1
);
curPageIndex
=
0
;
if
(
chapterChangeListener
!=
null
)
{
chapterChangeListener
.
onChapterChange
(
curChapterIndex
);
}
}
mCancelPage
=
mCurPage
;
mCurPage
=
mCurPageList
.
get
(
curPageIndex
);
pageView
.
drawNextPage
();
return
true
;
}
//取消翻页
public
void
cancelChangePage
()
{
// 加载到下一章取消了
if
(
mCurPage
.
position
==
0
&&
curChapterIndex
>
lastChapterIndex
)
{
if
(
mPrePageList
!=
null
)
{
cancelNextChapter
();
}
else
{
mCurPage
=
new
TxtPageModel
();
}
}
// 加载上一章取消了
else
if
(
mCurPageList
==
null
||
(
mCurPage
.
position
==
mCurPageList
.
size
()
-
1
&&
curChapterIndex
<
lastChapterIndex
))
{
if
(
mNextPageList
!=
null
)
{
cancelPreChapter
();
}
else
{
mCurPage
=
new
TxtPageModel
();
}
}
else
{
// 假设加载到下一页,又取消了。那么需要重新装载。
mCurPage
=
mCancelPage
;
curPageIndex
=
mCurPage
.
position
;
}
}
//翻到下一章 取消加载
private
void
cancelNextChapter
()
{
int
temp
=
lastChapterIndex
;
lastChapterIndex
=
curChapterIndex
;
curChapterIndex
=
temp
;
mNextPageList
=
mCurPageList
;
mCurPageList
=
mPrePageList
;
mPrePageList
=
null
;
if
(
curChapterIndex
>
0
)
mPrePageList
=
loadPageList
(
curChapterIndex
-
1
);
curPageIndex
=
mCurPageList
.
size
()
-
1
;
mCurPage
=
mCurPageList
.
get
(
curPageIndex
);
mCancelPage
=
null
;
}
//翻到上一章 取消加载
private
void
cancelPreChapter
()
{
// 重置位置点
int
temp
=
lastChapterIndex
;
lastChapterIndex
=
curChapterIndex
;
curChapterIndex
=
temp
;
// 重置页面列表
mPrePageList
=
mCurPageList
;
mCurPageList
=
mNextPageList
;
mNextPageList
=
null
;
if
(
curChapterIndex
<
mChapterList
.
size
()
-
1
)
mNextPageList
=
loadPageList
(
curChapterIndex
+
1
);
curPageIndex
=
0
;
mCurPage
=
mCurPageList
.
get
(
curPageIndex
);
mCancelPage
=
null
;
}
//下一章
public
void
nextChapter
()
{
if
(
curChapterIndex
<
mChapterList
.
size
()
-
1
)
skipToChapter
(++
curChapterIndex
);
}
//上一章
public
void
preChapter
()
{
if
(
curChapterIndex
>
0
)
skipToChapter
(--
curChapterIndex
);
}
//跳转到某一章
public
void
skipToChapter
(
int
pos
)
{
curChapterIndex
=
pos
;
if
(
chapterChangeListener
!=
null
)
{
chapterChangeListener
.
onChapterChange
(
curChapterIndex
);
}
curPageIndex
=
0
;
reloadPageList
();
}
//设置翻页模式
public
void
setPageMode
(
AnimType
animType
)
{
pageView
.
setAnimType
(
animType
);
}
//设置背景颜色
public
void
setPageBgColor
(
int
color
)
{
lastBgColor
=
this
.
bgColor
;
this
.
bgColor
=
color
;
//updateCurPage();
}
//设置字体颜色
public
void
setTextColor
(
int
color
)
{
lastTextColor
=
this
.
textColor
;
this
.
textColor
=
color
;
}
//设置阅读样式
public
void
setPageStyle
(
int
bgColor
,
int
textColor
)
{
lastBgColor
=
this
.
bgColor
;
lastTextColor
=
this
.
textColor
;
this
.
bgColor
=
bgColor
;
this
.
textColor
=
textColor
;
this
.
mTitleTextPaint
.
setColor
(
textColor
);
this
.
mContentTextPaint
.
setColor
(
textColor
);
updateCurPage
();
}
//恢复上次颜色
public
void
cancelColorChange
()
{
this
.
bgColor
=
lastBgColor
;
this
.
textColor
=
lastTextColor
;
this
.
mTitleTextPaint
.
setColor
(
textColor
);
this
.
mContentTextPaint
.
setColor
(
textColor
);
updateCurPage
();
}
//设置字体大小
public
void
setTextSize
(
int
textSize
)
{
mTextSize
=
textSize
;
}
//更新字体大小
public
void
updateTextSize
(
int
size
)
{
mTextSize
=
size
;
initPaint
();
initDimens
();
reloadPageList
();
}
private
void
updateCurPage
()
{
mCurPage
=
mCurPageList
.
get
(
curPageIndex
);
pageView
.
drawNextPage
();
pageView
.
invalidate
();
}
public
int
getCurChapterIndex
()
{
return
curChapterIndex
;
}
public
int
getCurPageIndex
()
{
return
curPageIndex
;
}
public
void
setCurChapterIndex
(
int
curChapterIndex
)
{
this
.
curChapterIndex
=
curChapterIndex
;
}
public
void
setCurPageIndex
(
int
curPageIndex
)
{
this
.
curPageIndex
=
curPageIndex
;
}
public
int
getBgColor
()
{
return
bgColor
;
}
public
void
setChapterChangeListener
(
OnChapterChangeListener
listener
)
{
this
.
chapterChangeListener
=
listener
;
}
public
int
getmTextSize
()
{
return
mTextSize
;
}
public
int
getTextColor
()
{
return
textColor
;
}
/********************************abstract***********************************/
public
abstract
BufferedReader
getChapterReader
(
TxtChapterModel
chapterModel
)
throws
IOException
;
public
abstract
void
loadChapters
()
throws
IOException
;
public
abstract
void
loadNextChapters
();
public
abstract
void
loadPreChapters
();
private
float
dp2px
(
float
dp
)
{
return
pageView
.
getContext
().
getResources
().
getDisplayMetrics
().
density
*
dp
;
}
/**************************interface*******************************/
public
interface
OnChapterChangeListener
{
void
onChapterChange
(
int
pos
);
void
requestChapters
(
List
<
TxtChapterModel
>
requestChapters
);
void
finishedLoadChapters
(
List
<
TxtChapterModel
>
bookChapters
);
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/YPageView.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
;
import
android.content.Context
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.graphics.RectF
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
android.view.MotionEvent
;
import
android.view.View
;
import
android.view.ViewConfiguration
;
import
com.mints.enjoyboxjia.read.anim.AlikeAnim
;
import
com.mints.enjoyboxjia.read.anim.CoverAnim
;
import
com.mints.enjoyboxjia.read.anim.NoneAnim
;
import
com.mints.enjoyboxjia.read.anim.PageAnim
;
import
com.mints.enjoyboxjia.read.anim.SlideAnim
;
import
com.mints.enjoyboxjia.read.models.BookModel
;
import
java.io.IOException
;
public
class
YPageView
extends
View
implements
SlideAnim
.
OnPageChangeListener
{
/**
* 属性
*/
//背景颜色
//private int bgColor = 0xFFCEC29C;
//内容加载器
PageLoader
mPageLoader
;
//触摸事件位移记录
int
mStartX
=
0
;
int
mStartY
=
0
;
//是否是在移动
private
boolean
isMove
=
false
;
// 唤醒菜单的区域
private
RectF
mCenterRect
=
null
;
//中心点击事件回调
private
OnCenterClickListener
listener
;
//是否能触摸
boolean
canTouch
=
true
;
//翻页方向
boolean
isNext
=
true
;
//翻页动画
AnimType
animType
=
AnimType
.
SLIDE
;
PageAnim
pageAnim
;
public
YPageView
(
Context
context
)
{
this
(
context
,
null
);
}
public
YPageView
(
Context
context
,
AttributeSet
attrs
)
{
this
(
context
,
attrs
,
0
);
}
public
YPageView
(
Context
context
,
AttributeSet
attrs
,
int
defStyleAttr
)
{
super
(
context
,
attrs
,
defStyleAttr
);
}
/*******************************初始化方法***************************************/
private
void
initData
()
throws
IOException
{
setAnimType
(
animType
);
mPageLoader
.
initDimens
();
mPageLoader
.
loadChapters
();
}
public
void
showCategory
()
{
mPageLoader
.
initData
();
}
public
void
showContent
()
{
mPageLoader
.
reloadPageList
();
}
/*******************************自定义绘制方法***************************************/
@Override
protected
void
onSizeChanged
(
int
w
,
int
h
,
int
oldw
,
int
oldh
)
{
super
.
onSizeChanged
(
w
,
h
,
oldw
,
oldh
);
try
{
initData
();
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
//自定义绘制
@Override
protected
void
onDraw
(
Canvas
canvas
)
{
//canvas.drawColor(bgColor);
// mPageLoader.drawPage(coverAnimation.getmNextBitmap());
if
(
pageAnim
==
null
)
return
;
pageAnim
.
drawViewPages
(
canvas
);
}
/*******************************Setter and Getter***************************************/
public
PageLoader
getPageLoader
(
BookModel
bookModel
)
{
if
(
mPageLoader
!=
null
)
return
mPageLoader
;
mPageLoader
=
new
NetworkPageLoader
(
this
,
bookModel
);
return
mPageLoader
;
}
public
void
setOnCenterClickListener
(
OnCenterClickListener
listener
)
{
this
.
listener
=
listener
;
}
public
void
setAnimType
(
AnimType
animType
)
{
this
.
animType
=
animType
;
if
(
this
.
getWidth
()
==
0
||
getHeight
()
==
0
)
return
;
Bitmap
tempBitmap
=
null
;
if
(
pageAnim
!=
null
)
tempBitmap
=
pageAnim
.
getmNextBitmap
().
copy
(
Bitmap
.
Config
.
RGB_565
,
true
);
//显示出来后再创建
switch
(
animType
)
{
case
COVER:
pageAnim
=
new
CoverAnim
(
this
,
this
);
break
;
case
ALIKE:
pageAnim
=
new
AlikeAnim
(
this
,
this
);
break
;
case
SLIDE:
pageAnim
=
new
SlideAnim
(
this
,
this
);
break
;
default
:
pageAnim
=
new
NoneAnim
(
this
,
this
);
break
;
}
if
(
tempBitmap
!=
null
)
{
pageAnim
.
setmCurBitmap
(
tempBitmap
);
}
pageAnim
.
changePage
();
}
public
AnimType
getAnimType
()
{
return
animType
;
}
@Override
public
boolean
onTouchEvent
(
MotionEvent
event
)
{
super
.
onTouchEvent
(
event
);
if
(!
canTouch
&&
event
.
getAction
()
!=
MotionEvent
.
ACTION_DOWN
)
return
true
;
int
x
=
(
int
)
event
.
getX
();
int
y
=
(
int
)
event
.
getY
();
switch
(
event
.
getAction
())
{
case
MotionEvent
.
ACTION_DOWN
:
mStartX
=
x
;
mStartY
=
y
;
isMove
=
false
;
//canTouch = mTouchListener.onTouch();
pageAnim
.
onTouchEvent
(
event
);
break
;
case
MotionEvent
.
ACTION_MOVE
:
// 判断是否大于最小滑动值。
int
slop
=
ViewConfiguration
.
get
(
getContext
()).
getScaledTouchSlop
();
if
(!
isMove
)
{
isMove
=
Math
.
abs
(
mStartX
-
event
.
getX
())
>
100
||
Math
.
abs
(
mStartY
-
event
.
getY
())
>
slop
;
isNext
=
event
.
getX
()
-
mStartX
<
0
;
}
if
(
isMove
)
{
pageAnim
.
onTouchEvent
(
event
);
}
break
;
case
MotionEvent
.
ACTION_UP
:
if
(!
isMove
)
{
//设置中间区域范围
if
(
mCenterRect
==
null
)
{
mCenterRect
=
new
RectF
(
getWidth
()
/
5
,
getHeight
()
/
3
,
getWidth
()
*
4
/
5
,
getHeight
()
*
2
/
3
);
}
//是否点击了中间
if
(
mCenterRect
.
contains
(
x
,
y
))
{
// if (mTouchListener != null) {
// mTouchListener.center();
// }
if
(
listener
!=
null
)
listener
.
centerClicked
();
return
true
;
}
}
//如果滑动了,则进行翻页
if
(
isMove
)
{
// if (isNext) mPageLoader.nextPage();
// else mPageLoader.prePage();
isNext
=
true
;
isMove
=
!
isMove
;
}
pageAnim
.
onTouchEvent
(
event
);
break
;
}
return
true
;
}
@Override
public
void
computeScroll
()
{
// 判断Scroller是否执行完毕
//进行滑动
Log
.
v
(
"yzll"
,
"computScroll"
);
if
(
pageAnim
==
null
)
return
;
pageAnim
.
scrollAnim
();
super
.
computeScroll
();
}
//判断是否存在上一页
private
boolean
hasPrevPage
()
{
return
mPageLoader
.
prePage
();
}
//判断是否下一页存在
private
boolean
hasNextPage
()
{
return
mPageLoader
.
nextPage
();
}
//绘制下一页
public
void
drawNextPage
()
{
pageAnim
.
changePage
();
drawCurPage
();
}
//绘制当前页
public
void
drawCurPage
()
{
mPageLoader
.
drawPage
(
pageAnim
.
getmNextBitmap
());
}
//取消翻页
public
void
cancelChangePage
()
{
mPageLoader
.
cancelChangePage
();
}
/*********************interface implements*************************/
public
interface
OnCenterClickListener
{
void
centerClicked
();
}
@Override
public
boolean
hasPrev
()
{
return
this
.
hasPrevPage
();
}
@Override
public
boolean
hasNext
()
{
return
this
.
hasNextPage
();
}
@Override
public
void
pageCancel
()
{
cancelChangePage
();
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/anim/AlikeAnim.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
anim
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.graphics.Color
;
import
android.graphics.ColorMatrix
;
import
android.graphics.ColorMatrixColorFilter
;
import
android.graphics.Matrix
;
import
android.graphics.Paint
;
import
android.graphics.Path
;
import
android.graphics.PointF
;
import
android.graphics.Region
;
import
android.graphics.drawable.GradientDrawable
;
import
android.os.Build
;
import
android.view.MotionEvent
;
import
android.view.View
;
import
com.mints.enjoyboxjia.read.Direction
;
public
class
AlikeAnim
extends
PageAnim
{
private
static
final
String
TAG
=
"SimulationPageAnim"
;
private
int
mCornerX
=
1
;
// 拖拽点对应的页脚
private
int
mCornerY
=
1
;
private
Path
mPath0
;
private
Path
mPath1
;
private
PointF
mBezierStart1
=
new
PointF
();
// 贝塞尔曲线起始点
private
PointF
mBezierControl1
=
new
PointF
();
// 贝塞尔曲线控制点
private
PointF
mBeziervertex1
=
new
PointF
();
// 贝塞尔曲线顶点
private
PointF
mBezierEnd1
=
new
PointF
();
// 贝塞尔曲线结束点
private
PointF
mBezierStart2
=
new
PointF
();
// 另一条贝塞尔曲线
private
PointF
mBezierControl2
=
new
PointF
();
private
PointF
mBeziervertex2
=
new
PointF
();
private
PointF
mBezierEnd2
=
new
PointF
();
private
float
mMiddleX
;
private
float
mMiddleY
;
private
float
mDegrees
;
private
float
mTouchToCornerDis
;
private
ColorMatrixColorFilter
mColorMatrixFilter
;
private
Matrix
mMatrix
;
private
float
[]
mMatrixArray
=
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
1.0f
};
private
boolean
mIsRTandLB
;
// 是否属于右上左下
private
float
mMaxLength
;
private
GradientDrawable
mBackShadowDrawableLR
;
// 有阴影的GradientDrawable
private
GradientDrawable
mBackShadowDrawableRL
;
private
GradientDrawable
mFolderShadowDrawableLR
;
private
GradientDrawable
mFolderShadowDrawableRL
;
private
GradientDrawable
mFrontShadowDrawableHBT
;
private
GradientDrawable
mFrontShadowDrawableHTB
;
private
GradientDrawable
mFrontShadowDrawableVLR
;
private
GradientDrawable
mFrontShadowDrawableVRL
;
private
Paint
mPaint
;
// 适配 android 高版本无法使用 XOR 的问题
private
Path
mXORPath
;
public
AlikeAnim
(
View
view
,
OnPageChangeListener
listener
)
{
super
(
view
,
listener
);
mPath0
=
new
Path
();
mPath1
=
new
Path
();
mXORPath
=
new
Path
();
mMaxLength
=
(
float
)
Math
.
hypot
(
mViewWidth
,
mViewHeight
);
mPaint
=
new
Paint
();
mPaint
.
setStyle
(
Paint
.
Style
.
FILL
);
createDrawable
();
ColorMatrix
cm
=
new
ColorMatrix
();
//设置颜色数组
float
array
[]
=
{
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
,
0
,
0
,
0
,
0
,
1
,
0
};
cm
.
set
(
array
);
mColorMatrixFilter
=
new
ColorMatrixColorFilter
(
cm
);
mMatrix
=
new
Matrix
();
mTouchX
=
0.01f
;
// 不让x,y为0,否则在点计算时会有问题
mTouchY
=
0.01f
;
}
@Override
public
void
drawMove
(
Canvas
canvas
)
{
switch
(
mDirection
)
{
case
NEXT:
calcPoints
();
drawCurrentPageArea
(
canvas
,
mCurBitmap
,
mPath0
);
drawNextPageAreaAndShadow
(
canvas
,
mNextBitmap
);
drawCurrentPageShadow
(
canvas
);
drawCurrentBackArea
(
canvas
,
mCurBitmap
);
break
;
default
:
calcPoints
();
drawCurrentPageArea
(
canvas
,
mNextBitmap
,
mPath0
);
drawNextPageAreaAndShadow
(
canvas
,
mCurBitmap
);
drawCurrentPageShadow
(
canvas
);
drawCurrentBackArea
(
canvas
,
mNextBitmap
);
break
;
}
}
@Override
public
void
startAnim
()
{
int
dx
,
dy
;
// dx 水平方向滑动的距离,负值会使滚动向左滚动
// dy 垂直方向滑动的距离,负值会使滚动向上滚动
if
(
isCancel
)
{
if
(
mCornerX
>
0
&&
mDirection
.
equals
(
Direction
.
NEXT
))
{
dx
=
(
int
)
(
mViewWidth
-
mTouchX
);
}
else
{
dx
=
-(
int
)
mTouchX
;
}
if
(!
mDirection
.
equals
(
Direction
.
NEXT
))
{
dx
=
(
int
)
-(
mViewWidth
+
mTouchX
);
}
if
(
mCornerY
>
0
)
{
dy
=
(
int
)
(
mViewHeight
-
mTouchY
);
}
else
{
dy
=
-(
int
)
mTouchY
;
// 防止mTouchY最终变为0
}
}
else
{
if
(
mCornerX
>
0
&&
mDirection
.
equals
(
Direction
.
NEXT
))
{
dx
=
-(
int
)
(
mViewWidth
+
mTouchX
);
}
else
{
dx
=
(
int
)
(
mViewWidth
-
mTouchX
+
mViewWidth
);
}
if
(
mCornerY
>
0
)
{
dy
=
(
int
)
(
mViewHeight
-
mTouchY
);
}
else
{
dy
=
(
int
)
(
1
-
mTouchY
);
// 防止mTouchY最终变为0
}
}
mScroller
.
startScroll
((
int
)
mTouchX
,
(
int
)
mTouchY
,
dx
,
dy
,
400
);
}
@Override
public
boolean
onTouchEvent
(
MotionEvent
event
){
//点击位置
int
x
=
(
int
)
event
.
getX
();
int
y
=
(
int
)
event
.
getY
();
//更新滑动坐标
mLastX
=
mTouchX
;
mLastY
=
mTouchY
;
mTouchX
=
x
;
mTouchY
=
y
;
//触摸y中间位置吧y变成屏幕高度
if
((
mStartY
>
mViewHeight
/
3
&&
mStartY
<
mViewHeight
*
2
/
3
)
||
mDirection
.
equals
(
Direction
.
PRE
))
{
mTouchY
=
mViewHeight
;
}
if
(
mStartY
>
mViewHeight
/
3
&&
mStartY
<
mViewHeight
/
2
&&
mDirection
.
equals
(
Direction
.
NEXT
))
{
mTouchY
=
1
;
}
switch
(
event
.
getAction
())
{
case
MotionEvent
.
ACTION_DOWN
:
mStartX
=
x
;
mStartY
=
y
;
//移动的点击位置
mLastX
=
0
;
mLastY
=
0
;
//未开始动画
isAnim
=
false
;
//取消
isCancel
=
false
;
//默认有下一页
noNext
=
false
;
//默认未移动
isMove
=
false
;
calcCornerXY
(
x
,
y
);
break
;
case
MotionEvent
.
ACTION_MOVE
:
//判断是否移动了
if
(!
isMove
)
{
isMove
=
Math
.
abs
(
mStartX
-
x
)
>
slop
||
Math
.
abs
(
mStartY
-
y
)
>
slop
;
}
//处理滑动
if
(
isMove
)
{
//还未开始滑动
if
(
mLastX
==
mStartX
)
{
//判断方向
if
(
x
-
mStartX
>
0
)
{
mDirection
=
Direction
.
PRE
;
configDirection
(
mDirection
);
//如果一页不存在
if
(!
mListener
.
hasPrev
())
{
noNext
=
true
;
return
true
;
}
}
else
{
mDirection
=
Direction
.
NEXT
;
configDirection
(
mDirection
);
//如果一页不存在
if
(!
mListener
.
hasNext
())
{
noNext
=
true
;
return
true
;
}
}
}
//已经开始滑动
else
{
//判断是否需要取消翻页
//即滑动位置到了与初始滑动方向相反时
if
(
mDirection
==
Direction
.
NEXT
)
{
if
(
x
-
mLastX
>
0
)
{
isCancel
=
true
;
}
else
{
isCancel
=
false
;
}
}
else
{
if
(
x
-
mLastX
<
0
)
{
isCancel
=
true
;
}
else
{
isCancel
=
false
;
}
}
}
mLastX
=
x
;
mLastY
=
y
;
if
(!
noNext
){
isAnim
=
true
;
mView
.
invalidate
();
}
}
break
;
case
MotionEvent
.
ACTION_UP
:
if
(!
isMove
)
{
isAnim
=
true
;
if
(
x
<
mViewWidth
/
2
)
{
mDirection
=
Direction
.
PRE
;
}
else
{
mDirection
=
Direction
.
NEXT
;
}
configDirection
(
mDirection
);
if
(
mDirection
==
Direction
.
NEXT
)
{
//判断是否下一页存在
boolean
hasNext
=
mListener
.
hasNext
();
if
(!
hasNext
)
{
return
true
;
}
}
else
{
boolean
hasPrev
=
mListener
.
hasPrev
();
if
(!
hasPrev
)
{
return
true
;
}
}
}
// 是否取消翻页
if
(
isCancel
){
mListener
.
pageCancel
();
}
// 开启翻页效果
if
(!
noNext
)
{
startAnim
();
mView
.
invalidate
();
}
break
;
}
return
true
;
}
public
void
configDirection
(
Direction
direction
)
{
switch
(
direction
)
{
case
PRE:
//上一页滑动不出现对角
if
(
mStartX
>
mViewWidth
/
2
)
{
calcCornerXY
(
mStartX
,
mViewHeight
);
}
else
{
calcCornerXY
(
mViewWidth
-
mStartX
,
mViewHeight
);
}
break
;
case
NEXT:
if
(
mViewWidth
/
2
>
mStartX
)
{
calcCornerXY
(
mViewWidth
-
mStartX
,
mStartY
);
}
break
;
}
}
/**
* 创建阴影的GradientDrawable
*/
private
void
createDrawable
()
{
int
[]
color
=
{
0x333333
,
0xb0333333
};
mFolderShadowDrawableRL
=
new
GradientDrawable
(
GradientDrawable
.
Orientation
.
RIGHT_LEFT
,
color
);
mFolderShadowDrawableRL
.
setGradientType
(
GradientDrawable
.
LINEAR_GRADIENT
);
mFolderShadowDrawableLR
=
new
GradientDrawable
(
GradientDrawable
.
Orientation
.
LEFT_RIGHT
,
color
);
mFolderShadowDrawableLR
.
setGradientType
(
GradientDrawable
.
LINEAR_GRADIENT
);
// 背面颜色组
int
[]
mBackShadowColors
=
new
int
[]{
0xff111111
,
0x111111
};
mBackShadowDrawableRL
=
new
GradientDrawable
(
GradientDrawable
.
Orientation
.
RIGHT_LEFT
,
mBackShadowColors
);
mBackShadowDrawableRL
.
setGradientType
(
GradientDrawable
.
LINEAR_GRADIENT
);
mBackShadowDrawableLR
=
new
GradientDrawable
(
GradientDrawable
.
Orientation
.
LEFT_RIGHT
,
mBackShadowColors
);
mBackShadowDrawableLR
.
setGradientType
(
GradientDrawable
.
LINEAR_GRADIENT
);
// 前面颜色组
int
[]
mFrontShadowColors
=
new
int
[]{
0x80111111
,
0x111111
};
mFrontShadowDrawableVLR
=
new
GradientDrawable
(
GradientDrawable
.
Orientation
.
LEFT_RIGHT
,
mFrontShadowColors
);
mFrontShadowDrawableVLR
.
setGradientType
(
GradientDrawable
.
LINEAR_GRADIENT
);
mFrontShadowDrawableVRL
=
new
GradientDrawable
(
GradientDrawable
.
Orientation
.
RIGHT_LEFT
,
mFrontShadowColors
);
mFrontShadowDrawableVRL
.
setGradientType
(
GradientDrawable
.
LINEAR_GRADIENT
);
mFrontShadowDrawableHTB
=
new
GradientDrawable
(
GradientDrawable
.
Orientation
.
TOP_BOTTOM
,
mFrontShadowColors
);
mFrontShadowDrawableHTB
.
setGradientType
(
GradientDrawable
.
LINEAR_GRADIENT
);
mFrontShadowDrawableHBT
=
new
GradientDrawable
(
GradientDrawable
.
Orientation
.
BOTTOM_TOP
,
mFrontShadowColors
);
mFrontShadowDrawableHBT
.
setGradientType
(
GradientDrawable
.
LINEAR_GRADIENT
);
}
/**
* 绘制翻起页背面
*
* @param canvas
* @param bitmap
*/
private
void
drawCurrentBackArea
(
Canvas
canvas
,
Bitmap
bitmap
)
{
int
i
=
(
int
)
(
mBezierStart1
.
x
+
mBezierControl1
.
x
)
/
2
;
float
f1
=
Math
.
abs
(
i
-
mBezierControl1
.
x
);
int
i1
=
(
int
)
(
mBezierStart2
.
y
+
mBezierControl2
.
y
)
/
2
;
float
f2
=
Math
.
abs
(
i1
-
mBezierControl2
.
y
);
float
f3
=
Math
.
min
(
f1
,
f2
);
mPath1
.
reset
();
mPath1
.
moveTo
(
mBeziervertex2
.
x
,
mBeziervertex2
.
y
);
mPath1
.
lineTo
(
mBeziervertex1
.
x
,
mBeziervertex1
.
y
);
mPath1
.
lineTo
(
mBezierEnd1
.
x
,
mBezierEnd1
.
y
);
mPath1
.
lineTo
(
mTouchX
,
mTouchY
);
mPath1
.
lineTo
(
mBezierEnd2
.
x
,
mBezierEnd2
.
y
);
mPath1
.
close
();
GradientDrawable
mFolderShadowDrawable
;
int
left
;
int
right
;
if
(
mIsRTandLB
)
{
left
=
(
int
)
(
mBezierStart1
.
x
-
1
);
right
=
(
int
)
(
mBezierStart1
.
x
+
f3
+
1
);
mFolderShadowDrawable
=
mFolderShadowDrawableLR
;
}
else
{
left
=
(
int
)
(
mBezierStart1
.
x
-
f3
-
1
);
right
=
(
int
)
(
mBezierStart1
.
x
+
1
);
mFolderShadowDrawable
=
mFolderShadowDrawableRL
;
}
canvas
.
save
();
try
{
canvas
.
clipPath
(
mPath0
);
canvas
.
clipPath
(
mPath1
,
Region
.
Op
.
INTERSECT
);
}
catch
(
Exception
e
)
{
}
mPaint
.
setColorFilter
(
mColorMatrixFilter
);
//对Bitmap进行取色
int
color
=
bitmap
.
getPixel
(
1
,
1
);
//获取对应的三色
int
red
=
(
color
&
0xff0000
)
>>
16
;
int
green
=
(
color
&
0x00ff00
)
>>
8
;
int
blue
=
(
color
&
0x0000ff
);
//转换成含有透明度的颜色
int
tempColor
=
Color
.
argb
(
200
,
red
,
green
,
blue
);
float
dis
=
(
float
)
Math
.
hypot
(
mCornerX
-
mBezierControl1
.
x
,
mBezierControl2
.
y
-
mCornerY
);
float
f8
=
(
mCornerX
-
mBezierControl1
.
x
)
/
dis
;
float
f9
=
(
mBezierControl2
.
y
-
mCornerY
)
/
dis
;
mMatrixArray
[
0
]
=
1
-
2
*
f9
*
f9
;
mMatrixArray
[
1
]
=
2
*
f8
*
f9
;
mMatrixArray
[
3
]
=
mMatrixArray
[
1
];
mMatrixArray
[
4
]
=
1
-
2
*
f8
*
f8
;
mMatrix
.
reset
();
mMatrix
.
setValues
(
mMatrixArray
);
mMatrix
.
preTranslate
(-
mBezierControl1
.
x
,
-
mBezierControl1
.
y
);
mMatrix
.
postTranslate
(
mBezierControl1
.
x
,
mBezierControl1
.
y
);
canvas
.
drawBitmap
(
bitmap
,
mMatrix
,
mPaint
);
//背景叠加
canvas
.
drawColor
(
tempColor
);
mPaint
.
setColorFilter
(
null
);
canvas
.
rotate
(
mDegrees
,
mBezierStart1
.
x
,
mBezierStart1
.
y
);
mFolderShadowDrawable
.
setBounds
(
left
,
(
int
)
mBezierStart1
.
y
,
right
,
(
int
)
(
mBezierStart1
.
y
+
mMaxLength
));
mFolderShadowDrawable
.
draw
(
canvas
);
canvas
.
restore
();
}
public
void
scrollAnim
()
{
if
(
mScroller
.
computeScrollOffset
())
{
int
x
=
mScroller
.
getCurrX
();
int
y
=
mScroller
.
getCurrY
();
mLastX
=
mTouchX
;
mLastY
=
mTouchY
;
mTouchX
=
x
;
mTouchY
=
y
;
//触摸y中间位置吧y变成屏幕高度
if
((
mStartY
>
mViewHeight
/
3
&&
mStartY
<
mViewHeight
*
2
/
3
)
||
mDirection
.
equals
(
Direction
.
PRE
))
{
mTouchY
=
mViewHeight
;
}
if
(
mStartY
>
mViewHeight
/
3
&&
mStartY
<
mViewHeight
/
2
&&
mDirection
.
equals
(
Direction
.
NEXT
))
{
mTouchY
=
1
;
}
if
(
mScroller
.
getFinalX
()
==
x
&&
mScroller
.
getFinalY
()
==
y
){
isAnim
=
false
;
}
mView
.
postInvalidate
();
}
}
/**
* 绘制翻起页的阴影
*
* @param canvas
*/
private
void
drawCurrentPageShadow
(
Canvas
canvas
)
{
double
degree
;
if
(
mIsRTandLB
)
{
degree
=
Math
.
PI
/
4
-
Math
.
atan2
(
mBezierControl1
.
y
-
mTouchY
,
mTouchX
-
mBezierControl1
.
x
);
}
else
{
degree
=
Math
.
PI
/
4
-
Math
.
atan2
(
mTouchY
-
mBezierControl1
.
y
,
mTouchX
-
mBezierControl1
.
x
);
}
// 翻起页阴影顶点与touch点的距离
double
d1
=
(
float
)
25
*
1.414
*
Math
.
cos
(
degree
);
double
d2
=
(
float
)
25
*
1.414
*
Math
.
sin
(
degree
);
float
x
=
(
float
)
(
mTouchX
+
d1
);
float
y
;
if
(
mIsRTandLB
)
{
y
=
(
float
)
(
mTouchY
+
d2
);
}
else
{
y
=
(
float
)
(
mTouchY
-
d2
);
}
mPath1
.
reset
();
mPath1
.
moveTo
(
x
,
y
);
mPath1
.
lineTo
(
mTouchX
,
mTouchY
);
mPath1
.
lineTo
(
mBezierControl1
.
x
,
mBezierControl1
.
y
);
mPath1
.
lineTo
(
mBezierStart1
.
x
,
mBezierStart1
.
y
);
mPath1
.
close
();
float
rotateDegrees
;
canvas
.
save
();
try
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
P
)
{
mXORPath
.
reset
();
mXORPath
.
moveTo
(
0
f
,
0
f
);
mXORPath
.
lineTo
(
canvas
.
getWidth
(),
0
f
);
mXORPath
.
lineTo
(
canvas
.
getWidth
(),
canvas
.
getHeight
());
mXORPath
.
lineTo
(
0
f
,
canvas
.
getHeight
());
mXORPath
.
close
();
// 取 path 的补集,作为 canvas 的交集
mXORPath
.
op
(
mPath0
,
Path
.
Op
.
XOR
);
canvas
.
clipPath
(
mXORPath
);
}
else
{
canvas
.
clipPath
(
mPath0
,
Region
.
Op
.
XOR
);
}
canvas
.
clipPath
(
mPath1
,
Region
.
Op
.
INTERSECT
);
}
catch
(
Exception
e
)
{
// TODO: handle exception
}
int
leftx
;
int
rightx
;
GradientDrawable
mCurrentPageShadow
;
if
(
mIsRTandLB
)
{
leftx
=
(
int
)
(
mBezierControl1
.
x
);
rightx
=
(
int
)
mBezierControl1
.
x
+
25
;
mCurrentPageShadow
=
mFrontShadowDrawableVLR
;
}
else
{
leftx
=
(
int
)
(
mBezierControl1
.
x
-
25
);
rightx
=
(
int
)
mBezierControl1
.
x
+
1
;
mCurrentPageShadow
=
mFrontShadowDrawableVRL
;
}
rotateDegrees
=
(
float
)
Math
.
toDegrees
(
Math
.
atan2
(
mTouchX
-
mBezierControl1
.
x
,
mBezierControl1
.
y
-
mTouchY
));
canvas
.
rotate
(
rotateDegrees
,
mBezierControl1
.
x
,
mBezierControl1
.
y
);
mCurrentPageShadow
.
setBounds
(
leftx
,
(
int
)
(
mBezierControl1
.
y
-
mMaxLength
),
rightx
,
(
int
)
(
mBezierControl1
.
y
));
mCurrentPageShadow
.
draw
(
canvas
);
canvas
.
restore
();
mPath1
.
reset
();
mPath1
.
moveTo
(
x
,
y
);
mPath1
.
lineTo
(
mTouchX
,
mTouchY
);
mPath1
.
lineTo
(
mBezierControl2
.
x
,
mBezierControl2
.
y
);
mPath1
.
lineTo
(
mBezierStart2
.
x
,
mBezierStart2
.
y
);
mPath1
.
close
();
canvas
.
save
();
try
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
P
)
{
mXORPath
.
reset
();
mXORPath
.
moveTo
(
0
f
,
0
f
);
mXORPath
.
lineTo
(
canvas
.
getWidth
(),
0
f
);
mXORPath
.
lineTo
(
canvas
.
getWidth
(),
canvas
.
getHeight
());
mXORPath
.
lineTo
(
0
f
,
canvas
.
getHeight
());
mXORPath
.
close
();
// 取 path 的补给,作为 canvas 的交集
mXORPath
.
op
(
mPath0
,
Path
.
Op
.
XOR
);
canvas
.
clipPath
(
mXORPath
);
}
else
{
canvas
.
clipPath
(
mPath0
,
Region
.
Op
.
XOR
);
}
canvas
.
clipPath
(
mPath1
,
Region
.
Op
.
INTERSECT
);
}
catch
(
Exception
e
)
{
}
if
(
mIsRTandLB
)
{
leftx
=
(
int
)
(
mBezierControl2
.
y
);
rightx
=
(
int
)
(
mBezierControl2
.
y
+
25
);
mCurrentPageShadow
=
mFrontShadowDrawableHTB
;
}
else
{
leftx
=
(
int
)
(
mBezierControl2
.
y
-
25
);
rightx
=
(
int
)
(
mBezierControl2
.
y
+
1
);
mCurrentPageShadow
=
mFrontShadowDrawableHBT
;
}
rotateDegrees
=
(
float
)
Math
.
toDegrees
(
Math
.
atan2
(
mBezierControl2
.
y
-
mTouchY
,
mBezierControl2
.
x
-
mTouchX
));
canvas
.
rotate
(
rotateDegrees
,
mBezierControl2
.
x
,
mBezierControl2
.
y
);
float
temp
;
if
(
mBezierControl2
.
y
<
0
)
temp
=
mBezierControl2
.
y
-
mViewHeight
;
else
temp
=
mBezierControl2
.
y
;
int
hmg
=
(
int
)
Math
.
hypot
(
mBezierControl2
.
x
,
temp
);
if
(
hmg
>
mMaxLength
)
mCurrentPageShadow
.
setBounds
((
int
)
(
mBezierControl2
.
x
-
25
)
-
hmg
,
leftx
,
(
int
)
(
mBezierControl2
.
x
+
mMaxLength
)
-
hmg
,
rightx
);
else
mCurrentPageShadow
.
setBounds
(
(
int
)
(
mBezierControl2
.
x
-
mMaxLength
),
leftx
,
(
int
)
(
mBezierControl2
.
x
),
rightx
);
mCurrentPageShadow
.
draw
(
canvas
);
canvas
.
restore
();
}
private
void
drawNextPageAreaAndShadow
(
Canvas
canvas
,
Bitmap
bitmap
)
{
mPath1
.
reset
();
mPath1
.
moveTo
(
mBezierStart1
.
x
,
mBezierStart1
.
y
);
mPath1
.
lineTo
(
mBeziervertex1
.
x
,
mBeziervertex1
.
y
);
mPath1
.
lineTo
(
mBeziervertex2
.
x
,
mBeziervertex2
.
y
);
mPath1
.
lineTo
(
mBezierStart2
.
x
,
mBezierStart2
.
y
);
mPath1
.
lineTo
(
mCornerX
,
mCornerY
);
mPath1
.
close
();
mDegrees
=
(
float
)
Math
.
toDegrees
(
Math
.
atan2
(
mBezierControl1
.
x
-
mCornerX
,
mBezierControl2
.
y
-
mCornerY
));
int
leftx
;
int
rightx
;
GradientDrawable
mBackShadowDrawable
;
if
(
mIsRTandLB
)
{
//左下及右上
leftx
=
(
int
)
(
mBezierStart1
.
x
);
rightx
=
(
int
)
(
mBezierStart1
.
x
+
mTouchToCornerDis
/
4
);
mBackShadowDrawable
=
mBackShadowDrawableLR
;
}
else
{
leftx
=
(
int
)
(
mBezierStart1
.
x
-
mTouchToCornerDis
/
4
);
rightx
=
(
int
)
mBezierStart1
.
x
;
mBackShadowDrawable
=
mBackShadowDrawableRL
;
}
canvas
.
save
();
try
{
canvas
.
clipPath
(
mPath0
);
canvas
.
clipPath
(
mPath1
,
Region
.
Op
.
INTERSECT
);
}
catch
(
Exception
e
)
{
}
canvas
.
drawBitmap
(
bitmap
,
0
,
0
,
null
);
canvas
.
rotate
(
mDegrees
,
mBezierStart1
.
x
,
mBezierStart1
.
y
);
mBackShadowDrawable
.
setBounds
(
leftx
,
(
int
)
mBezierStart1
.
y
,
rightx
,
(
int
)
(
mMaxLength
+
mBezierStart1
.
y
));
//左上及右下角的xy坐标值,构成一个矩形
mBackShadowDrawable
.
draw
(
canvas
);
canvas
.
restore
();
}
private
void
drawCurrentPageArea
(
Canvas
canvas
,
Bitmap
bitmap
,
Path
path
)
{
mPath0
.
reset
();
mPath0
.
moveTo
(
mBezierStart1
.
x
,
mBezierStart1
.
y
);
mPath0
.
quadTo
(
mBezierControl1
.
x
,
mBezierControl1
.
y
,
mBezierEnd1
.
x
,
mBezierEnd1
.
y
);
mPath0
.
lineTo
(
mTouchX
,
mTouchY
);
mPath0
.
lineTo
(
mBezierEnd2
.
x
,
mBezierEnd2
.
y
);
mPath0
.
quadTo
(
mBezierControl2
.
x
,
mBezierControl2
.
y
,
mBezierStart2
.
x
,
mBezierStart2
.
y
);
mPath0
.
lineTo
(
mCornerX
,
mCornerY
);
mPath0
.
close
();
canvas
.
save
();
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
P
)
{
mXORPath
.
reset
();
mXORPath
.
moveTo
(
0
f
,
0
f
);
mXORPath
.
lineTo
(
canvas
.
getWidth
(),
0
f
);
mXORPath
.
lineTo
(
canvas
.
getWidth
(),
canvas
.
getHeight
());
mXORPath
.
lineTo
(
0
f
,
canvas
.
getHeight
());
mXORPath
.
close
();
// 取 path 的补给,作为 canvas 的交集
mXORPath
.
op
(
path
,
Path
.
Op
.
XOR
);
canvas
.
clipPath
(
mXORPath
);
}
else
{
canvas
.
clipPath
(
path
,
Region
.
Op
.
XOR
);
}
canvas
.
drawBitmap
(
bitmap
,
0
,
0
,
null
);
try
{
canvas
.
restore
();
}
catch
(
Exception
e
)
{
}
}
/**
* 计算拖拽点对应的拖拽脚
*
* @param x
* @param y
*/
public
void
calcCornerXY
(
float
x
,
float
y
)
{
if
(
x
<=
mViewWidth
/
2
)
{
mCornerX
=
0
;
}
else
{
mCornerX
=
mViewWidth
;
}
if
(
y
<=
mViewHeight
/
2
)
{
mCornerY
=
0
;
}
else
{
mCornerY
=
mViewHeight
;
}
if
((
mCornerX
==
0
&&
mCornerY
==
mViewHeight
)
||
(
mCornerX
==
mViewWidth
&&
mCornerY
==
0
))
{
mIsRTandLB
=
true
;
}
else
{
mIsRTandLB
=
false
;
}
}
private
void
calcPoints
()
{
mMiddleX
=
(
mTouchX
+
mCornerX
)
/
2
;
mMiddleY
=
(
mTouchY
+
mCornerY
)
/
2
;
mBezierControl1
.
x
=
mMiddleX
-
(
mCornerY
-
mMiddleY
)
*
(
mCornerY
-
mMiddleY
)
/
(
mCornerX
-
mMiddleX
);
mBezierControl1
.
y
=
mCornerY
;
mBezierControl2
.
x
=
mCornerX
;
float
f4
=
mCornerY
-
mMiddleY
;
if
(
f4
==
0
)
{
mBezierControl2
.
y
=
mMiddleY
-
(
mCornerX
-
mMiddleX
)
*
(
mCornerX
-
mMiddleX
)
/
0.1f
;
}
else
{
mBezierControl2
.
y
=
mMiddleY
-
(
mCornerX
-
mMiddleX
)
*
(
mCornerX
-
mMiddleX
)
/
(
mCornerY
-
mMiddleY
);
}
mBezierStart1
.
x
=
mBezierControl1
.
x
-
(
mCornerX
-
mBezierControl1
.
x
)
/
2
;
mBezierStart1
.
y
=
mCornerY
;
// 当mBezierStart1.x < 0或者mBezierStart1.x > 480时
// 如果继续翻页,会出现BUG故在此限制
if
(
mTouchX
>
0
&&
mTouchX
<
mViewWidth
)
{
if
(
mBezierStart1
.
x
<
0
||
mBezierStart1
.
x
>
mViewWidth
)
{
if
(
mBezierStart1
.
x
<
0
)
mBezierStart1
.
x
=
mViewWidth
-
mBezierStart1
.
x
;
float
f1
=
Math
.
abs
(
mCornerX
-
mTouchX
);
float
f2
=
mViewWidth
*
f1
/
mBezierStart1
.
x
;
mTouchX
=
Math
.
abs
(
mCornerX
-
f2
);
float
f3
=
Math
.
abs
(
mCornerX
-
mTouchX
)
*
Math
.
abs
(
mCornerY
-
mTouchY
)
/
f1
;
mTouchY
=
Math
.
abs
(
mCornerY
-
f3
);
mMiddleX
=
(
mTouchX
+
mCornerX
)
/
2
;
mMiddleY
=
(
mTouchY
+
mCornerY
)
/
2
;
mBezierControl1
.
x
=
mMiddleX
-
(
mCornerY
-
mMiddleY
)
*
(
mCornerY
-
mMiddleY
)
/
(
mCornerX
-
mMiddleX
);
mBezierControl1
.
y
=
mCornerY
;
mBezierControl2
.
x
=
mCornerX
;
float
f5
=
mCornerY
-
mMiddleY
;
if
(
f5
==
0
)
{
mBezierControl2
.
y
=
mMiddleY
-
(
mCornerX
-
mMiddleX
)
*
(
mCornerX
-
mMiddleX
)
/
0.1f
;
}
else
{
mBezierControl2
.
y
=
mMiddleY
-
(
mCornerX
-
mMiddleX
)
*
(
mCornerX
-
mMiddleX
)
/
(
mCornerY
-
mMiddleY
);
}
mBezierStart1
.
x
=
mBezierControl1
.
x
-
(
mCornerX
-
mBezierControl1
.
x
)
/
2
;
}
}
mBezierStart2
.
x
=
mCornerX
;
mBezierStart2
.
y
=
mBezierControl2
.
y
-
(
mCornerY
-
mBezierControl2
.
y
)
/
2
;
mTouchToCornerDis
=
(
float
)
Math
.
hypot
((
mTouchX
-
mCornerX
),
(
mTouchY
-
mCornerY
));
mBezierEnd1
=
getCross
(
new
PointF
(
mTouchX
,
mTouchY
),
mBezierControl1
,
mBezierStart1
,
mBezierStart2
);
mBezierEnd2
=
getCross
(
new
PointF
(
mTouchX
,
mTouchY
),
mBezierControl2
,
mBezierStart1
,
mBezierStart2
);
mBeziervertex1
.
x
=
(
mBezierStart1
.
x
+
2
*
mBezierControl1
.
x
+
mBezierEnd1
.
x
)
/
4
;
mBeziervertex1
.
y
=
(
2
*
mBezierControl1
.
y
+
mBezierStart1
.
y
+
mBezierEnd1
.
y
)
/
4
;
mBeziervertex2
.
x
=
(
mBezierStart2
.
x
+
2
*
mBezierControl2
.
x
+
mBezierEnd2
.
x
)
/
4
;
mBeziervertex2
.
y
=
(
2
*
mBezierControl2
.
y
+
mBezierStart2
.
y
+
mBezierEnd2
.
y
)
/
4
;
}
/**
* 求解直线P1P2和直线P3P4的交点坐标
*
* @param P1
* @param P2
* @param P3
* @param P4
* @return
*/
private
PointF
getCross
(
PointF
P1
,
PointF
P2
,
PointF
P3
,
PointF
P4
)
{
PointF
CrossP
=
new
PointF
();
// 二元函数通式: y=ax+b
float
a1
=
(
P2
.
y
-
P1
.
y
)
/
(
P2
.
x
-
P1
.
x
);
float
b1
=
((
P1
.
x
*
P2
.
y
)
-
(
P2
.
x
*
P1
.
y
))
/
(
P1
.
x
-
P2
.
x
);
float
a2
=
(
P4
.
y
-
P3
.
y
)
/
(
P4
.
x
-
P3
.
x
);
float
b2
=
((
P3
.
x
*
P4
.
y
)
-
(
P4
.
x
*
P3
.
y
))
/
(
P3
.
x
-
P4
.
x
);
CrossP
.
x
=
(
b2
-
b1
)
/
(
a1
-
a2
);
CrossP
.
y
=
a1
*
CrossP
.
x
+
b1
;
return
CrossP
;
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/anim/ContentScaleAnimation.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
anim
;
import
android.graphics.Matrix
;
import
android.view.animation.Animation
;
import
android.view.animation.Transformation
;
public
class
ContentScaleAnimation
extends
Animation
{
private
float
mPivotX
;
private
float
mPivotY
;
// 控件左上角坐标
private
float
mStartX
;
private
float
mStartY
;
private
final
float
scaleTimes
;
private
boolean
mReverse
;
public
ContentScaleAnimation
(
float
mPivotXValue
,
float
mPivotYValue
,
float
scaleTimes
,
boolean
mReverse
)
{
this
.
mStartX
=
mPivotXValue
;
this
.
mStartY
=
mPivotYValue
;
this
.
scaleTimes
=
scaleTimes
;
this
.
mReverse
=
mReverse
;
}
@Override
protected
void
applyTransformation
(
float
interpolatedTime
,
Transformation
t
)
{
//缩放方法
Matrix
matrix
=
t
.
getMatrix
();
if
(
mReverse
)
{
matrix
.
postScale
(
1
+
(
scaleTimes
-
1
)
*
(
1.0f
-
interpolatedTime
),
1
+
(
scaleTimes
-
1
)
*
(
1.0f
-
interpolatedTime
),
mPivotX
-
mStartX
,
mPivotY
-
mStartY
);
}
else
{
matrix
.
postScale
(
1
+
(
scaleTimes
-
1
)
*
interpolatedTime
,
1
+
(
scaleTimes
-
1
)
*
interpolatedTime
,
mPivotX
-
mStartX
,
mPivotY
-
mStartY
);
//matrix.postScale(1 + (scaleTimes - 1) * interpolatedTime, 1 + (scaleTimes - 1) * interpolatedTime, mPivotX - mPivotXValue , 171 );
}
}
//缩放点坐标值
@Override
public
void
initialize
(
int
width
,
int
height
,
int
parentWidth
,
int
parentHeight
)
{
super
.
initialize
(
width
,
height
,
parentWidth
,
parentHeight
);
mPivotX
=
resolvePivotX
(
mStartX
,
parentWidth
,
width
);
mPivotY
=
resolvePivoY
(
mStartY
,
parentHeight
,
height
);
}
//缩放点坐标值 缩放点到自身左边距离/缩放点到父控件左边的距离=缩放点自身右侧距离/缩放点到父控件右边的距离
private
float
resolvePivotX
(
float
margingLeft
,
int
parentWidth
,
int
width
)
{
//换算得出的结果
return
(
margingLeft
*
parentWidth
)
/
(
parentWidth
-
width
);
}
private
float
resolvePivoY
(
float
marginTop
,
int
parentHeight
,
int
height
)
{
return
(
marginTop
*
parentHeight
)
/
(
parentHeight
-
height
);
}
public
void
reverse
()
{
mReverse
=
!
mReverse
;
}
public
boolean
getMReverse
()
{
return
mReverse
;
}
}
\ No newline at end of file
book/app/src/main/java/com/mints/enjoyboxjia/read/anim/CoverAnim.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
anim
;
import
android.graphics.Canvas
;
import
android.graphics.drawable.GradientDrawable
;
import
android.view.View
;
public
class
CoverAnim
extends
SlideAnim
{
private
GradientDrawable
mBackShadowDrawableLR
;
public
CoverAnim
(
View
view
,
OnPageChangeListener
mListener
)
{
super
(
view
,
mListener
);
int
[]
mBackShadowColors
=
new
int
[]
{
0x66000000
,
0x00000000
};
mBackShadowDrawableLR
=
new
GradientDrawable
(
GradientDrawable
.
Orientation
.
LEFT_RIGHT
,
mBackShadowColors
);
mBackShadowDrawableLR
.
setGradientType
(
GradientDrawable
.
LINEAR_GRADIENT
);
}
//添加阴影
public
void
addShadow
(
int
left
,
Canvas
canvas
)
{
mBackShadowDrawableLR
.
setBounds
(
left
,
0
,
left
+
30
,
mViewHeight
);
mBackShadowDrawableLR
.
draw
(
canvas
);
}
@Override
public
void
drawMove
(
Canvas
canvas
)
{
if
(!
isAnim
)
return
;
switch
(
mDirection
){
case
NEXT:
int
dis
=
(
int
)
(
mViewWidth
-
mStartX
+
mTouchX
);
if
(
dis
>
mViewWidth
){
dis
=
mViewWidth
;
}
//计算bitmap截取的区域
mSrcRect
.
left
=
mViewWidth
-
dis
;
//计算bitmap在canvas显示的区域
mDestRect
.
right
=
dis
;
canvas
.
drawBitmap
(
mNextBitmap
,
0
,
0
,
null
);
canvas
.
drawBitmap
(
mCurBitmap
,
mSrcRect
,
mDestRect
,
null
);
addShadow
(
dis
,
canvas
);
break
;
default
:
mSrcRect
.
left
=
(
int
)
(
mViewWidth
-
mTouchX
);
mDestRect
.
right
=
(
int
)
mTouchX
;
canvas
.
drawBitmap
(
mCurBitmap
,
0
,
0
,
null
);
canvas
.
drawBitmap
(
mNextBitmap
,
mSrcRect
,
mDestRect
,
null
);
addShadow
((
int
)
mTouchX
,
canvas
);
break
;
}
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/anim/NoneAnim.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
anim
;
import
android.graphics.Canvas
;
import
android.view.MotionEvent
;
import
android.view.View
;
import
com.mints.enjoyboxjia.read.Direction
;
public
class
NoneAnim
extends
PageAnim
{
public
NoneAnim
(
View
view
,
OnPageChangeListener
mListener
)
{
super
(
view
,
mListener
);
}
@Override
public
void
startAnim
()
{
}
@Override
public
boolean
onTouchEvent
(
MotionEvent
event
){
//点击位置
int
x
=
(
int
)
event
.
getX
();
int
y
=
(
int
)
event
.
getY
();
//更新滑动坐标
mLastX
=
mTouchX
;
mLastY
=
mTouchY
;
mTouchX
=
x
;
mTouchY
=
y
;
switch
(
event
.
getAction
())
{
case
MotionEvent
.
ACTION_DOWN
:
mStartX
=
x
;
mStartY
=
y
;
//移动的点击位置
mLastX
=
0
;
mLastY
=
0
;
//未开始动画
isAnim
=
false
;
//取消
isCancel
=
false
;
break
;
case
MotionEvent
.
ACTION_MOVE
:
//判断是否移动了
if
(!
isMove
)
{
isMove
=
Math
.
abs
(
mStartX
-
x
)
>
slop
||
Math
.
abs
(
mStartY
-
y
)
>
slop
;
}
//处理滑动
if
(
isMove
)
{
//还未开始滑动
if
(
mLastX
==
mStartX
)
{
//判断方向
if
(
x
-
mStartX
>
0
)
{
mDirection
=
Direction
.
PRE
;
//如果一页不存在
if
(!
mListener
.
hasPrev
())
{
noNext
=
true
;
return
true
;
}
}
else
{
mDirection
=
Direction
.
NEXT
;
//如果一页不存在
if
(!
mListener
.
hasNext
())
{
noNext
=
true
;
return
true
;
}
}
}
//已经开始滑动
else
{
//判断是否需要取消翻页
//即滑动位置到了与初始滑动方向相反时
if
(
mDirection
==
Direction
.
NEXT
)
{
if
(
x
-
mLastX
>
0
)
{
isCancel
=
true
;
}
else
{
isCancel
=
false
;
}
}
else
{
if
(
x
-
mLastX
<
0
)
{
isCancel
=
true
;
}
else
{
isCancel
=
false
;
}
}
}
mLastX
=
x
;
mLastY
=
y
;
isAnim
=
true
;
mView
.
invalidate
();
}
break
;
case
MotionEvent
.
ACTION_UP
:
if
(!
isMove
)
{
if
(
x
<
mViewWidth
/
2
)
{
mDirection
=
Direction
.
PRE
;
}
else
{
mDirection
=
Direction
.
NEXT
;
}
if
(
mDirection
==
Direction
.
NEXT
)
{
//判断是否下一页存在
boolean
hasNext
=
mListener
.
hasNext
();
if
(!
hasNext
)
{
return
true
;
}
}
else
{
boolean
hasPrev
=
mListener
.
hasPrev
();
if
(!
hasPrev
)
{
return
true
;
}
}
}
// 是否取消翻页
if
(
isCancel
){
mListener
.
pageCancel
();
}
// 开启翻页效果
if
(!
noNext
)
{
startAnim
();
mView
.
invalidate
();
}
break
;
}
return
true
;
}
@Override
public
void
scrollAnim
()
{
}
@Override
public
void
drawMove
(
Canvas
canvas
)
{
if
(
isCancel
){
canvas
.
drawBitmap
(
mCurBitmap
,
0
,
0
,
null
);
}
else
{
canvas
.
drawBitmap
(
mNextBitmap
,
0
,
0
,
null
);
}
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/anim/PageAnim.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
anim
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.graphics.Rect
;
import
android.view.MotionEvent
;
import
android.view.View
;
import
android.view.ViewConfiguration
;
import
android.widget.Scroller
;
import
com.mints.enjoyboxjia.read.Direction
;
public
abstract
class
PageAnim
{
//绘制的页面
Bitmap
mCurBitmap
;
Bitmap
mNextBitmap
;
//滑动器
public
Scroller
mScroller
;
//需要动画的视图
View
mView
;
//视图的尺寸
protected
int
mViewWidth
;
protected
int
mViewHeight
;
//起始点
protected
float
mStartX
;
protected
float
mStartY
;
//触碰点
protected
float
mTouchX
;
protected
float
mTouchY
;
//上一个触碰点
protected
float
mLastX
;
protected
float
mLastY
;
//是否在移动
protected
boolean
isMove
;
//最短滑动距离
int
slop
;
//滑动方向
Direction
mDirection
=
Direction
.
NONE
;
//是否取消翻页
boolean
isCancel
;
//页面位移矩阵
protected
Rect
mSrcRect
,
mDestRect
;
//是否开始动画
boolean
isAnim
=
false
;
//监听者
protected
OnPageChangeListener
mListener
;
//是否没下一页或者上一页
protected
boolean
noNext
=
false
;
public
PageAnim
(
View
view
,
OnPageChangeListener
mListener
){
mView
=
view
;
mScroller
=
new
Scroller
(
mView
.
getContext
());
this
.
mListener
=
mListener
;
initData
();
}
/***********************************public***********************************/
//初始化数据
protected
void
initData
(){
mViewWidth
=
mView
.
getWidth
();
mViewHeight
=
mView
.
getHeight
();
mCurBitmap
=
Bitmap
.
createBitmap
(
mView
.
getWidth
(),
mView
.
getHeight
(),
Bitmap
.
Config
.
RGB_565
);
mNextBitmap
=
Bitmap
.
createBitmap
(
mView
.
getWidth
(),
mView
.
getHeight
(),
Bitmap
.
Config
.
RGB_565
);
mSrcRect
=
new
Rect
(
0
,
0
,
mViewWidth
,
mViewHeight
);
mDestRect
=
new
Rect
(
0
,
0
,
mViewWidth
,
mViewHeight
);
slop
=
ViewConfiguration
.
get
(
mView
.
getContext
()).
getScaledTouchSlop
();
}
//画页面
public
void
drawViewPages
(
Canvas
canvas
){
if
(
isAnim
){
drawMove
(
canvas
);
}
else
{
if
(
isCancel
){
mNextBitmap
=
mCurBitmap
.
copy
(
Bitmap
.
Config
.
RGB_565
,
true
);
canvas
.
drawBitmap
(
mCurBitmap
,
0
,
0
,
null
);
}
else
{
canvas
.
drawBitmap
(
mNextBitmap
,
0
,
0
,
null
);
}
}
}
public
void
changePage
(){
Bitmap
bitmap
=
mCurBitmap
;
mCurBitmap
=
mNextBitmap
;
mNextBitmap
=
bitmap
;
}
/************************************abstract****************************************/
//开启翻页动画
public
abstract
void
startAnim
();
public
Bitmap
getmCurBitmap
()
{
return
mCurBitmap
;
}
//获取下页的bitmap
public
Bitmap
getmNextBitmap
()
{
return
mNextBitmap
;
}
public
void
setmCurBitmap
(
Bitmap
mCurBitmap
)
{
this
.
mCurBitmap
=
mCurBitmap
;
}
public
void
setmNextBitmap
(
Bitmap
mNextBitmap
)
{
this
.
mNextBitmap
=
mNextBitmap
;
}
//处理触摸事件
public
abstract
boolean
onTouchEvent
(
MotionEvent
event
);
//计算滚动
public
abstract
void
scrollAnim
();
//绘制翻页动画
public
abstract
void
drawMove
(
Canvas
canvas
);
/************************************interface****************************************/
//监听界面变化 PageView实现
public
interface
OnPageChangeListener
{
boolean
hasPrev
();
boolean
hasNext
();
void
pageCancel
();
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/anim/Rotate3DAnimation.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
anim
;
import
android.content.Context
;
import
android.graphics.Camera
;
import
android.graphics.Matrix
;
import
android.util.Log
;
import
android.view.animation.Animation
;
import
android.view.animation.Transformation
;
public
class
Rotate3DAnimation
extends
Animation
{
private
static
final
String
TAG
=
"Rotate3DAnimation"
;
private
final
float
mFromDegrees
;
private
final
float
mToDegrees
;
private
final
float
mMarginLeft
;
private
final
float
mMarginTop
;
// private final float mDepthZ;
private
final
float
mAnimationScale
;
private
boolean
reverse
;
private
Camera
mCamera
;
// 旋转中心
private
float
mPivotX
;
private
float
mPivotY
;
private
float
scale
=
1
;
// <------- 像素密度
public
Rotate3DAnimation
(
Context
context
,
float
mFromDegrees
,
float
mToDegrees
,
float
mMarginLeft
,
float
mMarginTop
,
float
animationScale
,
boolean
reverse
)
{
this
.
mFromDegrees
=
mFromDegrees
;
this
.
mToDegrees
=
mToDegrees
;
this
.
mMarginLeft
=
mMarginLeft
;
this
.
mMarginTop
=
mMarginTop
;
this
.
mAnimationScale
=
animationScale
;
this
.
reverse
=
reverse
;
// 获取手机像素密度 (即dp与px的比例)
scale
=
context
.
getResources
().
getDisplayMetrics
().
density
;
}
@Override
public
void
initialize
(
int
width
,
int
height
,
int
parentWidth
,
int
parentHeight
)
{
super
.
initialize
(
width
,
height
,
parentWidth
,
parentHeight
);
mCamera
=
new
Camera
();
mPivotX
=
calculatePivotX
(
mMarginLeft
,
parentWidth
,
width
);
mPivotY
=
calculatePivotY
(
mMarginTop
,
parentHeight
,
height
);
Log
.
i
(
TAG
,
"width:"
+
width
+
",height:"
+
height
+
",pw:"
+
parentWidth
+
",ph:"
+
parentHeight
);
Log
.
i
(
TAG
,
"中心点x:"
+
mPivotX
+
",中心点y:"
+
mPivotY
);
}
@Override
protected
void
applyTransformation
(
float
interpolatedTime
,
Transformation
t
)
{
super
.
applyTransformation
(
interpolatedTime
,
t
);
float
degrees
=
reverse
?
mToDegrees
+
(
mFromDegrees
-
mToDegrees
)
*
interpolatedTime
:
mFromDegrees
+
(
mToDegrees
-
mFromDegrees
)
*
interpolatedTime
;
Matrix
matrix
=
t
.
getMatrix
();
Camera
camera
=
mCamera
;
camera
.
save
();
camera
.
rotateY
(
degrees
);
camera
.
getMatrix
(
matrix
);
camera
.
restore
();
// 修正失真,主要修改 MPERSP_0 和 MPERSP_1
float
[]
mValues
=
new
float
[
9
];
matrix
.
getValues
(
mValues
);
//获取数值
mValues
[
6
]
=
mValues
[
6
]
/
scale
;
//数值修正
mValues
[
7
]
=
mValues
[
7
]
/
scale
;
//数值修正
matrix
.
setValues
(
mValues
);
//重新赋值
if
(
reverse
)
{
matrix
.
postScale
(
1
+
(
mAnimationScale
-
1
)
*
interpolatedTime
,
1
+
(
mAnimationScale
-
1
)
*
interpolatedTime
,
mPivotX
-
mMarginLeft
,
mPivotY
-
mMarginTop
);
}
else
{
matrix
.
postScale
(
1
+
(
mAnimationScale
-
1
)
*
(
1
-
interpolatedTime
),
1
+
(
mAnimationScale
-
1
)
*
(
1
-
interpolatedTime
),
mPivotX
-
mMarginLeft
,
mPivotY
-
mMarginTop
);
}
}
/**
* 计算缩放的中心点的横坐标
*
* @param marginLeft 该View距离父布局左边的距离
* @param parentWidth 父布局的宽度
* @param width View的宽度
* @return 缩放中心点的横坐标
*/
public
float
calculatePivotX
(
float
marginLeft
,
float
parentWidth
,
float
width
)
{
return
parentWidth
*
marginLeft
/
(
parentWidth
-
width
);
}
/**
* 计算缩放的中心点的纵坐标
*
* @param marginTop 该View顶部距离父布局顶部的距离
* @param parentHeight 父布局的高度
* @param height 子布局的高度
* @return 缩放的中心点的纵坐标
*/
public
float
calculatePivotY
(
float
marginTop
,
float
parentHeight
,
float
height
)
{
return
parentHeight
*
marginTop
/
(
parentHeight
-
height
);
}
public
void
reverse
()
{
reverse
=
!
reverse
;
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/anim/SlideAnim.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
anim
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.view.MotionEvent
;
import
android.view.View
;
import
com.mints.enjoyboxjia.read.Direction
;
public
class
SlideAnim
extends
PageAnim
{
public
SlideAnim
(
View
view
,
PageAnim
.
OnPageChangeListener
mListener
){
super
(
view
,
mListener
);
}
public
void
startAnim
(){
int
dx
=
0
;
switch
(
mDirection
){
case
NEXT:
if
(
isCancel
){
int
dis
=
(
int
)
((
mViewWidth
-
mStartX
)
+
mTouchX
);
if
(
dis
>
mViewWidth
){
dis
=
mViewWidth
;
}
dx
=
mViewWidth
-
dis
;
}
else
{
dx
=
(
int
)
-(
mTouchX
+
(
mViewWidth
-
mStartX
));
}
break
;
default
:
if
(
isCancel
){
dx
=
(
int
)
-
mTouchX
;
}
else
{
dx
=
(
int
)
(
mViewWidth
-
mTouchX
);
}
break
;
}
//滑动速度保持一致
int
duration
=
(
800
*
Math
.
abs
(
dx
))
/
mViewWidth
;
mScroller
.
startScroll
((
int
)
mTouchX
,
0
,
dx
,
0
,
duration
);
}
public
Bitmap
getmCurBitmap
()
{
return
mCurBitmap
;
}
public
Bitmap
getmNextBitmap
()
{
return
mNextBitmap
;
}
public
boolean
onTouchEvent
(
MotionEvent
event
){
//点击位置
int
x
=
(
int
)
event
.
getX
();
int
y
=
(
int
)
event
.
getY
();
//更新滑动坐标
mLastX
=
mTouchX
;
mLastY
=
mTouchY
;
mTouchX
=
x
;
mTouchY
=
y
;
switch
(
event
.
getAction
())
{
case
MotionEvent
.
ACTION_DOWN
:
mStartX
=
x
;
mStartY
=
y
;
//移动的点击位置
mLastX
=
0
;
mLastY
=
0
;
//未开始动画
isAnim
=
false
;
//取消
isCancel
=
false
;
break
;
case
MotionEvent
.
ACTION_MOVE
:
//判断是否移动了
if
(!
isMove
)
{
isMove
=
Math
.
abs
(
mStartX
-
x
)
>
slop
||
Math
.
abs
(
mStartY
-
y
)
>
slop
;
}
//处理滑动
if
(
isMove
)
{
//还未开始滑动
if
(
mLastX
==
mStartX
)
{
//判断方向
if
(
x
-
mStartX
>
0
)
{
mDirection
=
Direction
.
PRE
;
//如果一页不存在
if
(!
mListener
.
hasPrev
())
{
noNext
=
true
;
return
true
;
}
}
else
{
mDirection
=
Direction
.
NEXT
;
//如果一页不存在
if
(!
mListener
.
hasNext
())
{
noNext
=
true
;
return
true
;
}
}
}
//已经开始滑动
else
{
//判断是否需要取消翻页
//即滑动位置到了与初始滑动方向相反时
if
(
mDirection
==
Direction
.
NEXT
)
{
if
(
x
-
mLastX
>
0
)
{
isCancel
=
true
;
}
else
{
isCancel
=
false
;
}
}
else
{
if
(
x
-
mLastX
<
0
)
{
isCancel
=
true
;
}
else
{
isCancel
=
false
;
}
}
}
mLastX
=
x
;
mLastY
=
y
;
isAnim
=
true
;
mView
.
invalidate
();
}
break
;
case
MotionEvent
.
ACTION_UP
:
if
(!
isMove
)
{
if
(
x
<
mViewWidth
/
2
)
{
mDirection
=
Direction
.
PRE
;
}
else
{
mDirection
=
Direction
.
NEXT
;
}
if
(
mDirection
==
Direction
.
NEXT
)
{
//判断是否下一页存在
boolean
hasNext
=
mListener
.
hasNext
();
if
(!
hasNext
)
{
return
true
;
}
}
else
{
boolean
hasPrev
=
mListener
.
hasPrev
();
if
(!
hasPrev
)
{
return
true
;
}
}
}
// 是否取消翻页
if
(
isCancel
){
mListener
.
pageCancel
();
}
// 开启翻页效果
if
(!
noNext
)
{
startAnim
();
mView
.
invalidate
();
}
break
;
}
return
true
;
}
public
void
scrollAnim
()
{
if
(
mScroller
.
computeScrollOffset
())
{
int
x
=
mScroller
.
getCurrX
();
int
y
=
mScroller
.
getCurrY
();
mLastX
=
mTouchX
;
mLastY
=
mTouchY
;
mTouchX
=
x
;
mTouchY
=
y
;
if
(
mScroller
.
getFinalX
()
==
x
&&
mScroller
.
getFinalY
()
==
y
){
isAnim
=
false
;
}
mView
.
postInvalidate
();
}
}
//绘制翻页动画
public
void
drawMove
(
Canvas
canvas
)
{
switch
(
mDirection
){
case
NEXT:
int
dis
=
(
int
)
(
mViewWidth
-
mStartX
+
mTouchX
);
if
(
dis
>
mViewWidth
){
dis
=
mViewWidth
;
}
//计算bitmap截取的区域
mSrcRect
.
left
=
mViewWidth
-
dis
;
//计算bitmap在canvas显示的区域
mDestRect
.
right
=
dis
;
canvas
.
drawBitmap
(
mNextBitmap
,
0
,
0
,
null
);
canvas
.
drawBitmap
(
mCurBitmap
,
mSrcRect
,
mDestRect
,
null
);
break
;
default
:
mSrcRect
.
left
=
(
int
)
(
mViewWidth
-
mTouchX
);
mDestRect
.
right
=
(
int
)
mTouchX
;
canvas
.
drawBitmap
(
mCurBitmap
,
0
,
0
,
null
);
canvas
.
drawBitmap
(
mNextBitmap
,
mSrcRect
,
mDestRect
,
null
);
break
;
}
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/models/BookModel.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
models
;
import
android.os.Build
;
import
android.os.Parcel
;
import
android.os.Parcelable
;
import
androidx.annotation.RequiresApi
;
import
org.litepal.crud.LitePalSupport
;
/**
* 书籍的模型
*/
public
class
BookModel
extends
LitePalSupport
implements
Parcelable
{
//LitePal自动生成id
private
Long
id
=
0
l
;
private
String
bookId
;
private
String
bookTitle
;
private
String
coverResource
;
private
String
record
;
private
String
filePath
;
public
BookModel
(
String
bookTitle
,
String
coverResource
,
String
record
,
String
filePath
)
{
this
.
bookTitle
=
bookTitle
;
this
.
coverResource
=
coverResource
;
this
.
record
=
record
;
this
.
filePath
=
filePath
;
}
public
BookModel
()
{
}
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
Q
)
protected
BookModel
(
Parcel
in
)
{
id
=
in
.
readLong
();
bookId
=
in
.
readString
();
bookTitle
=
in
.
readString
();
coverResource
=
in
.
readString
();
record
=
in
.
readString
();
filePath
=
in
.
readString
();
}
public
static
final
Creator
<
BookModel
>
CREATOR
=
new
Creator
<
BookModel
>()
{
@RequiresApi
(
api
=
Build
.
VERSION_CODES
.
Q
)
@Override
public
BookModel
createFromParcel
(
Parcel
in
)
{
BookModel
model
=
new
BookModel
();
model
.
id
=
in
.
readLong
();
model
.
bookId
=
in
.
readString
();
model
.
bookTitle
=
in
.
readString
();
model
.
coverResource
=
in
.
readString
();
model
.
record
=
in
.
readString
();
model
.
filePath
=
in
.
readString
();
return
model
;
}
@Override
public
BookModel
[]
newArray
(
int
size
)
{
return
new
BookModel
[
size
];
}
};
public
long
getId
()
{
return
id
;
}
public
void
setId
(
long
id
)
{
this
.
id
=
id
;
}
public
String
getBookId
()
{
return
bookId
;
}
public
void
setBookId
(
String
bookId
)
{
this
.
bookId
=
bookId
;
}
public
String
getBookTitle
()
{
return
bookTitle
;
}
public
void
setBookTitle
(
String
bookTitle
)
{
this
.
bookTitle
=
bookTitle
;
}
public
String
getCoverResource
()
{
return
coverResource
;
}
public
void
setCoverResource
(
String
coverResource
)
{
this
.
coverResource
=
coverResource
;
}
public
String
getRecord
()
{
return
record
;
}
public
void
setRecord
(
String
record
)
{
this
.
record
=
record
;
}
public
String
getFilePath
()
{
return
filePath
;
}
public
void
setFilePath
(
String
filePath
)
{
this
.
filePath
=
filePath
;
}
@Override
public
int
describeContents
()
{
return
0
;
}
@Override
public
void
writeToParcel
(
Parcel
dest
,
int
flags
)
{
dest
.
writeLong
(
id
);
dest
.
writeString
(
bookId
);
dest
.
writeString
(
bookTitle
);
dest
.
writeString
(
coverResource
);
dest
.
writeString
(
record
);
dest
.
writeString
(
filePath
);
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/models/BookRecordModel.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
models
;
import
org.litepal.crud.LitePalSupport
;
public
class
BookRecordModel
extends
LitePalSupport
{
private
String
book_id
;
private
int
chapterPos
;
private
int
pagePos
;
private
int
text_color
;
private
int
page_color
;
private
int
text_size
;
private
int
anim_type
;
public
String
getBook_id
()
{
return
book_id
;
}
public
void
setBook_id
(
String
book_id
)
{
this
.
book_id
=
book_id
;
}
public
int
getChapterPos
()
{
return
chapterPos
;
}
public
void
setChapterPos
(
int
chapterPos
)
{
this
.
chapterPos
=
chapterPos
;
}
public
int
getPagePos
()
{
return
pagePos
;
}
public
void
setPagePos
(
int
pagePos
)
{
this
.
pagePos
=
pagePos
;
}
public
int
getText_color
()
{
return
text_color
;
}
public
void
setText_color
(
int
text_color
)
{
this
.
text_color
=
text_color
;
}
public
int
getPage_color
()
{
return
page_color
;
}
public
void
setPage_color
(
int
page_color
)
{
this
.
page_color
=
page_color
;
}
public
int
getText_size
()
{
return
text_size
;
}
public
void
setText_size
(
int
text_size
)
{
this
.
text_size
=
text_size
;
}
public
int
getAnim_type
()
{
return
anim_type
;
}
public
void
setAnim_type
(
int
anim_type
)
{
this
.
anim_type
=
anim_type
;
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/models/ChapterInfoBean.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
models
;
import
com.google.gson.annotations.SerializedName
;
import
io.reactivex.SingleObserver
;
public
class
ChapterInfoBean
{
private
String
title
;
@SerializedName
(
"content"
)
private
String
body
;
public
String
getTitle
()
{
return
title
;
}
public
void
setTitle
(
String
title
)
{
this
.
title
=
title
;
}
public
String
getBody
()
{
return
body
;
}
public
void
setBody
(
String
body
)
{
this
.
body
=
body
;
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/models/TxtChapterModel.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
models
;
import
com.google.gson.annotations.SerializedName
;
import
org.litepal.crud.LitePalSupport
;
import
java.util.Date
;
/**
* 小说的章节
* */
public
class
TxtChapterModel
extends
LitePalSupport
{
@SerializedName
(
"Local_id"
)
long
id
;
//chapterId
@SerializedName
(
"id"
)
private
String
chapterId
;
//章节名
@SerializedName
(
"indexName"
)
public
String
title
;
//章节链接
String
link
;
//章节的起始和结束位置
public
long
start
;
public
long
end
;
//书籍id
private
long
book_id
;
private
Integer
indexNum
;
private
Integer
wordCount
;
private
Byte
isVip
;
private
Integer
bookPrice
;
private
String
storageType
;
private
Date
createTime
;
private
Date
updateTime
;
public
TxtChapterModel
()
{
}
public
long
getId
()
{
return
id
;
}
public
void
setId
(
long
id
)
{
this
.
id
=
id
;
}
public
String
getChapterId
()
{
return
chapterId
;
}
public
void
setChapterId
(
String
chapterId
)
{
this
.
chapterId
=
chapterId
;
}
public
TxtChapterModel
(
long
book_id
)
{
this
.
book_id
=
book_id
;
}
public
TxtChapterModel
(
String
title
)
{
this
.
title
=
title
;
}
public
String
getTitle
()
{
return
title
;
}
public
void
setTitle
(
String
title
)
{
this
.
title
=
title
;
}
public
String
getLink
()
{
return
link
;
}
public
void
setLink
(
String
link
)
{
this
.
link
=
link
;
}
public
long
getStart
()
{
return
start
;
}
public
void
setStart
(
int
start
)
{
this
.
start
=
start
;
}
public
long
getEnd
()
{
return
end
;
}
public
void
setEnd
(
int
end
)
{
this
.
end
=
end
;
}
public
long
getBook_id
()
{
return
book_id
;
}
public
void
setBook_id
(
long
book_id
)
{
this
.
book_id
=
book_id
;
}
public
Integer
getIndexNum
()
{
return
indexNum
;
}
public
void
setIndexNum
(
Integer
indexNum
)
{
this
.
indexNum
=
indexNum
;
}
public
Integer
getWordCount
()
{
return
wordCount
;
}
public
void
setWordCount
(
Integer
wordCount
)
{
this
.
wordCount
=
wordCount
;
}
public
Byte
getIsVip
()
{
return
isVip
;
}
public
void
setIsVip
(
Byte
isVip
)
{
this
.
isVip
=
isVip
;
}
public
Integer
getBookPrice
()
{
return
bookPrice
;
}
public
void
setBookPrice
(
Integer
bookPrice
)
{
this
.
bookPrice
=
bookPrice
;
}
public
String
getStorageType
()
{
return
storageType
;
}
public
void
setStorageType
(
String
storageType
)
{
this
.
storageType
=
storageType
==
null
?
null
:
storageType
.
trim
();
}
public
Date
getCreateTime
()
{
return
createTime
;
}
public
void
setCreateTime
(
Date
createTime
)
{
this
.
createTime
=
createTime
;
}
public
Date
getUpdateTime
()
{
return
updateTime
;
}
public
void
setUpdateTime
(
Date
updateTime
)
{
this
.
updateTime
=
updateTime
;
}
}
book/app/src/main/java/com/mints/enjoyboxjia/read/models/TxtPageModel.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
read
.
models
;
import
java.util.List
;
/**
* 小说显示的页面
* */
public
class
TxtPageModel
{
public
int
position
;
public
String
title
;
public
int
titleLines
;
public
List
<
String
>
lines
;
}
book/app/src/main/java/com/mints/enjoyboxjia/ui/activitys/BookReadActivity.kt
View file @
b6ce8584
...
@@ -6,6 +6,7 @@ import androidx.core.content.ContextCompat
...
@@ -6,6 +6,7 @@ import androidx.core.content.ContextCompat
import
com.mints.enjoyboxjia.R
import
com.mints.enjoyboxjia.R
import
com.mints.enjoyboxjia.common.BOOK_CONTENT_COLOR
import
com.mints.enjoyboxjia.common.BOOK_CONTENT_COLOR
import
com.mints.enjoyboxjia.common.BOOK_CONTENT_SIZE
import
com.mints.enjoyboxjia.common.BOOK_CONTENT_SIZE
import
com.mints.enjoyboxjia.common.Constant
import
com.mints.enjoyboxjia.manager.ReadTimeCount
import
com.mints.enjoyboxjia.manager.ReadTimeCount
import
com.mints.enjoyboxjia.mvp.model.BookContentBean
import
com.mints.enjoyboxjia.mvp.model.BookContentBean
import
com.mints.enjoyboxjia.mvp.presenters.BookReadPresenter
import
com.mints.enjoyboxjia.mvp.presenters.BookReadPresenter
...
@@ -21,10 +22,6 @@ import net.nightwhistler.htmlspanner.HtmlSpanner
...
@@ -21,10 +22,6 @@ import net.nightwhistler.htmlspanner.HtmlSpanner
class
BookReadActivity
:
BaseActivity
(),
View
.
OnClickListener
,
BookReadView
{
class
BookReadActivity
:
BaseActivity
(),
View
.
OnClickListener
,
BookReadView
{
companion
object
{
const
val
BOOK_ID
=
"BOOK_ID"
}
private
var
bookId
=
""
private
var
bookId
=
""
private
var
isCollect
=
false
private
var
isCollect
=
false
private
val
readPresenter
by
lazy
{
BookReadPresenter
()
}
private
val
readPresenter
by
lazy
{
BookReadPresenter
()
}
...
@@ -38,7 +35,7 @@ class BookReadActivity : BaseActivity(), View.OnClickListener, BookReadView {
...
@@ -38,7 +35,7 @@ class BookReadActivity : BaseActivity(), View.OnClickListener, BookReadView {
override
fun
getBundleExtras
(
extras
:
Bundle
?)
{
override
fun
getBundleExtras
(
extras
:
Bundle
?)
{
super
.
getBundleExtras
(
extras
)
super
.
getBundleExtras
(
extras
)
extras
?.
let
{
extras
?.
let
{
bookId
=
extras
.
getString
(
BOOK_ID
).
toString
()
bookId
=
extras
.
getString
(
Constant
.
ROUTE_
BOOK_ID
).
toString
()
}
}
}
}
...
...
book/app/src/main/java/com/mints/enjoyboxjia/ui/activitys/BookSearchActivity.kt
View file @
b6ce8584
...
@@ -80,7 +80,7 @@ class BookSearchActivity : BaseActivity(), View.OnClickListener, BookSearchView,
...
@@ -80,7 +80,7 @@ class BookSearchActivity : BaseActivity(), View.OnClickListener, BookSearchView,
searchHotBookAdapter
=
SearchHotBookAdapter
(
this
)
searchHotBookAdapter
=
SearchHotBookAdapter
(
this
)
searchHotBookAdapter
?.
setOnItemClickListener
{
_
,
_
,
position
->
searchHotBookAdapter
?.
setOnItemClickListener
{
_
,
_
,
position
->
val
bundle
=
Bundle
()
val
bundle
=
Bundle
()
bundle
.
putString
(
BookReadActivity
.
BOOK_ID
,
searchHotBookData
[
position
].
id
)
bundle
.
putString
(
Constant
.
ROUTE_
BOOK_ID
,
searchHotBookData
[
position
].
id
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
}
}
rv_hot
.
layoutManager
=
LinearLayoutManager
(
this
)
rv_hot
.
layoutManager
=
LinearLayoutManager
(
this
)
...
@@ -91,7 +91,7 @@ class BookSearchActivity : BaseActivity(), View.OnClickListener, BookSearchView,
...
@@ -91,7 +91,7 @@ class BookSearchActivity : BaseActivity(), View.OnClickListener, BookSearchView,
searchBookAdapter
=
SearchBookAdapter
(
this
)
searchBookAdapter
=
SearchBookAdapter
(
this
)
searchBookAdapter
?.
setOnItemClickListener
{
_
,
_
,
position
->
searchBookAdapter
?.
setOnItemClickListener
{
_
,
_
,
position
->
val
bundle
=
Bundle
()
val
bundle
=
Bundle
()
bundle
.
putString
(
BookReadActivity
.
BOOK_ID
,
searchBookData
[
position
].
id
)
bundle
.
putString
(
Constant
.
ROUTE_
BOOK_ID
,
searchBookData
[
position
].
id
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
}
}
rv_search_show
.
layoutManager
=
LinearLayoutManager
(
this
)
rv_search_show
.
layoutManager
=
LinearLayoutManager
(
this
)
...
@@ -240,4 +240,9 @@ class BookSearchActivity : BaseActivity(), View.OnClickListener, BookSearchView,
...
@@ -240,4 +240,9 @@ class BookSearchActivity : BaseActivity(), View.OnClickListener, BookSearchView,
++
searchPage
++
searchPage
searchBook
(
et_search
.
text
.
toString
())
searchBook
(
et_search
.
text
.
toString
())
}
}
override
fun
onDestroy
()
{
super
.
onDestroy
()
searchPresenter
.
detachView
()
}
}
}
book/app/src/main/java/com/mints/enjoyboxjia/ui/activitys/LongBookReadActivity.kt
0 → 100644
View file @
b6ce8584
package
com.mints.enjoyboxjia.ui.activitys
import
android.os.Bundle
import
android.os.Handler
import
android.os.Looper
import
android.view.View
import
com.mints.enjoyboxjia.R
import
com.mints.enjoyboxjia.common.BOOK_CONTENT_COLOR
import
com.mints.enjoyboxjia.common.BOOK_CONTENT_SIZE
import
com.mints.enjoyboxjia.common.Constant
import
com.mints.enjoyboxjia.manager.ReadTimeCount
import
com.mints.enjoyboxjia.mvp.model.BookContentBean
import
com.mints.enjoyboxjia.mvp.presenters.BookReadPresenter
import
com.mints.enjoyboxjia.mvp.views.BookReadView
import
com.mints.enjoyboxjia.read.AnimType
import
com.mints.enjoyboxjia.read.PageLoader
import
com.mints.enjoyboxjia.read.models.BookModel
import
com.mints.enjoyboxjia.read.models.BookRecordModel
import
com.mints.enjoyboxjia.read.models.TxtChapterModel
import
com.mints.enjoyboxjia.ui.activitys.base.BaseActivity
import
com.mints.enjoyboxjia.ui.widgets.BookSettingDialog
import
com.mints.enjoyboxjia.utils.AppPreferencesManager
import
com.mints.enjoyboxjia.utils.LogUtil
import
kotlinx.android.synthetic.main.activity_long_book_read.*
import
kotlinx.android.synthetic.main.header_layout.*
import
org.litepal.LitePal
class
LongBookReadActivity
:
BaseActivity
(),
View
.
OnClickListener
,
BookReadView
{
private
val
readPresenter
by
lazy
{
BookReadPresenter
()
}
private
var
mBookModel
:
BookModel
?
=
null
private
var
mPageLoader
:
PageLoader
?
=
null
private
var
bookSettingDialog
:
BookSettingDialog
?
=
null
override
fun
getContentViewLayoutID
()
=
R
.
layout
.
activity_long_book_read
override
fun
isApplyKitKatTranslucency
()
=
false
override
fun
getBundleExtras
(
extras
:
Bundle
?)
{
super
.
getBundleExtras
(
extras
)
extras
?.
let
{
mBookModel
=
BookModel
()
mBookModel
?.
bookId
=
extras
.
getString
(
Constant
.
ROUTE_BOOK_ID
).
toString
()
}
}
override
fun
initViewsAndEvents
()
{
iv_left_icon
.
visibility
=
View
.
VISIBLE
iv_left_icon
.
setImageResource
(
R
.
mipmap
.
ic_arrow_back
)
readPresenter
.
attachView
(
this
)
initWidgets
()
initListener
()
popBookSettingDialog
()
}
override
fun
onResume
()
{
super
.
onResume
()
ReadTimeCount
.
instance
.
startCountReadTime
()
}
override
fun
onPause
()
{
super
.
onPause
()
ReadTimeCount
.
instance
.
endCountReadTime
()
}
override
fun
onClick
(
v
:
View
?)
{
when
(
v
?.
id
)
{
R
.
id
.
iv_left_icon
->
finish
()
R
.
id
.
tab_setting_chapter
->
{
}
R
.
id
.
tab_setting_book
->
{
bookSettingDialog
?.
show
()
}
R
.
id
.
tab_setting_share
->
{}
R
.
id
.
btn_submit
->
{
val
bundle
=
Bundle
()
bundle
.
putBoolean
(
VipActivity
.
IS_RECOMMEND
,
true
)
readyGo
(
VipActivity
::
class
.
java
,
bundle
)
}
}
}
private
fun
popBookSettingDialog
()
{
bookSettingDialog
=
BookSettingDialog
(
this
)
bookSettingDialog
?.
setOnBookSettingCallback
(
object
:
BookSettingDialog
.
OnBookSettingCallback
{
override
fun
onFontSize
(
size
:
Int
)
{
// tv_content.textSize = size.toFloat()
AppPreferencesManager
.
get
().
put
(
BOOK_CONTENT_SIZE
,
size
)
}
override
fun
onBgColor
(
color
:
Int
)
{
// pageview.setBackgroundColor(color)
AppPreferencesManager
.
get
().
put
(
BOOK_CONTENT_COLOR
,
color
)
}
})
bookSettingDialog
?.
loadSetting
()
}
private
fun
initWidgets
()
{
//书籍
mPageLoader
=
pageview
.
getPageLoader
(
mBookModel
)
pageview
.
animType
=
AnimType
.
ALIKE
//从数据库加载分章信息
mPageLoader
?.
mChapterList
=
LitePal
.
where
(
"book_id=?"
,
""
+
mBookModel
?.
id
)
.
find
(
TxtChapterModel
::
class
.
java
)
//获取上次的数据
val
recordModel
:
BookRecordModel
?
=
LitePal
.
where
(
"book_id=?"
,
""
+
mBookModel
?.
id
)
.
findFirst
(
BookRecordModel
::
class
.
java
)
if
(
recordModel
!=
null
)
{
mPageLoader
?.
run
{
curChapterIndex
=
recordModel
.
chapterPos
curPageIndex
=
recordModel
.
pagePos
setTextSize
(
recordModel
.
text_size
)
textColor
=
recordModel
.
text_color
setPageBgColor
(
recordModel
.
page_color
)
when
(
recordModel
.
anim_type
)
{
1
->
pageview
.
animType
=
AnimType
.
SLIDE
2
->
pageview
.
animType
=
AnimType
.
COVER
3
->
pageview
.
animType
=
AnimType
.
ALIKE
else
->
pageview
.
animType
=
AnimType
.
NONE
}
}
}
//章节回调
mPageLoader
?.
setChapterChangeListener
(
object
:
PageLoader
.
OnChapterChangeListener
{
override
fun
onChapterChange
(
pos
:
Int
)
{
LogUtil
.
d
(
"XXXIX ----> $pos"
)
// if (pos >= mPageLoader.){
//
// }
// readChaptersAdapter.setChapter(pos)
}
override
fun
requestChapters
(
requestChapters
:
List
<
TxtChapterModel
>)
{}
override
fun
finishedLoadChapters
(
bookChapters
:
List
<
TxtChapterModel
>)
{
mPageLoader
?.
pageView
?.
showCategory
()
// readChaptersAdapter.setChapterModels(bookChapters)
}
})
//初始化目录
// initChapterRecyclerView()
}
private
fun
initListener
()
{
iv_left_icon
.
setOnClickListener
(
this
)
tab_setting_chapter
.
setOnClickListener
(
this
)
tab_setting_share
.
setOnClickListener
(
this
)
tab_setting_book
.
setOnClickListener
(
this
)
btn_submit
.
setOnClickListener
(
this
)
}
override
fun
getBookDetailSuc
(
data
:
BookContentBean
)
{
}
override
fun
getBookDetailFail
()
{
}
override
fun
onDestroy
()
{
super
.
onDestroy
()
readPresenter
.
detachView
()
}
}
book/app/src/main/java/com/mints/enjoyboxjia/ui/activitys/MainActivity.kt
View file @
b6ce8584
...
@@ -12,10 +12,11 @@ import com.mints.enjoyboxjia.common.AppConfig
...
@@ -12,10 +12,11 @@ import com.mints.enjoyboxjia.common.AppConfig
import
com.mints.enjoyboxjia.common.Constant
import
com.mints.enjoyboxjia.common.Constant
import
com.mints.enjoyboxjia.ui.activitys.base.BaseActivity
import
com.mints.enjoyboxjia.ui.activitys.base.BaseActivity
import
com.mints.enjoyboxjia.ui.fragment.BookCityFragment
import
com.mints.enjoyboxjia.ui.fragment.BookCityFragment
import
com.mints.enjoyboxjia.ui.fragment.CountFragment
import
com.mints.enjoyboxjia.ui.fragment.BookShelfFragment
import
com.mints.enjoyboxjia.ui.fragment.BookShelfFragment
import
com.mints.enjoyboxjia.ui.fragment.CountFragment
import
com.mints.enjoyboxjia.ui.fragment.MyFragment
import
com.mints.enjoyboxjia.ui.fragment.MyFragment
import
kotlinx.android.synthetic.main.activity_main.*
import
kotlinx.android.synthetic.main.activity_main.*
import
org.litepal.LitePal
/**
/**
* 描述:首页
* 描述:首页
...
@@ -40,6 +41,9 @@ class MainActivity : BaseActivity(), View.OnClickListener {
...
@@ -40,6 +41,9 @@ class MainActivity : BaseActivity(), View.OnClickListener {
override
fun
initViewsAndEvents
()
{
override
fun
initViewsAndEvents
()
{
audioManager
=
getSystemService
(
Context
.
AUDIO_SERVICE
)
as
AudioManager
audioManager
=
getSystemService
(
Context
.
AUDIO_SERVICE
)
as
AudioManager
//数据库 LitePal
LitePal
.
initialize
(
this
)
AppConfig
.
fragmentClickFlag
=
Constant
.
FRAGMENT_CLICK_TWO
AppConfig
.
fragmentClickFlag
=
Constant
.
FRAGMENT_CLICK_TWO
if
(
bookCityFragment
==
null
)
{
if
(
bookCityFragment
==
null
)
{
bookCityFragment
=
BookCityFragment
()
bookCityFragment
=
BookCityFragment
()
...
...
book/app/src/main/java/com/mints/enjoyboxjia/ui/activitys/WatchRecordActivity.kt
View file @
b6ce8584
...
@@ -5,6 +5,7 @@ import android.view.LayoutInflater
...
@@ -5,6 +5,7 @@ import android.view.LayoutInflater
import
android.view.View
import
android.view.View
import
androidx.recyclerview.widget.LinearLayoutManager
import
androidx.recyclerview.widget.LinearLayoutManager
import
com.mints.enjoyboxjia.R
import
com.mints.enjoyboxjia.R
import
com.mints.enjoyboxjia.common.Constant
import
com.mints.enjoyboxjia.mvp.model.*
import
com.mints.enjoyboxjia.mvp.model.*
import
com.mints.enjoyboxjia.mvp.presenters.WatchRecordPresenter
import
com.mints.enjoyboxjia.mvp.presenters.WatchRecordPresenter
import
com.mints.enjoyboxjia.mvp.views.WatchRecordView
import
com.mints.enjoyboxjia.mvp.views.WatchRecordView
...
@@ -38,7 +39,7 @@ class WatchRecordActivity : BaseActivity(), WatchRecordView {
...
@@ -38,7 +39,7 @@ class WatchRecordActivity : BaseActivity(), WatchRecordView {
mWatchRecordAdapter
?.
setNewInstance
(
datas
)
mWatchRecordAdapter
?.
setNewInstance
(
datas
)
mWatchRecordAdapter
?.
setOnItemClickListener
{
adapter
,
view
,
position
->
mWatchRecordAdapter
?.
setOnItemClickListener
{
adapter
,
view
,
position
->
val
bundle
=
Bundle
()
val
bundle
=
Bundle
()
bundle
.
putString
(
BookReadActivity
.
BOOK_ID
,
datas
.
get
(
position
).
id
)
bundle
.
putString
(
Constant
.
ROUTE_
BOOK_ID
,
datas
.
get
(
position
).
id
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
}
}
mWatchRecordAdapter
?.
setOnItemCollectClickListener
(
object
:
mWatchRecordAdapter
?.
setOnItemCollectClickListener
(
object
:
...
...
book/app/src/main/java/com/mints/enjoyboxjia/ui/fragment/BookCityFragment.kt
View file @
b6ce8584
...
@@ -72,7 +72,7 @@ class BookCityFragment : LazyLoadBaseFragment(), BookCityView, View.OnClickListe
...
@@ -72,7 +72,7 @@ class BookCityFragment : LazyLoadBaseFragment(), BookCityView, View.OnClickListe
hotBookAdapter
=
HotBookAdapter
(
requireActivity
())
hotBookAdapter
=
HotBookAdapter
(
requireActivity
())
hotBookAdapter
?.
setOnItemClickListener
{
_
,
_
,
position
->
hotBookAdapter
?.
setOnItemClickListener
{
_
,
_
,
position
->
val
bundle
=
Bundle
()
val
bundle
=
Bundle
()
bundle
.
putString
(
BookReadActivity
.
BOOK_ID
,
hotBookData
[
position
].
id
)
bundle
.
putString
(
Constant
.
ROUTE_
BOOK_ID
,
hotBookData
[
position
].
id
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
}
}
rv_hotbook
.
layoutManager
=
GridLayoutManager
(
requireContext
(),
4
)
rv_hotbook
.
layoutManager
=
GridLayoutManager
(
requireContext
(),
4
)
...
@@ -104,7 +104,7 @@ class BookCityFragment : LazyLoadBaseFragment(), BookCityView, View.OnClickListe
...
@@ -104,7 +104,7 @@ class BookCityFragment : LazyLoadBaseFragment(), BookCityView, View.OnClickListe
}
}
view
.
setOnClickListener
{
view
.
setOnClickListener
{
val
bundle
=
Bundle
()
val
bundle
=
Bundle
()
bundle
.
putString
(
BookReadActivity
.
BOOK_ID
,
headData
.
id
)
bundle
.
putString
(
Constant
.
ROUTE_
BOOK_ID
,
headData
.
id
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
}
}
return
view
return
view
...
@@ -114,7 +114,7 @@ class BookCityFragment : LazyLoadBaseFragment(), BookCityView, View.OnClickListe
...
@@ -114,7 +114,7 @@ class BookCityFragment : LazyLoadBaseFragment(), BookCityView, View.OnClickListe
newBookAdapter
=
NewBookAdapter
(
requireActivity
())
newBookAdapter
=
NewBookAdapter
(
requireActivity
())
newBookAdapter
?.
setOnItemClickListener
{
_
,
_
,
position
->
newBookAdapter
?.
setOnItemClickListener
{
_
,
_
,
position
->
val
bundle
=
Bundle
()
val
bundle
=
Bundle
()
bundle
.
putString
(
BookReadActivity
.
BOOK_ID
,
newBookData
[
position
].
id
)
bundle
.
putString
(
Constant
.
ROUTE_
BOOK_ID
,
newBookData
[
position
].
id
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
}
}
rv_newbook
.
layoutManager
=
GridLayoutManager
(
requireContext
(),
2
)
rv_newbook
.
layoutManager
=
GridLayoutManager
(
requireContext
(),
2
)
...
@@ -172,7 +172,7 @@ class BookCityFragment : LazyLoadBaseFragment(), BookCityView, View.OnClickListe
...
@@ -172,7 +172,7 @@ class BookCityFragment : LazyLoadBaseFragment(), BookCityView, View.OnClickListe
.
setAdapter
(
ImageTitleAdapter
(
data
.
records
))
.
setAdapter
(
ImageTitleAdapter
(
data
.
records
))
.
setOnBannerListener
{
data2
,
_
->
.
setOnBannerListener
{
data2
,
_
->
val
bundle
=
Bundle
()
val
bundle
=
Bundle
()
bundle
.
putString
(
BookReadActivity
.
BOOK_ID
,
(
data2
as
BookBean
).
id
)
bundle
.
putString
(
Constant
.
ROUTE_
BOOK_ID
,
(
data2
as
BookBean
).
id
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
}
}
}
}
...
...
book/app/src/main/java/com/mints/enjoyboxjia/ui/fragment/BookListFragment.kt
View file @
b6ce8584
...
@@ -116,11 +116,11 @@ class BookListFragment : LazyLoadBaseFragment(), PicContentView, OnRefreshListen
...
@@ -116,11 +116,11 @@ class BookListFragment : LazyLoadBaseFragment(), PicContentView, OnRefreshListen
hotStyleAdapter
=
CountAdapter
()
hotStyleAdapter
=
CountAdapter
()
hotStyleAdapter
.
animationEnable
=
false
hotStyleAdapter
.
animationEnable
=
false
rv_pic_list
.
adapter
=
hotStyleAdapter
rv_pic_list
.
adapter
=
hotStyleAdapter
hotStyleAdapter
?
.
setOnCountItemClickListener
(
object
:
hotStyleAdapter
.
setOnCountItemClickListener
(
object
:
CountAdapter
.
OnCountItemClickListener
{
CountAdapter
.
OnCountItemClickListener
{
override
fun
onItemClick
(
bean
:
BookBean
)
{
override
fun
onItemClick
(
bean
:
BookBean
)
{
val
bundle
=
Bundle
()
val
bundle
=
Bundle
()
bundle
.
putString
(
BookReadActivity
.
BOOK_ID
,
bean
.
id
)
bundle
.
putString
(
Constant
.
ROUTE_
BOOK_ID
,
bean
.
id
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
}
}
})
})
...
...
book/app/src/main/java/com/mints/enjoyboxjia/ui/fragment/BookShelfFragment.kt
View file @
b6ce8584
...
@@ -49,7 +49,7 @@ class BookShelfFragment : LazyLoadBaseFragment(), BookShelfView, View.OnClickLis
...
@@ -49,7 +49,7 @@ class BookShelfFragment : LazyLoadBaseFragment(), BookShelfView, View.OnClickLis
}
}
val
bundle
=
Bundle
()
val
bundle
=
Bundle
()
bundle
.
putString
(
BookReadActivity
.
BOOK_ID
,
shelfBookData
[
position
].
id
)
bundle
.
putString
(
Constant
.
ROUTE_
BOOK_ID
,
shelfBookData
[
position
].
id
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
}
}
rv_bookshelf
.
layoutManager
=
GridLayoutManager
(
requireContext
(),
3
)
rv_bookshelf
.
layoutManager
=
GridLayoutManager
(
requireContext
(),
3
)
...
@@ -62,7 +62,7 @@ class BookShelfFragment : LazyLoadBaseFragment(), BookShelfView, View.OnClickLis
...
@@ -62,7 +62,7 @@ class BookShelfFragment : LazyLoadBaseFragment(), BookShelfView, View.OnClickLis
likeBookAdapter
=
LikeBookAdapter
(
requireActivity
())
likeBookAdapter
=
LikeBookAdapter
(
requireActivity
())
likeBookAdapter
?.
setOnItemClickListener
{
_
,
_
,
position
->
likeBookAdapter
?.
setOnItemClickListener
{
_
,
_
,
position
->
val
bundle
=
Bundle
()
val
bundle
=
Bundle
()
bundle
.
putString
(
BookReadActivity
.
BOOK_ID
,
likeBookData
[
position
].
id
)
bundle
.
putString
(
Constant
.
ROUTE_
BOOK_ID
,
likeBookData
[
position
].
id
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
readyGo
(
BookReadActivity
::
class
.
java
,
bundle
)
}
}
rv_booklike
.
layoutManager
=
GridLayoutManager
(
requireContext
(),
4
)
rv_booklike
.
layoutManager
=
GridLayoutManager
(
requireContext
(),
4
)
...
@@ -185,13 +185,15 @@ class BookShelfFragment : LazyLoadBaseFragment(), BookShelfView, View.OnClickLis
...
@@ -185,13 +185,15 @@ class BookShelfFragment : LazyLoadBaseFragment(), BookShelfView, View.OnClickLis
}
}
fun
delete
()
{
fun
delete
()
{
var
strArr
=
""
if
(
shelfBookData
.
size
>
0
)
{
for
(
datum
in
shelfBookData
)
{
var
strArr
=
""
if
(
datum
.
isChecked
&&
datum
.
id
!=
null
)
{
for
(
datum
in
shelfBookData
)
{
strArr
+=
(
datum
.
id
+
","
)
if
(
datum
.
isChecked
&&
datum
.
id
!=
null
)
{
strArr
+=
(
datum
.
id
+
","
)
}
}
}
bookShelfPresenter
.
cancelCollect
(
strArr
)
}
}
bookShelfPresenter
.
cancelCollect
(
strArr
)
}
}
override
fun
onClick
(
v
:
View
?)
{
override
fun
onClick
(
v
:
View
?)
{
...
...
book/app/src/main/java/com/mints/enjoyboxjia/ui/fragment/MyFragment.kt
View file @
b6ce8584
...
@@ -103,7 +103,10 @@ class MyFragment : LazyLoadBaseFragment(), MyView, View.OnClickListener {
...
@@ -103,7 +103,10 @@ class MyFragment : LazyLoadBaseFragment(), MyView, View.OnClickListener {
backPhoneDialog
()
backPhoneDialog
()
}
}
R
.
id
.
ll_my_set
->
{
R
.
id
.
ll_my_set
->
{
readyGo
(
SettingsActivity
::
class
.
java
)
val
bundle
=
Bundle
()
bundle
.
putString
(
Constant
.
ROUTE_BOOK_ID
,
"80670"
)
readyGo
(
LongBookReadActivity
::
class
.
java
,
bundle
)
// readyGo(SettingsActivity::class.java)
}
}
}
}
...
...
book/app/src/main/java/com/mints/enjoyboxjia/utils/StringUtils.java
0 → 100644
View file @
b6ce8584
package
com
.
mints
.
enjoyboxjia
.
utils
;
import
android.content.Context
;
import
androidx.annotation.StringRes
;
import
com.mints.enjoyboxjia.MintsApplication
;
import
java.text.DateFormat
;
import
java.text.ParseException
;
import
java.text.SimpleDateFormat
;
import
java.util.Calendar
;
import
java.util.Date
;
public
class
StringUtils
{
private
static
final
String
TAG
=
"StringUtils"
;
private
static
final
int
HOUR_OF_DAY
=
24
;
private
static
final
int
DAY_OF_YESTERDAY
=
2
;
private
static
final
int
TIME_UNIT
=
60
;
//将时间转换成日期
public
static
String
dateConvert
(
long
time
,
String
pattern
)
{
Date
date
=
new
Date
(
time
);
SimpleDateFormat
format
=
new
SimpleDateFormat
(
pattern
);
return
format
.
format
(
date
);
}
//将日期转换成昨天、今天、明天
public
static
String
dateConvert
(
String
source
,
String
pattern
)
{
DateFormat
format
=
new
SimpleDateFormat
(
pattern
);
Calendar
calendar
=
Calendar
.
getInstance
();
try
{
Date
date
=
format
.
parse
(
source
);
long
curTime
=
calendar
.
getTimeInMillis
();
calendar
.
setTime
(
date
);
//将MISC 转换成 sec
long
difSec
=
Math
.
abs
((
curTime
-
date
.
getTime
())
/
1000
);
long
difMin
=
difSec
/
60
;
long
difHour
=
difMin
/
60
;
long
difDate
=
difHour
/
60
;
int
oldHour
=
calendar
.
get
(
Calendar
.
HOUR
);
//如果没有时间
if
(
oldHour
==
0
)
{
//比日期:昨天今天和明天
if
(
difDate
==
0
)
{
return
"今天"
;
}
else
if
(
difDate
<
DAY_OF_YESTERDAY
)
{
return
"昨天"
;
}
else
{
DateFormat
convertFormat
=
new
SimpleDateFormat
(
"yyyy-MM-dd"
);
String
value
=
convertFormat
.
format
(
date
);
return
value
;
}
}
if
(
difSec
<
TIME_UNIT
)
{
return
difSec
+
"秒前"
;
}
else
if
(
difMin
<
TIME_UNIT
)
{
return
difMin
+
"分钟前"
;
}
else
if
(
difHour
<
HOUR_OF_DAY
)
{
return
difHour
+
"小时前"
;
}
else
if
(
difDate
<
DAY_OF_YESTERDAY
)
{
return
"昨天"
;
}
else
{
DateFormat
convertFormat
=
new
SimpleDateFormat
(
"yyyy-MM-dd"
);
String
value
=
convertFormat
.
format
(
date
);
return
value
;
}
}
catch
(
ParseException
e
)
{
e
.
printStackTrace
();
}
return
""
;
}
public
static
String
toFirstCapital
(
String
str
)
{
return
str
.
substring
(
0
,
1
).
toUpperCase
()
+
str
.
substring
(
1
);
}
public
static
String
getString
(
Context
context
,
@StringRes
int
id
)
{
return
context
.
getResources
().
getString
(
id
);
}
public
static
String
getString
(
Context
context
,
@StringRes
int
id
,
Object
...
formatArgs
)
{
return
MintsApplication
.
getContext
().
getResources
().
getString
(
id
,
formatArgs
);
}
/**
* 将文本中的半角字符,转换成全角字符
*
* @param input
* @return
*/
public
static
String
halfToFull
(
String
input
)
{
char
[]
c
=
input
.
toCharArray
();
for
(
int
i
=
0
;
i
<
c
.
length
;
i
++)
{
if
(
c
[
i
]
==
32
)
//半角空格
{
c
[
i
]
=
(
char
)
12288
;
continue
;
}
//根据实际情况,过滤不需要转换的符号
//if (c[i] == 46) //半角点号,不转换
// continue;
if
(
c
[
i
]
>
32
&&
c
[
i
]
<
127
)
//其他符号都转换为全角
c
[
i
]
=
(
char
)
(
c
[
i
]
+
65248
);
}
return
new
String
(
c
);
}
//功能:字符串全角转换为半角
public
static
String
fullToHalf
(
String
input
)
{
char
[]
c
=
input
.
toCharArray
();
for
(
int
i
=
0
;
i
<
c
.
length
;
i
++)
{
if
(
c
[
i
]
==
12288
)
//全角空格
{
c
[
i
]
=
(
char
)
32
;
continue
;
}
if
(
c
[
i
]
>
65280
&&
c
[
i
]
<
65375
)
c
[
i
]
=
(
char
)
(
c
[
i
]
-
65248
);
}
return
new
String
(
c
);
}
}
book/app/src/main/java/com/mints/library/utils/Utils.java
View file @
b6ce8584
...
@@ -43,7 +43,7 @@ public final class Utils {
...
@@ -43,7 +43,7 @@ public final class Utils {
/**
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
* 根据手机的分辨率从 dp 的单位 转成为 px(像素)
*/
*/
public
static
int
d
ip2p
x
(
Context
context
,
float
dpValue
)
{
public
static
int
d
pToP
x
(
Context
context
,
float
dpValue
)
{
final
float
scale
=
context
.
getResources
().
getDisplayMetrics
().
density
;
final
float
scale
=
context
.
getResources
().
getDisplayMetrics
().
density
;
return
(
int
)
(
dpValue
*
scale
+
0.5f
);
return
(
int
)
(
dpValue
*
scale
+
0.5f
);
}
}
...
...
book/app/src/main/res/layout/activity_long_book_read.xml
0 → 100644
View file @
b6ce8584
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:id=
"@+id/view_content"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:background=
"@color/white"
android:orientation=
"vertical"
>
<include
layout=
"@layout/header_layout"
/>
<LinearLayout
android:id=
"@+id/view_book"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<FrameLayout
android:layout_width=
"match_parent"
android:layout_height=
"0dp"
android:layout_weight=
"1"
>
<com.mints.enjoyboxjia.read.YPageView
android:id=
"@+id/pageview"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
/>
<LinearLayout
android:id=
"@+id/view_vip"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"30dp"
android:orientation=
"vertical"
android:visibility=
"gone"
>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center_horizontal"
android:layout_marginTop=
"20dp"
android:text=
"后续内容更精彩,充值后继续阅读"
android:textColor=
"@color/color_goldenrod"
/>
<TextView
android:id=
"@+id/btn_submit"
android:layout_width=
"300dp"
android:layout_height=
"38dp"
android:layout_gravity=
"center_horizontal"
android:layout_marginTop=
"40dp"
android:background=
"@drawable/btn_bg_gold"
android:gravity=
"center"
android:text=
"开通会员,免费阅读本书"
android:textColor=
"@color/color_goldenrod"
android:textSize=
"18sp"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"30dp"
android:text=
"1.目前充值会员暂不支持退款,一经购买不可退换\n\n2.未满18岁的未成年人需要在监护人主导,同意下进行相关付费操作\n\n3.充值一般在5分钟内到账,如未到账请提供支付截图在'我的'页面联系客服\n\n4.之前充值账户请登录后继续阅读"
android:textColor=
"@color/color_956244"
/>
</LinearLayout>
</FrameLayout>
<LinearLayout
android:id=
"@+id/view_setting"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:orientation=
"horizontal"
android:paddingTop=
"5dp"
android:paddingBottom=
"5dp"
>
<LinearLayout
android:id=
"@+id/tab_setting_chapter"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_weight=
"1"
android:gravity=
"center"
android:orientation=
"vertical"
>
<ImageView
android:id=
"@+id/tab_iv_bookshelf"
android:layout_width=
"20dp"
android:layout_height=
"20dp"
android:contentDescription=
"@null"
android:paddingTop=
"2dp"
/>
<TextView
android:id=
"@+id/tab_tv_bookshelf"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"2dp"
android:text=
"目录"
android:textColor=
"@color/black"
android:textSize=
"12sp"
/>
</LinearLayout>
<LinearLayout
android:id=
"@+id/tab_setting_book"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_weight=
"1"
android:gravity=
"center"
android:orientation=
"vertical"
>
<ImageView
android:layout_width=
"20dp"
android:layout_height=
"20dp"
android:contentDescription=
"@null"
android:src=
"@mipmap/ic_book_setting"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"2dp"
android:text=
"设置"
android:textColor=
"@color/black"
android:textSize=
"12sp"
/>
</LinearLayout>
<LinearLayout
android:id=
"@+id/tab_setting_share"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_weight=
"1.0"
android:gravity=
"center"
android:orientation=
"vertical"
android:visibility=
"gone"
>
<ImageView
android:layout_width=
"20dp"
android:layout_height=
"20dp"
android:contentDescription=
"@null"
android:src=
"@mipmap/ic_book_share"
/>
<TextView
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"2dp"
android:text=
"分享"
android:textColor=
"@color/black"
android:textSize=
"12sp"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
book/app/src/main/res/layout/item_bookshelf.xml
View file @
b6ce8584
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"20
2
dp"
android:layout_height=
"20
6
dp"
android:layout_marginTop=
"4dp"
android:layout_marginTop=
"4dp"
android:layout_marginBottom=
"6dp"
android:layout_marginBottom=
"6dp"
android:orientation=
"vertical"
>
android:orientation=
"vertical"
>
...
@@ -10,7 +10,7 @@
...
@@ -10,7 +10,7 @@
<ImageView
<ImageView
android:id=
"@+id/image_iv"
android:id=
"@+id/image_iv"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"1
5
0dp"
android:layout_height=
"1
4
0dp"
android:scaleType=
"centerCrop"
android:scaleType=
"centerCrop"
android:src=
"@mipmap/bg_book_more"
android:src=
"@mipmap/bg_book_more"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
...
@@ -21,20 +21,20 @@
...
@@ -21,20 +21,20 @@
android:id=
"@+id/title_tv"
android:id=
"@+id/title_tv"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"
10
dp"
android:layout_marginTop=
"
4
dp"
android:ellipsize=
"end"
android:ellipsize=
"end"
android:maxLines=
"1"
android:lines=
"2"
android:maxLines=
"2"
android:textColor=
"@color/black"
android:textColor=
"@color/black"
app:layout_constraintStart_toStartOf=
"@id/image_iv"
app:layout_constraintStart_toStartOf=
"@id/image_iv"
app:layout_constraintTop_toBottomOf=
"@id/image_iv"
/>
app:layout_constraintTop_toBottomOf=
"@id/image_iv"
/>
<TextView
<TextView
android:id=
"@+id/label_tv"
android:id=
"@+id/label_tv"
android:layout_width=
"
106dp
"
android:layout_width=
"
match_parent
"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"4dp"
android:layout_marginTop=
"4dp"
android:ellipsize=
"end"
android:lines=
"1"
android:maxLines=
"1"
android:textColor=
"@color/gray"
android:textColor=
"@color/gray"
android:textSize=
"12sp"
android:textSize=
"12sp"
app:layout_constraintStart_toStartOf=
"@id/image_iv"
app:layout_constraintStart_toStartOf=
"@id/image_iv"
...
...
book/app/src/main/res/layout/item_hotbook.xml
View file @
b6ce8584
...
@@ -2,11 +2,10 @@
...
@@ -2,11 +2,10 @@
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_margin=
"10dp"
android:layout_marginBottom=
"10dp"
android:paddingLeft=
"6dp"
android:orientation=
"horizontal"
android:layout_marginTop=
"6dp"
android:paddingStart=
"5dp"
android:paddingBottom=
"5dp"
android:paddingEnd=
"5dp"
>
android:orientation=
"horizontal"
>
<ImageView
<ImageView
android:id=
"@+id/image_iv"
android:id=
"@+id/image_iv"
...
@@ -27,8 +26,8 @@
...
@@ -27,8 +26,8 @@
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"6dp"
android:layout_marginTop=
"6dp"
android:lines=
"1"
android:ellipsize=
"end"
android:ellipsize=
"end"
android:lines=
"1"
android:text=
"我去平行时空"
android:text=
"我去平行时空"
android:textColor=
"@color/black"
android:textColor=
"@color/black"
android:textSize=
"14sp"
/>
android:textSize=
"14sp"
/>
...
...
book/app/src/main/res/layout/item_list_count.xml
View file @
b6ce8584
...
@@ -38,9 +38,9 @@
...
@@ -38,9 +38,9 @@
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"6dp"
android:layout_marginTop=
"6dp"
android:lines=
"
3
"
android:lines=
"
2
"
android:ellipsize=
"end"
android:ellipsize=
"end"
android:minLines=
"
3
"
android:minLines=
"
2
"
android:textColor=
"@color/gray"
android:textColor=
"@color/gray"
android:textSize=
"16sp"
/>
android:textSize=
"16sp"
/>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment