HarmonyOS鸿蒙Next中ArkUI识别手指的触摸方向失败

HarmonyOS鸿蒙Next中ArkUI识别手指的触摸方向失败 也不是说完全失败就是两个if判断放在一起就只能识别一个

cke_3701.png这是方法

cke_5282.png

可是就运行这个方法就能识别手指的左或右

cke_17154.png

这是我的完整的代码

import {框架, 布局} from './框架';

@Entry
@ComponentV2
struct Index_o2 {


  @Local 框架长宽:框架=new 框架(0, 0);
  @Local 上组件:布局=new 布局(0, 0)
  @Local 中组件:布局=new 布局(0, 0)
  @Local 下组件:布局=new 布局(0, 0)
  build() {
    Column(){

      上组件({上组件:this.上组件})

      中组件({中组件:this.中组件})

      下组件({下组件:this.下组件})

    }
    .width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Center)  // 水平居中
    .justifyContent(FlexAlign.Center)
    .onSizeChange((框架长宽旧值: SizeOptions, 框架长宽新值: SizeOptions) => {
      this.上组件.宽=框架长宽新值.width as number*1;
      this.上组件.高=框架长宽新值.height as number*0.1;
      this.中组件.宽=框架长宽新值.width as number*1;
      this.中组件.高=框架长宽新值.height as number*0.65;
      this.下组件.宽=框架长宽新值.width as number*1;
      this.下组件.高=框架长宽新值.height as number*0.25;
    })
  }
}
@ComponentV2
struct 上组件{
  @Param @Require 上组件!:布局
  build() {
    Row(){
      //上
    }
    .backgroundColor(Color.Red)
    .width(this.上组件.宽)
    .height(this.上组件.高)
    .onTouch((手指触摸事件:TouchEvent) => {

    })
  }
}
@ComponentV2
struct 中组件{
  @Param @Require 中组件!:布局
  @Local 左组件:布局=new 布局(0, 0)
  @Local 右组件:布局=new 布局(0, 0)
  build() {
    Row(){
      左组件({左组件:this.左组件,右组件:this.右组件})
      右组件({右组件:this.右组件,左组件:this.左组件})
    }
    .border({
      width: {top:2, bottom:2},
      color: Color.Black,
      style: BorderStyle.Dashed
    })
    .width(this.中组件.宽)
    .height(this.中组件.高)
    .onSizeChange((框架长宽旧值: SizeOptions, 框架长宽新值: SizeOptions) => {
      this.左组件.宽=框架长宽新值.width as number *0.4
      this.左组件.初始宽=框架长宽新值.width as number *0.4
      this.左组件.高=框架长宽新值.height as number
      this.左组件.设置父布局宽(框架长宽新值.width as number)
      this.右组件.宽=框架长宽新值.width as number *0.6
      this.右组件.初始宽=框架长宽新值.width as number *0.6
      this.右组件.高=框架长宽新值.height as number
      this.右组件.设置父布局宽(框架长宽新值.width as number)
    })
  }
}
@ComponentV2
struct 左组件{
  @Param @Require 左组件!:布局
  @Param @Require 右组件!:布局
  build() {
    Row(){
      //左
    }
    .backgroundColor(Color.Green)
    .border({
      width: {right:2},
      color: Color.Black,
      style: BorderStyle.Dashed
    })
    .width(this.左组件.宽)
    .height(this.左组件.高)
    .onMouse((事件) => {

    })
/*
    .onTouch((手指触摸事件)=>{
      let 获取的手指:TouchObject[]=手指触摸事件.touches
      if(获取的手指[0].type==TouchType.Down&&this.左组件.手指触摸的第一次甄别==0){
        this.左组件.手指触摸初的始位置=获取的手指[0].x
        this.左组件.手指触摸的第一次甄别=1;
      }

      if(this.左组件.组件边缘判别('右', 20)){
        if(获取的手指[0].type==TouchType.Move){
          this.左组件.宽=获取的手指[0].x+(this.左组件.初始宽-this.左组件.手指触摸初的始位置)
          this.右组件.宽=this.左组件.返回父布局宽()-this.左组件.宽
        }
      }

      if(获取的手指[0].type==TouchType.Up){
        this.左组件.手指触摸的第一次甄别=0;
        this.左组件.初始宽=this.左组件.宽;
      }
    })
*/
  }
}
@ComponentV2
struct 右组件{
  @Param @Require 右组件!:布局
  @Param @Require 左组件!:布局
  build() {
    Row(){
      //右
    }
    .backgroundColor(Color.Orange)
    .width(this.右组件.宽)
    .height(this.右组件.高)

    .onTouch((手指触摸事件)=>{
      let 获取的手指:TouchObject[]=手指触摸事件.touches
      if(获取的手指[0].type==TouchType.Down&&this.右组件.手指触摸的第一次甄别==0){
        this.右组件.手指触摸初的始位置=获取的手指[0].x
        this.右组件.手指触摸的第一次甄别=1;
        this.右组件.横轴=获取的手指[0].x
        this.右组件.纵轴=获取的手指[0].y
      }

      /*
      if(this.右组件.识别手指滑动的方位('横轴', 获取的手指[0].x, 获取的手指[0].y)==='左'){
        console.error('左')
      }

      if(this.右组件.识别手指滑动的方位('横轴', 获取的手指[0].x, 获取的手指[0].y)==='右'){
        console.error('右')
      }
      */

      console.error(this.右组件.识别手指滑动的方位('横轴', 获取的手指[0].x, 获取的手指[0].y))







      /*
      if(this.右组件.组件边缘判别('左', 20)&&this.右组件.组件大小限制('宽', this.右组件.返回父布局宽()*0.8, this.右组件.返回父布局宽()*0.2)){
        if(获取的手指[0].type==TouchType.Move){
          this.左组件.宽=(this.左组件.初始宽+获取的手指[0].x)-this.右组件.手指触摸初的始位置
          this.右组件.宽=this.左组件.返回父布局宽()-this.左组件.宽
        }
     }
     */


      if(获取的手指[0].type==TouchType.Up){
        this.右组件.手指触摸的第一次甄别=0;
        this.左组件.初始宽=this.左组件.宽;
      }
    })

  }
}
@ComponentV2
struct 下组件{
  @Param @Require 下组件!:布局
  build() {
    Row(){
      //下
    }
    .backgroundColor(Color.Brown)
    .width(this.下组件.宽)
    .height(this.下组件.高)
    .onTouch((手指触摸事件:TouchEvent) => {
      let 获取的手指:TouchObject[]=手指触摸事件.touches
      if(获取的手指[0].type==TouchType.Down&&this.下组件.手指触摸的第一次甄别==0){
        this.下组件.手指触摸初的始位置=获取的手指[0].y
        this.下组件.手指触摸的第一次甄别=1;
      }
      if(获取的手指[0].type==TouchType.Up){
        this.下组件.手指触摸的第一次甄别=0;
      }

      if(获取的手指[0].type==TouchType.Move){

      }
    })
  }

}



@ObservedV2
export class  框架 {
    @Trace 宽:number=0;
    @Trace 初始宽:number=0;
    @Trace 高:number=0;
    @Trace 初始高:number=0;


    @Trace 手指触摸的第一次甄别:number=0;
    @Trace 手指触摸初的始位置:number=0;
  constructor(宽: number, c: number) {
    this.宽 = 宽;
    this.高 = 宽;
  }
  public 布局边缘甄别():boolean{

    return false;
  }
 }

export class  布局 extends 框架 {
  private 父布局宽:number=0;
  private 父布局高:number=0;
  public 横轴:number=0;
  public 纵轴:number=0;
  public 方位真假:boolean=false;
  constructor(宽: number, 高: number) {
    super(宽, 高)
  }
  public 设置父布局宽(宽:number):void{
    this.父布局宽=宽;
  }
  public 设置父布局高(高:number):void{
    this.父布局高=高;
  }
  public 返回父布局宽():number{
    return this.父布局宽
  }
  public 返回父布局高():number{
    return this.父布局高
  }
  public 组件大小限制(限制的宽或高:string, 限制的最大值:number, 限制的最小值:number):boolean{
    if(限制的宽或高==='宽'){
      if(this.宽>限制的最小值&&this.宽<限制的最大值){
        return true;
      }
    }

    if(限制的宽或高==='高'){
      if(this.高>限制的最小值&&this.高<限制的最大值){
        return true;
      }
    }

    return false;

  }

  public 组件边缘判别(组件边缘方位:string,阈值:number):boolean{
    if(组件边缘方位==='左'){
      if(this.手指触摸初的始位置>0&&this.手指触摸初的始位置<阈值){
        return true;
      }
    }
    /*
     if(this.左组件.手指触摸初的始位置>(this.左组件.初始宽-10)&&this.左组件.手指触摸初的始位置<this.左组件.初始宽){
        if(获取的手指[0].type==TouchType.Move){
          this.左组件.宽=获取的手指[0].x+(this.左组件.初始宽-this.左组件.手指触摸初的始位置)
          this.右组件.宽=this.左组件.返回父布局宽()-this.左组件.宽
        }
      }
      */

    if(组件边缘方位==='右'){
      if(this.手指触摸初的始位置>(this.初始宽-阈值)&&this.手指触摸初的始位置<this.初始宽){
        return true;
      }

      /*
       if(this.右组件.手指触摸初的始位置>0&&this.右组件.手指触摸初的始位置<10){
       if(获取的手指[0].type==TouchType.Move){
       this.左组件.宽=(this.左组件.初始宽+获取的手指[0].x)-this.右组件.手指触摸初的始位置
       this.右组件.宽=this.左组件.返回父布局宽()-this.左组件.宽
       }
       }
       */
    }
    return false;
  }

  public 识别手指滑动的方位(横轴或纵轴:string, 获取手指的横轴:number, 获取手指的纵轴:number):string{
    if(横轴或纵轴==='横轴'){
      if(this.横轴<获取手指的横轴){
        this.横轴=获取手指的横轴
        return '右'
      }
      if(this.横轴>获取手指的横轴){
        this.横轴=获取手指的横轴
        return '左'
      }
    }

    if(横轴或纵轴==='纵轴'){
      if(this.纵轴<获取手指的纵轴){
        this.纵轴=获取手指的纵轴
        return '下'
      }
      if(this.纵轴>获取手指的纵轴){
        this.纵轴=获取手指的纵轴
        return '上'
      }
    }
    return '不动'

  }

}

哪位大神帮我看看是怎么个事


更多关于HarmonyOS鸿蒙Next中ArkUI识别手指的触摸方向失败的实战教程也可以访问 https://www.itying.com/category-93-b0.html

10 回复

开发者您好,定位问题是由于调用了两次识别手指滑动方法。第一个if判断调用识别手指滑动方法时已经将获取手指的横轴的值赋值给this.横轴,导致在第二个if判断调用识别手指滑动方法时由于this.横轴===获取手指的横轴始终成立,不符合所有if场景,产生了第二个if判断没有运行的错觉。无需调用两次识别手指滑动方法,只需调用一次识别手指滑动方法获取返回值,然后进行if判断即可。

更多关于HarmonyOS鸿蒙Next中ArkUI识别手指的触摸方向失败的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


开发者您好,如以上方案无法解决问题请及时反馈。

太厉害了,中英混合编程,没见到你的帖子之前还不知道鸿蒙支持中文编程了。

是不是对中文编程有深深的鄙视😒,

这倒没有,我一般用拼音+外语混合编程,因为中文汉字编程以及中文路径之前在很多语言不支持,习惯了。

谢谢大神在百忙之中回答我的问题,是我大总了没有在问题中详细的说明我的想法,让大神白白的浪费了许多时间,对不起。。。。。。

我的意思是在右组件中运行这一段代码

cke_138.png

可以完全实现我想要的效果

你看。。。。当我在右组件中向左滑动手指在log中就能打印 “左”

cke_396.png

当我在右组件中向右滑动手指在log中就能打印 “右”

cke_873.png

当我在右组件中向按信手指不动在log中就能打印 “不动”

cke_1298.png

可是当我运行这一段代码效果就完全不一样了

cke_110894.png

按道理来说它们运行的都是同一个方法

this.右组件.识别手指滑动的方位('横轴', 获取的手指[0].x, 获取的手指[0].y)

可为什么只能判断出向“右”滑动手指

向“左”滑动手指 就判断不出来

你看 当我向右滑动在log中就能显示出来

cke_1798.png

当我向左滑动在log中就不能显示出来

也就是说第二个 if()语句 没有执行

cke_2446.png

按道理 右 和 左 都能判断的

去掉您的代码中的注释,触摸方向识别失败的根本原因在于只调用了单一轴向的判断,而您可能期望同时识别横轴和纵轴的方向变化。下面详细分析问题所在,并给出改进建议。


1. 当前代码的逻辑分析

右组件onTouch 事件中,您只调用了一次 识别手指滑动的方位 方法,且参数固定为 '横轴'

console.error(this.右组件.识别手指滑动的方位('横轴', 获取的手指[0].x, 获取的手指[0].y))

因此,每次触摸事件(DownMoveUp)都仅比较横轴坐标,并更新 this.右组件.横轴。纵轴坐标 this.右组件.纵轴 仅在 Down 时被记录,之后从未更新,所以纵轴方向永远无法被识别。

识别手指滑动的方位 方法内部有两个 if 分支(横轴和纵轴),但执行哪个分支完全取决于传入的第一个参数。您只传入了 '横轴',因此纵轴分支永远不会执行,这就是“两个 if 判断放在一起却只能识别一个”的直接原因。


2. 隐含的其他问题

即使您尝试在同一个 onTouch 中同时调用两次(一次 '横轴',一次 '纵轴'),也会遇到状态更新的问题:

  • 第一次调用(横轴)会更新 this.右组件.横轴 为当前 x
  • 第二次调用(纵轴)会更新 this.右组件.纵轴 为当前 y

但若两次调用顺序固定,且每次 Move 事件都执行,逻辑上是可行的。不过,您目前的代码中并没有这样做,所以纵轴方向始终未参与比较。

此外,下组件onTouch 中虽然记录了 DownUp,但完全没有调用任何方向识别逻辑,所以也无法识别上下滑动。


3. 改进建议

方案一:分别调用两次,分别获取横纵方向

onTouchMove 分支中,分别调用两次方法,并分别处理返回的方向:

if (获取的手指[0].type == TouchType.Move) {
    let 横向方向 = this.右组件.识别手指滑动的方位('横轴', 获取的手指[0].x, 获取的手指[0].y);
    let 纵向方向 = this.右组件.识别手指滑动的方位('纵轴', 获取的手指[0].x, 获取的手指[0].y);
    console.log(`横向:${横向方向},纵向:${纵向方向}`);
}

注意:Down 事件中必须同时记录横轴和纵轴的初始值,Move 中每次都要更新两个轴的值。

方案二:重构识别方法,一次性返回两个方向

修改 识别手指滑动的方位 方法,使其同时比较并更新横纵坐标,返回一个包含两个方向的对象:

public 识别手指滑动方向(x: number, y: number): { x: '左'|'右'|'不动', y: '上'|'下'|'不动' } {
    let xDir = '不动';
    let yDir = '不动';
    if (this.横轴 < x) {
        xDir = '右';
        this.横轴 = x;
    } else if (this.横轴 > x) {
        xDir = '左';
        this.横轴 = x;
    }
    if (this.纵轴 < y) {
        yDir = '下';
        this.纵轴 = y;
    } else if (this.纵轴 > y) {
        yDir = '上';
        this.纵轴 = y;
    }
    return { x: xDir, y: yDir };
}

然后在 onTouchMove 中调用一次即可获得两个方向。


4. 额外注意事项

  • 触摸事件中 touches[0] 代表第一个触摸点,但如果您支持多点触控,需要更复杂的处理。
  • 您的 布局 类继承自 框架,且 框架 中的 手指触摸的第一次甄别 等属性在多个组件实例中共享,但当前逻辑是每个组件独立使用自己的实例,所以没有共享问题。
  • 右组件Up 事件中,您重置了 this.右组件.手指触摸的第一次甄别 并更新了 this.左组件.初始宽,这看起来像是用于调整左右组件宽度,但方向识别失败与此无关。

大神我回错了回成了我自己了 不好意思 本来是要回你的我想让你帮我看看

在HarmonyOS Next中,ArkUI识别触摸方向失败通常与手势事件处理有关。请检查PanGestureTouchEvent事件回调中的offsetXoffsetY参数,这些参数用于计算移动方向。确保在组件上正确绑定了手势事件,如.gesture(PanGesture(...).onActionUpdate((event: GestureEvent) => { ... }))。方向判断逻辑需基于这些偏移值的正负和大小来实现。

问题出在识别手指滑动的方位方法的逻辑上。你每次调用这个方法时,都会更新this.横轴的值,这导致连续判断时方向识别失效。

具体分析:

  1. 右组件onTouch中,你连续调用了两次识别手指滑动的方位方法(虽然第二次被注释了)。
  2. 第一次调用时,如果手指向右滑动,方法返回"右",但同时this.横轴被更新为新的x坐标。
  3. 紧接着第二次调用时,由于this.横轴已经是新的x坐标,与传入的获取手指的横轴相同,方法返回"不动"。

解决方案:

  • 不要在识别手指滑动的方位方法内部更新this.横轴this.纵轴
  • 改为在TouchType.Move事件中计算方向,并单独更新坐标值。

修正后的方法示例:

public 识别手指滑动的方位(横轴或纵轴:string, 获取手指的横轴:number, 获取手指的纵轴:number):string{
  if(横轴或纵轴==='横轴'){
    if(this.横轴 < 获取手指的横轴){
      return '右'
    }
    if(this.横轴 > 获取手指的横轴){
      return '左'
    }
  }
  
  if(横轴或纵轴==='纵轴'){
    if(this.纵轴 < 获取手指的纵轴){
      return '下'
    }
    if(this.纵轴 > 获取手指的纵轴){
      return '上'
    }
  }
  return '不动'
}

然后在onTouch事件中:

.onTouch((手指触摸事件)=>{
  let 获取的手指:TouchObject[]=手指触摸事件.touches
  if(获取的手指[0].type==TouchType.Down&&this.右组件.手指触摸的第一次甄别==0){
    this.右组件.手指触摸初的始位置=获取的手指[0].x
    this.右组件.手指触摸的第一次甄别=1;
    this.右组件.横轴=获取的手指[0].x
    this.右组件.纵轴=获取的手指[0].y
  }

  if(获取的手指[0].type==TouchType.Move){
    let 方向 = this.右组件.识别手指滑动的方位('横轴', 获取的手指[0].x, 获取的手指[0].y)
    console.error(方向)
    // 更新坐标值
    this.右组件.横轴=获取的手指[0].x
    this.右组件.纵轴=获取的手指[0].y
  }

  if(获取的手指[0].type==TouchType.Up){
    this.右组件.手指触摸的第一次甄别=0;
    this.左组件.初始宽=this.左组件.宽;
  }
})

这样修改后,方向识别就能正常工作了。

回到顶部