Android JetPack Compose 仿真书籍翻页组件,支持自定义任何非动态内容。
[效果演示] DemoApk v1.1.0 提取码:ptq6
[项目仓库] Github
[组件使用] 传送门
[设计思路] 传送门
[源码解析]
(DemoApk 中的图片均使用 AI 生成的图片)
1、在项目的 root 的 build.gradle 中引入仓库。(高版本gradle是在settings.gradle里配)
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
2、在项目的 app 的 build.gradle 中添加依赖。
dependencies {
implementation 'com.github.FantasticPornTaiQiang:PTQFlipper:$latest_version'
}
在@Composable 中使用组件。
val state by rememberPTQBookPageViewState(pageCount = 100)
PTQBookPageView(state = state) {
contents { currentPage, refresh ->
Box(modifier = Modifier.fillMaxSize().background(Color.White)) {
//任何非动态的自定义内容
}
refresh()
}
}
- 在 rememberPTQBookPageViewState 中设置总页数
- 请务必在 contents 的最末尾调用 refresh 方法以保证 View 显示的内容正常
- 例如需要网络请求图片,那么请在请求成功后手动refresh,把新内容同步到组件内
- 在 contents 中利用回调参数 currentPage 设置当前页显示的内容
- 在 contents 中,最外层是一个 fillMaxSize 的 Box,并需要使用 background 设置当前纸页正面的颜色
- 在 contents 的 Box 中(即示例代码的注释处),可以自定义任何非动态的内容
注:不支持:
- 不支持纸张(即背景色)带透明度
- 不支持纸张设置圆角(即必须是矩形的)
- 暂时不支持像LazyColumn这种内部状态会快速变化的View(除非你能监听到状态停止变化的时刻,然后手动调用refresh,总之就是要保证refresh能调用到)
组件提供了rememberPTQBookPageViewState方法进行页数相关的控制。
rememberPTQBookPageViewState(pageCount: Int = 1, currentPage: Int? = null)
-
pageCount 总页数,如果页面总数小于当前页数,则会引发异常
-
currentPage 当前页数,如果为 null 则页数由翻页器内部控制
控制页数方式有两种:
-
不传入 currentPage,则页数作为组件内部状态,由翻页器内部自动控制
-
传入 currentPage,则页数作为外部状态,需要在onTurnPageRequest方法中维护(详细介绍)。
示例如下
var state by rememberPTQBookPageViewState(pageCount = 100, currentPage = 0)
PTQBookPageView(state = state) {
onTurnPageRequest { currentPage, isNextOrPrevious, success ->
if (!success) {
Toast.makeText(ctx, if (isNextOrPrevious) "已经是最后一页啦" else "已经是第一页啦", Toast.LENGTH_SHORT).show()
} else {
state = state.copy(currentPage = if (isNextOrPrevious) currentPage + 1 else currentPage - 1)
}
}
contents { currentPage, refresh ->
Box(modifier = Modifier.fillMaxSize().background(Color.White)) {
//任何非动态的自定义内容
Text(currentPage.toString(), modifier = Modifier.align(Alignment.Center))
}
refresh()
}
}
组件提供了rememberPTQBookPageViewConfig方法进行相关的控制。
rememberPTQBookPageViewConfig(pageColor: Color = Color.White, disabled: Boolean = false)
-
pageColor 当前页背面的颜色(页面正面的颜色在 contents 的 Box 的 background modifier 中设置)(暂不支持页面透明度的设置,即alpha通道必须为ff)
-
disabled 整个组件是否禁用(若想单独禁用单击或拖动手势,请看高级定制)
v1.1.0新增属性:
-
distortionInterval 图像扭曲的采样间隔,可以根据屏幕大小去作适配,此值越小,曲线越精密,但同样地,计算开销会越大,性能会下降
-
bezierEdgeDownSampling 边缘扭曲的采样间隔,可以根据屏幕大小去作适配,此值越大,曲线越精密,但同样地,计算开销会越大,性能会下降(变化不是线性的)
config 以参数的形式传入组件以生效,示例如下
val config by rememberPTQBookPageViewConfig()
PTQBookPageView(state = state, config = config) {
...
}
组件支持以 modifier 的形式设置大小和位置,具体地
-
支持以 padding modifier 方式设置组件位置和大小
-
支持以 height modifier 和 width modifier 方式设置大小
-
不支持offset 和 size modifier
示例如下
PTQBookPageView(
modifier = Modifier.padding(start = padding[0].dp, top = padding[1].dp, end = padding[2].dp, bottom = padding[3].dp),
config = config,) {
...
}
PTQBookPageView(
modifier = Modifier.width(100.dp).height(100.dp),
config = config,) {
...
}
在PTQBookPageViewScope中注册onTurnPageRequest
回调以响应手指的翻页请求。
onTurnPageRequest(block: (currentPage: Int, isNextOrPrevious: Boolean, success: Boolean) -> Unit)
当用户有想翻页的操作时,会触发这个回调。如果当前处于最后一页,仍想向右翻,则会翻页失败,但此回调仍然会调用,可以利用这个回调弹 Toast 显示没有下一页了。
-
currentPage 用户操作之后的页面索引,范围是 [0, pageCount)
-
isNextOrPrevious 用户想向前翻页还是向后翻页,true 表示 next
-
success 用户翻页是否成功,若处于最后一页还想向右翻则翻页失败,处于第一页向前翻同理
在PTQBookPageViewScope中注册tapBehavior
回调以自定义控制点击时的行为。
tapBehavior(block: (leftUp: Point, rightDown: Point, touchPoint: Point) -> Boolean?)
-
leftUP 组件左上角坐标
-
rightDown 组件右下角坐标
-
touchPoint 用户手指触摸坐标
-
返回值 翻页行为,true=下一页,false=上一页,null=不响应
此回调中的 Point 均为相对于组件左上角的坐标点,且此回调会影响 UI 的呈现和onTurnPageRequest回调。
如果不注册此回调,则默认情况下:
-
点击 x>1/2 处时翻下一页
-
点击 x<1/2 处时翻上一页
在PTQBookPageViewScope中注册responseDragWhen
回调以自定义控制拖动时的起手响应。
responseDragWhen(block: (rightDown: Point, startTouchPoint: Point, currentTouchPoint: Point) -> Boolean?)
-
rightDown 组件右下角坐标(左上角为 0)
-
startTouchPoint 用户起手坐标(开始动画前)
-
currentTouchPoint 当前触摸点坐标
-
返回值 翻页行为,true=下一页(从右侧翻开),false=上一页(从左侧翻开),null=不响应
此回调决定了从起手开始到能够自由拖动之间的翻页行为,如果不注册此回调,默认情况下:
-
从右往左滑则右起手(翻下一页)
-
从左往右划则左起手(翻上一页)
在PTQBookPageViewScope中注册dragBehavior
回调以自定义控制拖动松手时的翻页行为。
dragBehavior(block: (
rightDown: Point,
initialTouchPoint: Point,
lastTouchPoint: Point,
isRightToLeftWhenStart: Boolean
) -> Pair<Boolean, Boolean?>
)
-
rightDown 组件右下角坐标(左上角为 0)
-
initialTouchPoint 用户初始触摸坐标(开始动画前)
-
lastTouchPoint 用户松手坐标(结束动画前)
-
isRightToLeftWhenStart 用户起手是从右向左还是从左向右(即 responseDragWhen 的结果)
-
返回值 翻页行为
-
第一个参数控制 UI 动画,true=从左侧退出,false=从右侧退出
-
第二个参数控制翻页响应,true=下一页,false=上一页,null=不翻页
-
此回调中的 Point 均为相对于组件左上角的坐标点,且此回调会影响 UI 的呈现和onTurnPageRequest回调。
如果不注册此回调,则默认情况下:
-
起手从右向左
-
松手在 x>1/2 处则不翻页
-
松手在 x<1/2 处则翻下一页
-
-
起手从左向右
-
松手在 x>1/2 处则翻上一页
-
松手在 x<1/2 处则不翻页
-
v1.0.0
- 初始版本,readme内的基本功能
v1.0.1
- 修复跟随算法bug
v1.1.0
- 配置项新增distortionInterval和bezierEdgeDownSampling
- 性能优化
- 移除了minSdk26的限制