Android Compose 仿真书籍翻页组件PTQBookPageView
Android Compose 仿真书籍翻页组件PTQBookPageView
Android Compose 仿真书籍翻页组件PTQBookPageView

写在前面

历时数月,总算完结了这个Jetpack Compose的仿真书本翻页组件,它支撑任何的非动态内容,且可定制程度高,翻页手感十分舒适丝滑~

这个项目源于我很喜欢看小说,可是发现国内干流的几款小说阅读APP的仿真翻页作用的安卓端都不如iOS端体会好,例如手势处理或者翻页作用的制作等,以及一些暗影、页面扭曲作用的处理等等,因此便诞生了写一个仿iOS端翻页作用的组件的主意,而正好最近又正好在学Compose,所以决议运用Compose完结。

下面将详细介绍翻页器组件的运用。


PTQBookPageView

Android JetPack Compose 仿真书本翻页组件,支撑自定义任何非动态内容。

组件的作用是仿iOS端完结的,具体能够直接下载DemoApk体会。

(DemoApk 中的图片均运用 AI 生成的图片)

[作用演示] DemoApk

[项目库房] Github

[设计思路] 传送门

[源码解析]

  • 算法部分
  • 制作和动画部分(包括文字扭曲、点击动画、暗影等作用)

1 运用组件

1.1 引入

1、在项目的 root 的 build.gradle 中引入库房。

    allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

2、在项目的 app 的 build.gradle 中增加依赖。

    dependencies {
        implementation 'com.github.FantasticPornTaiQiang:PTQFlipper:$latest_version'
    }

最新版别

1.2 根本运用

在@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 显现的内容正常
  • 在 contents 中使用回调参数 currentPage 设置当时页显现的内容
  • 在 contents 中,最外层是一个 fillMaxSize 的 Box,并需要运用 background 设置当时纸页正面的色彩
  • 在 contents 的 Box 中(即示例代码的注释处),能够自定义任何非动态的内容

2 定制

2.1 页数操控

组件供给了rememberPTQBookPageViewState办法进行页数相关的操控。

rememberPTQBookPageViewState(pageCount: Int = 1, currentPage: Int? = null)

  • pageCount 总页数,假如页面总数小于当时页数,则会引发反常

  • currentPage 当时页数,假如为 null 则页数由翻页器内部操控

操控页数办法有两种:

  • 不传入 currentPage,则页数作为组件内部状况,由翻页器内部自动操控

  • 传入 currentPage,则页数作为外部状况,需要在onTurnPageRequest办法中保护(详细介绍(见2.4))。

示例如下

    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()
        }
    }

2.2 装备参数

组件供给了rememberPTQBookPageViewConfig办法进行相关的操控。

rememberPTQBookPageViewConfig(pageColor: Color = Color.White, disabled: Boolean = false)

  • pageColor 当时页背面的色彩(页面正面的色彩在 contents 的 Box 的 background modifier 中设置)

  • disabled 整个组件是否禁用(若想单独禁用单击或拖动手势,请看高档定制(见3))

config 以参数的方法传入组件以生效,示例如下

    val config by rememberPTQBookPageViewConfig()
    PTQBookPageView(state = state, config = config) {
        ...
    }

2.3 巨细和方位

组件支撑以 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,) {
        ...
    }

2.4 翻页恳求

在PTQBookPageViewScope中注册onTurnPageRequest回调以呼应手指的翻页恳求。

onTurnPageRequest(block: (currentPage: Int, isNextOrPrevious: Boolean, success: Boolean) -> Unit)

当用户有想翻页的操作时,会触发这个回调。假如当时处于最终一页,仍想向右翻,则会翻页失败,但此回调仍然会调用,能够使用这个回调弹 Toast 显现没有下一页了。

  • currentPage 用户操作之后的页面索引,范围是 [0, pageCount)

  • isNextOrPrevious 用户想向前翻页仍是向后翻页,true 表明 next

  • success 用户翻页是否成功,若处于最终一页还想向右翻则翻页失败,处于第一页向前翻同理

示例代码(见2.1)

3 高档定制

3.1 操控点击时的翻页行为

在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 处时翻上一页

示例代码

3.2 操控拖动时的起手呼应

在PTQBookPageViewScope中注册responseDragWhen回调以自定义操控拖动时的起手呼应。

responseDragWhen(block: (rightDown: Point, startTouchPoint: Point, currentTouchPoint: Point) -> Boolean?)

  • rightDown 组件右下角坐标(左上角为 0)

  • startTouchPoint 用户起手坐标(开端动画前)

  • currentTouchPoint 当时接触点坐标

  • 返回值 翻页行为,true=下一页(从右侧翻开),false=上一页(从左侧翻开),null=不呼应

此回调决议了从起手开端到能够自由拖动之间的翻页行为,假如不注册此回调,默许情况下:

  • 从右往左滑则右起手(翻下一页)

  • 从左往右划则左起手(翻上一页)

示例代码

3.3 操控拖动松手时的翻页行为

在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(见2.4)回调。

假如不注册此回调,则默许情况下:

  • 起手从右向左

    • 松手在 x>1/2 处则不翻页

    • 松手在 x<1/2 处则翻下一页

  • 起手从左向右

    • 松手在 x>1/2 处则翻上一页

    • 松手在 x<1/2 处则不翻页

示例代码


最终

以上就是组件的全部内容了,完结进程不可谓不崎岖,之后会出这个组件的源码解析。

在完结翻页器的进程中,我的同学xzy在完结图片扭曲的功用时供给了一些协助,在此表明感谢。

就写到这儿吧~