HarmonyOS 鸿蒙Next hitTestMode 问题
HarmonyOS 鸿蒙Next hitTestMode 问题
以下测试代码,当下拉使得offsety>0时,再反向上拉这个时候hitTestMode 应该是block,为什么list也会跟着往上滚动?
import { LogUtils } from ‘ds_components/Index’
import { MATCH_PARENT } from ‘…/contants/Size’
import { curves } from ‘@kit.ArkUI’
@Component
@Preview
export struct DSText {
datas: number[] = []
scroller: Scroller = new Scroller()
aboutToAppear(): void {
for (let i = 0; i < 30; i++) {
this.datas.push(i)
}
}
build() {
DSRefresh({ scroller: this.scroller }) {
List({ scroller: this.scroller }) {
ForEach(this.datas, (data: number, index) => {
ListItem() {
Text(data.toString()).width(MATCH_PARENT).height(60)
}
}, (data: number, index) => index.toString())
}.width(MATCH_PARENT).height(MATCH_PARENT).edgeEffect(EdgeEffect.None)
}
}
}
@Component
@Preview
export struct DSRefresh {
scroller: Scroller = new Scroller()
@BuilderParam itemLayout: () => void
@State offsetY: number = 0
@State scrollUp: Boolean = false
@State hitTestMode: HitTestMode = HitTestMode.Default
refreshEnable: boolean = true
maxOffsetY = vp2px(300)
downY: number = 0
lastX: number = 0
lastY: number = 0
damping: number = 0.5
@State state: DSRefreshState = DSRefreshState.None
@State headerHeight: number = 0
@State footerHeight: number = 0
onRefresh ?: () => void
onLoadMore ?: () => void
aboutToAppear(): void {
if (this.damping < 0) {
this.damping = 0.5
} else if (this.damping > 1) {
this.damping = 1
}
}
advancedDamping(offset: number, maxOffset: number = this.maxOffsetY): number {
const dampingCoefficient = this.damping / 1000; // 阻尼系数,调整阻尼增长速率
const dampingEffect = maxOffset * (1 - Math.exp(-dampingCoefficient * offset));
return dampingEffect;
}
build() {
Column() {
Row() {
Image($r(‘app.media.ic_header_loading’))
.width(30)
.aspectRatio(1)
.margin({ bottom: 10, top: 50 })
.rotate({ angle: this.state == DSRefreshState.Refresh ? 360 : 0 })
.animation({ iterations: -1, curve: Curve.Linear })
}.alignItems(VerticalAlign.Bottom).margin({ top: -this.headerHeight })
.onAreaChange((oldValue, newValue) => {
this.headerHeight = Number(newValue.height)
})
this.itemLayout()
// .width(MATCH_PARENT).height(MATCH_PARENT).backgroundColor(Color.Blue).textAlign(TextAlign.Center)
Text(<span class="hljs-string">'footer'</span>)
.width(MATCH_PARENT)
.height(<span class="hljs-number">100</span>)
.backgroundColor(Color.Red)
.textAlign(TextAlign.Center)
.onAreaChange((oldValue, newValue) => {
<span class="hljs-keyword">this</span>.footerHeight = <span class="hljs-built_in">Number</span>(newValue.height)
})
}
.hitTestBehavior(<span class="hljs-keyword">this</span>.hitTestMode)
.onTouch((event) => {
<span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.refreshEnable || <span class="hljs-keyword">this</span>.state != DSRefreshState.None) {
<span class="hljs-keyword">return</span>
}
<span class="hljs-keyword">const</span> touch = event.touches[<span class="hljs-number">0</span>]
<span class="hljs-keyword">let</span> diff = <span class="hljs-keyword">this</span>.advancedDamping(touch.y - <span class="hljs-keyword">this</span>.downY)
<span class="hljs-comment">// if ((diff > 0 && this.scroller.currentOffset()</span>
<span class="hljs-comment">// .yOffset > 0 || diff < 0 && !this.scroller.isAtEnd()) && this.offsetY == 0) {</span>
<span class="hljs-comment">// return</span>
<span class="hljs-comment">// }</span>
<span class="hljs-keyword">switch</span> (event.type) {
<span class="hljs-keyword">case</span> TouchType.Down: {
<span class="hljs-keyword">this</span>.downY = touch.y
LogUtils.e(<span class="hljs-string">"touch"</span>, `down:${<span class="hljs-keyword">this</span>.downY} `)
<span class="hljs-keyword">break</span>
}
<span class="hljs-keyword">case</span> TouchType.Move: {
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.offsetY != <span class="hljs-number">0</span>) {
<span class="hljs-keyword">this</span>.hitTestMode = HitTestMode.Block
LogUtils.e(<span class="hljs-string">"touch"</span>, <span class="hljs-string">"block"</span>)
}
<span class="hljs-comment">// else if (!this.scroller.isAtEnd() && this.scroller.currentOffset().yOffset > 0) {</span>
<span class="hljs-comment">// this.hitTestMode = HitTestMode.None</span>
<span class="hljs-comment">// LogUtils.e("touch", "none")</span>
<span class="hljs-comment">// return</span>
<span class="hljs-comment">// } else {</span>
<span class="hljs-comment">// this.hitTestMode = HitTestMode.Default</span>
<span class="hljs-comment">// LogUtils.e("touch", "default")</span>
<span class="hljs-comment">// }</span>
<span class="hljs-keyword">this</span>.scrollUp = <span class="hljs-keyword">this</span>.lastY > touch.y
<span class="hljs-comment">// LogUtils.e("touch", `move:${touch.y - this.downY}--${1 - Math.exp(-0.5 * (touch.y - this.downY))} `)</span>
<span class="hljs-keyword">if</span> (diff > <span class="hljs-keyword">this</span>.maxOffsetY || diff < -<span class="hljs-keyword">this</span>.maxOffsetY) {
<span class="hljs-keyword">return</span>
}
<span class="hljs-keyword">this</span>.offsetY = diff
<span class="hljs-keyword">break</span>
}
<span class="hljs-keyword">case</span> TouchType.Up:
<span class="hljs-keyword">case</span> TouchType.Cancel: {
<span class="hljs-comment">// if(!this.scroller.isAtEnd() && this.scroller.currentOffset().yOffset>0){</span>
<span class="hljs-comment">// this.hitTestMode = HitTestMode.None</span>
<span class="hljs-comment">// }else if(this.offsetY >0 ){</span>
<span class="hljs-comment">// this.hitTestMode = HitTestMode.Block</span>
<span class="hljs-comment">// }else{</span>
<span class="hljs-keyword">this</span>.hitTestMode = HitTestMode.Default
<span class="hljs-comment">// }</span>
<span class="hljs-comment">// if (this.scrollUp && !this.scroller.isAtEnd() || !this.scrollUp && this.scroller.currentOffset()</span>
<span class="hljs-comment">// .yOffset > 0) {</span>
<span class="hljs-comment">// this.hitTestMode = HitTestMode.Default</span>
<span class="hljs-comment">// } else {</span>
<span class="hljs-comment">// this.hitTestMode = HitTestMode.Block</span>
<span class="hljs-comment">// }</span>
<span class="hljs-keyword">if</span> (<span class="hljs-built_in">Math</span>.abs(diff) > <span class="hljs-number">0</span>) {
animateTo({ curve: curves.springMotion() }, () => {
<span class="hljs-keyword">if</span> (diff > <span class="hljs-keyword">this</span>.headerHeight) {
<span class="hljs-keyword">this</span>.state = DSRefreshState.Refresh
<span class="hljs-keyword">this</span>.offsetY = <span class="hljs-keyword">this</span>.headerHeight
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.onRefresh != <span class="hljs-literal">undefined</span>) {
<span class="hljs-keyword">this</span>.onRefresh()
}
setTimeout(() => {
<span class="hljs-keyword">this</span>.refreshFinish()
}, <span class="hljs-number">3000</span>)
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (diff < -<span class="hljs-keyword">this</span>.footerHeight) {
<span class="hljs-keyword">this</span>.state = DSRefreshState.Load
<span class="hljs-keyword">this</span>.offsetY = -<span class="hljs-keyword">this</span>.footerHeight
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.onLoadMore != <span class="hljs-literal">undefined</span>) {
<span class="hljs-keyword">this</span>.onLoadMore()
}
setTimeout(() => {
<span class="hljs-keyword">this</span>.refreshFinish()
}, <span class="hljs-number">1000</span>)
} <span class="hljs-keyword">else</span> {
<span class="hljs-keyword">this</span>.offsetY = <span class="hljs-number">0</span>
}
})
}
<span class="hljs-keyword">break</span>
}
}
<span class="hljs-keyword">this</span>.lastX = touch.x
<span class="hljs-keyword">this</span>.lastY = touch.y
})
.width(MATCH_PARENT)
.height(MATCH_PARENT)
.offset({ y: <span class="hljs-keyword">this</span>.offsetY })
.animation({
curve: curves.springMotion(), onFinish: () => {
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.state != DSRefreshState.Finish) {
<span class="hljs-keyword">return</span>
}
<span class="hljs-keyword">this</span>.state = DSRefreshState.None
}
})
.height(MATCH_PARENT)
}
private refreshFinish() {
this.state = DSRefreshState.Finish
this.offsetY = 0
}
}
export enum DSRefreshState {
None,
Refresh,
Load,
Finish
}
<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>
更多关于HarmonyOS 鸿蒙Next hitTestMode 问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS 鸿蒙Next hitTestMode 问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
针对HarmonyOS 鸿蒙Next中的hitTestMode问题,以下是一些专业解答:
在HarmonyOS 鸿蒙Next中,hitTestBehavior属性用于设置组件的触摸测试类型,该属性影响组件的触摸测试收集结果,进而决定后续的触屏事件分发。hitTestBehavior属性的可选值包括:
- Default:默认触摸测试效果,自身和子节点都响应触摸测试,但会阻塞兄弟节点的触摸测试。
- Block:自身响应触摸测试,阻塞子节点和兄弟节点的触摸测试。
- Transparent:自身和子节点都响应触摸测试,不会阻塞兄弟节点的触摸测试。
- None:自身不响应触摸测试,不会阻塞子节点和兄弟节点的触摸测试。
开发者可以根据实际需求,为组件设置合适的hitTestBehavior值,以实现期望的触摸事件处理逻辑。
如果在使用hitTestBehavior时遇到问题,建议检查以下几点:
- 确保API版本支持该属性(从API Version 9开始支持)。
- 检查组件的嵌套关系和触摸区域是否有重叠。
- 确认是否有其他触摸事件监听器影响了事件的分发。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。