最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

手勢(shì)事件消費(fèi)

2023-04-02 23:51 作者:哆啦a夢(mèng)的道具師  | 我要投稿

在了解手勢(shì)事件分發(fā)之后,我們接下來學(xué)習(xí)如何完成手勢(shì)事件消費(fèi),我們看到?awaitPointerEvent?返回了一個(gè)?PointerEvent?實(shí)例。


actual data class PointerEvent internal constructor(

? ? actual val changes: List<PointerInputChange>,

? ? internal val motionEvent: MotionEvent?

)

從 PointerEvent 類的聲明中可以看到包含了兩個(gè)屬性 changes 與 motionEvent。

  • motionEvent:實(shí)際上就是傳統(tǒng) View 系統(tǒng)中的 MotionEvent,由于被聲明 internal ,說明官方并不希望我們直接拿來使用。

  • changes:其中包含了一次手勢(shì)交互中所有手指的交互信息。在多指操作時(shí),利用?changes?可以輕松定制多指手勢(shì)處理。

可以看出單指交互的完整信息被封裝在了一個(gè) PointerInputChange 實(shí)例中,接下來我們看看 PointerInputChange 提供了哪些手勢(shì)信息。


class PointerInputChange(

? ? val id: PointerId, // 手指Id

? ? val uptimeMillis: Long, // 當(dāng)前手勢(shì)事件的時(shí)間戳

? ? val position: Offset, // 當(dāng)前手勢(shì)事件相對(duì)組件左上角的位置

? ? val pressed: Boolean, // 當(dāng)前手勢(shì)是否按下

? ? val previousUptimeMillis: Long, // 上一次手勢(shì)事件的時(shí)間戳

? ? val previousPosition: Offset, // 上一次手勢(shì)事件相對(duì)組件左上角的位置

? ? val previousPressed: Boolean, // 上一次手勢(shì)是否按下

? ? val consumed: ConsumedData, // 當(dāng)前手勢(shì)是否已被消費(fèi)

? ? val type: PointerType = PointerType.Touch // 手勢(shì)類型(鼠標(biāo)、手指、手寫筆、橡皮)?

)

利用這些豐富的手勢(shì)信息,我們可以在上層定制實(shí)現(xiàn)各類復(fù)雜的交互手勢(shì)。

可以看到其中的 consumed 成員記錄著該事件是否已被消費(fèi),我們可以使用?PointerInputChange?提供的 consume 系列 API 來修改這個(gè)手勢(shì)事件的消費(fèi)標(biāo)記。

changedToDown是否已經(jīng)按下(按下手勢(shì)已消費(fèi)則返回false)

changedToDownIgnoreConsumed是否已經(jīng)按下(忽略按下手勢(shì)已消費(fèi)標(biāo)記)

changedToUp是否已經(jīng)抬起(按下手勢(shì)已消費(fèi)則返回false)

changedToUpIgnoreConsumed是否已經(jīng)抬起(忽略按下手勢(shì)已消費(fèi)標(biāo)記)

positionChanged是否位置發(fā)生了改變(移動(dòng)手勢(shì)已消費(fèi)則返回false)

positionChangedIgnoreConsumed是否位置發(fā)生了改變(忽略已消費(fèi)標(biāo)記)

positionChange位置改變量(移動(dòng)手勢(shì)已消費(fèi)則返回Offset.Zero)

positionChangeIgnoreConsumed位置改變量(忽略移動(dòng)手勢(shì)已消費(fèi)標(biāo)記)

positionChangeConsumed當(dāng)前移動(dòng)手勢(shì)是否已被消費(fèi)

anyChangeConsumed當(dāng)前按下手勢(shì)或移動(dòng)手勢(shì)是否有被消費(fèi)

consumeDownChange消費(fèi)按下手勢(shì)

consumePositionChange消費(fèi)移動(dòng)手勢(shì)

consumeAllChanges消費(fèi)按下與移動(dòng)手勢(shì)

isOutOfBounds當(dāng)前手勢(shì)是否在固定范圍內(nèi)

前面提到,我們可以通過設(shè)置?PointerEventPass?來定制嵌套組件間手勢(shì)事件分發(fā)順序。假設(shè)分發(fā)流程中組件 A 預(yù)先獲取到了手勢(shì)信息并進(jìn)行消費(fèi),手勢(shì)事件仍然會(huì)被之后的組件 B 獲取得到。組件 B 在使用?positionChange?獲取的偏移值時(shí)會(huì)返回?Offset.ZERO,這是因?yàn)榇藭r(shí)該手勢(shì)事件已被標(biāo)記為已消費(fèi)的狀態(tài)。當(dāng)然組件 B 也可以通過 IgnoreConsumed 系列 API 突破已消費(fèi)標(biāo)記的限制獲取到手勢(shì)信息。

我們?nèi)匀煌ㄟ^前面使用的嵌套組件示例子來看看手勢(shì)事件的消費(fèi)。我們的嵌套組件中第一層組件使用 Inital,第二層組件使用 Final ,第三層組件使用 Main。

我們?cè)诘谌龑咏M件的手勢(shì)事件監(jiān)聽中進(jìn)行消費(fèi),因?yàn)槲覀冎朗謩?shì)事件會(huì)交由第一層, 再交由第三層,最后交由第二層。第三層組件處于本次手勢(shì)分發(fā)流程的中間位置。

當(dāng)我們?cè)诘谌龑咏M件消費(fèi)了?ACTION_DOWN?后,之后處理的第二層組件接收的手勢(shì)事件仍是被標(biāo)記為消費(fèi)狀態(tài)的。

@Composable

fun ConsumeDemo() {

? ? Box(

? ? ? ? contentAlignment = Alignment.Center,

? ? ? ? modifier = Modifier

? ? ? ? ? ? .fillMaxSize()

? ? ? ? ? ? .pointerInput(Unit) {

? ? ? ? ? ? ? ? awaitPointerEventScope {

? ? ? ? ? ? ? ? ? ? var event = awaitPointerEvent(PointerEventPass.Initial)

? ? ? ? ? ? ? ? ? ? Log.d(TAG, "first layer, downChange: ${event.changes[0].consumed.downChange}")

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ) {

? ? ? ? Box(

? ? ? ? ? ? contentAlignment = Alignment.Center,

? ? ? ? ? ? modifier = Modifier

? ? ? ? ? ? ? ? .size(400.dp)

? ? ? ? ? ? ? ? .background(Color.Blue)

? ? ? ? ? ? ? ? .pointerInput(Unit) {

? ? ? ? ? ? ? ? ? ? awaitPointerEventScope {

? ? ? ? ? ? ? ? ? ? ? ? var event = awaitPointerEvent(PointerEventPass.Final)

? ? ? ? ? ? ? ? ? ? ? ? Log.d(TAG, "second layer, downChange: ${event.changes[0].consumed.downChange}")

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ) {

? ? ? ? ? ? Box(

? ? ? ? ? ? ? ? Modifier

? ? ? ? ? ? ? ? ? ? .size(200.dp)

? ? ? ? ? ? ? ? ? ? .background(Color.Green)

? ? ? ? ? ? ? ? ? ? .pointerInput(Unit) {

? ? ? ? ? ? ? ? ? ? ? ? awaitPointerEventScope {

? ? ? ? ? ? ? ? ? ? ? ? ? ? var event = awaitPointerEvent()

? ? ? ? ? ? ? ? ? ? ? ? ? ? event.changes[0].consumeDownChange() // 消費(fèi)手勢(shì)事件

? ? ? ? ? ? ? ? ? ? ? ? ? ? Log.d(TAG, "third layer, downChange: ${event.changes[0].consumed.downChange}")

? ? ? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? )

? ? ? ? }

? ? }

}

介紹完 Compose 的手勢(shì)事件分發(fā)與消費(fèi),想必大家已經(jīng)對(duì)?awaitPointerEvent?這個(gè)低級(jí)別基礎(chǔ)手勢(shì)監(jiān)聽 API 已經(jīng)有了足夠的了解。然而在實(shí)際場(chǎng)景中我們還是應(yīng)該更多的依賴上層封裝完善的 API,因?yàn)楫?dāng)手勢(shì)邏輯變得越來越復(fù)雜時(shí),維護(hù)手勢(shì)交互處理邏輯的難度也會(huì)越來越大。接下來我們來介紹?AwaitPointerEventScope?中基于?awaitPointerEvent?實(shí)現(xiàn)的幾個(gè)常用手勢(shì)監(jiān)聽掛起方法。

手勢(shì)事件消費(fèi)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
高台县| 桐柏县| 中山市| 紫云| 梅河口市| 淮南市| 新民市| 新和县| 锡林郭勒盟| 桃江县| 南陵县| 西乌珠穆沁旗| 治县。| 天长市| 黑山县| 黑水县| 宝丰县| 瓦房店市| 松原市| 凌源市| 临泉县| 新晃| 浠水县| 时尚| 阿拉尔市| 凤山县| 和顺县| 巫溪县| 五原县| 肃南| 漳浦县| 镇坪县| 云霄县| 堆龙德庆县| 邵武市| 建平县| 广平县| 盐亭县| 西藏| 乌兰浩特市| 清徐县|