← 返回首頁
Adit Lal
Adit Lal
@aditlal
41🔁 6
𝕏 (Twitter)🔥🔥
AI 中文摘要Claude 生成
開發者剛開源了「ComposePinchGrid」——一個為 Compose Multiplatform 打造的 Google Photos 風格捏縮網格元件。可在 Android、iOS、Desktop 和 Web 上運作,只需 3 行程式碼,且零 Material 依賴。 真正的難點不在網格本身,而在手勢辨識。transformable() 與 LazyVerticalGrid 捲軸的衝突在於兩者搶奪相同的指標事件。解決方案是使用原始的 pointerInput 搭配 PointerEventPass.Initial——在網格捲軸處理器之前截獲 2 指捏縮手勢,單指捲軸則完全通過。 元件提供的功能包括非對稱閾值調整(捏展自然產生較弱的縮放,透過補償實現平衡)、死區過濾(消除手指顫抖造成的抖動)、呼吸動畫效果(使用 graphicsLayer 達到零重組)、平台原生震動回饋(Android 使用 CLOCK_TICK,iOS 使用 UISelectionFeedbackGenerator)。 架構採用 Kotlin Multiplatform 開發,支援 Android、iOS、Desktop 和 Wasm,採用 Apache 2.0 授權。 技術特點在於為何選擇原始 pointerInput 而非 transformable——transformable 乍看是捏縮手勢的顯然選擇,卻與 LazyVerticalGrid 捲軸衝突。兩者競爭相同的指標事件,單指捲軸會被誤判為變換開始,導致網格凍結而非捲動。ComposePinchGrid 使用 awaitEachGesture 搭配 awaitFirstDown,只在偵測到 2 個或更多指標時才消費事件,單指捲軸完全不受影響。 使用者可透過 thresholdFraction 參數控制觸發欄數變更需要的捏縮程度(較低數值代表更靈敏),pinchOutThresholdMultiplier 在 0.85f 時讓放大需要 15% 較少的手指移動,使兩個方向感覺同樣反應靈敏。deadZone 預設 0.01f 過濾微小動作,防止手指顫抖造成的抖動。 呼吸動畫在捏縮手勢期間讓網格隨指標縮放,提供即時視覺回饋,使用 graphicsLayer 實現零重組的 GPU 變換。breathingScaleIntensity 預設 0.10f(±10% 縮放),可設為 0f 禁用;breathingReturnDuration 預設 150ms 控制釋放時回歸動畫速度。 欄數變更時,網格會快照首個可見項目索引並在變更後復原,防止天真的 GridCells.Fixed() 交換帶來的卡頓捲軸跳躍。最佳實踐是提供穩定的 key 值。 手勢感應可完全禁用,保留程式控制能力,透過 snapToColumn() 方法實現鍵盤、按鈕或無障礙功能的欄數控制。performHapticFeedback 在每次欄數變更時自動觸發,可透過 hapticEnabled = false 禁用。 效能考量上,呼吸動畫使用 graphicsLayer 純繪製階段零重組;欄數變更單次 mutableIntStateOf 更新觸發網格重組;震動回饋內聯執行無協程開銷;捲軸復原採標準 Compose 模式的 LaunchedEffect + snapshotFlow。 元件的可配置性極高——每個參數都有經過調整的預設值,但可覆蓋任何設定。thresholdFraction 預設 0.45f 提供反應靈敏但不易意外觸發的平衡;pinchOutThresholdMultiplier 預設 0.85f 補償捏展自然較弱的特性;breathingScaleIntensity 預設 0.10f 提供適度視覺回饋;transitionSpec 預設即時重排,也支援 crossfade 等過渡效果。